ts-class-to-openapi 1.3.2 → 1.3.4

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 (45) hide show
  1. package/dist/index.cjs +976 -0
  2. package/dist/index.d.cts +56 -0
  3. package/dist/index.d.mts +58 -0
  4. package/dist/index.mjs +951 -0
  5. package/package.json +32 -28
  6. package/dist/__test__/entities/additional-test-classes.d.ts +0 -12
  7. package/dist/__test__/entities/circular-reference-cases.d.ts +0 -1
  8. package/dist/__test__/entities/circular-reference-classes.d.ts +0 -110
  9. package/dist/__test__/entities/collision/arrays/number-array.d.ts +0 -3
  10. package/dist/__test__/entities/collision/arrays/string-array.d.ts +0 -3
  11. package/dist/__test__/entities/collision/number-props/same-name.d.ts +0 -5
  12. package/dist/__test__/entities/collision/string-props/same-name.d.ts +0 -5
  13. package/dist/__test__/entities/collision/throwing/class-a.d.ts +0 -4
  14. package/dist/__test__/entities/collision/throwing/class-b.d.ts +0 -4
  15. package/dist/__test__/entities/complex-circular-dependencies.d.ts +0 -71
  16. package/dist/__test__/entities/decorated-classes.d.ts +0 -54
  17. package/dist/__test__/entities/deep-nested-classes.d.ts +0 -1
  18. package/dist/__test__/entities/enum-classes.d.ts +0 -38
  19. package/dist/__test__/entities/evaluation/generics.d.ts +0 -6
  20. package/dist/__test__/entities/evaluation/modifiers.d.ts +0 -7
  21. package/dist/__test__/entities/generic-circular-classes.d.ts +0 -57
  22. package/dist/__test__/entities/nested-classes.d.ts +0 -70
  23. package/dist/__test__/entities/nested-reuse-classes.d.ts +0 -43
  24. package/dist/__test__/entities/pure-classes.d.ts +0 -37
  25. package/dist/__test__/entities/schema-validation-classes.d.ts +0 -35
  26. package/dist/__test__/index.d.ts +0 -8
  27. package/dist/__test__/test.d.ts +0 -1
  28. package/dist/__test__/testCases/collision-advanced.test.d.ts +0 -1
  29. package/dist/__test__/testCases/collision.test.d.ts +0 -1
  30. package/dist/__test__/testCases/decorated-classes.test.d.ts +0 -1
  31. package/dist/__test__/testCases/edge-cases.test.d.ts +0 -1
  32. package/dist/__test__/testCases/enum-properties.test.d.ts +0 -1
  33. package/dist/__test__/testCases/generics-and-modifiers.test.d.ts +0 -1
  34. package/dist/__test__/testCases/nested-classes.test.d.ts +0 -1
  35. package/dist/__test__/testCases/nested-reuse.test.d.ts +0 -1
  36. package/dist/__test__/testCases/pure-classes.test.d.ts +0 -1
  37. package/dist/__test__/testCases/schema-validation.test.d.ts +0 -1
  38. package/dist/index.d.ts +0 -3
  39. package/dist/index.esm.js +0 -1230
  40. package/dist/index.js +0 -1232
  41. package/dist/run.d.ts +0 -1
  42. package/dist/run.js +0 -1319
  43. package/dist/transformer.d.ts +0 -5
  44. package/dist/transformer.fixtures.d.ts +0 -175
  45. package/dist/types.d.ts +0 -97
package/dist/index.cjs ADDED
@@ -0,0 +1,976 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ let typescript = require("typescript");
25
+ typescript = __toESM(typescript);
26
+ let path = require("path");
27
+ path = __toESM(path);
28
+ //#region src/transformer.fixtures.ts
29
+ const constants = {
30
+ TS_CONFIG_DEFAULT_PATH: path.default.resolve(process.cwd(), "tsconfig.json"),
31
+ jsPrimitives: {
32
+ String: {
33
+ type: "String",
34
+ value: "string"
35
+ },
36
+ Any: {
37
+ type: "Any",
38
+ value: "string"
39
+ },
40
+ Unknown: {
41
+ type: "Unknown",
42
+ value: "string"
43
+ },
44
+ Number: {
45
+ type: "Number",
46
+ value: "number",
47
+ format: "integer"
48
+ },
49
+ Boolean: {
50
+ type: "Boolean",
51
+ value: "boolean"
52
+ },
53
+ Symbol: {
54
+ type: "Symbol",
55
+ value: "string"
56
+ },
57
+ BigInt: {
58
+ type: "BigInt",
59
+ value: "integer",
60
+ format: "int64"
61
+ },
62
+ null: {
63
+ type: "null",
64
+ value: "null"
65
+ },
66
+ Object: {
67
+ type: "Object",
68
+ value: "object"
69
+ },
70
+ Array: {
71
+ type: "Array",
72
+ value: "array"
73
+ },
74
+ Date: {
75
+ type: "Date",
76
+ value: "string",
77
+ format: "date-time"
78
+ },
79
+ Function: {
80
+ type: "Function",
81
+ value: "function"
82
+ },
83
+ Buffer: {
84
+ type: "Buffer",
85
+ value: "string",
86
+ format: "binary"
87
+ },
88
+ Uint8Array: {
89
+ type: "Uint8Array",
90
+ value: "string",
91
+ format: "binary"
92
+ },
93
+ UploadFile: {
94
+ type: "UploadFile",
95
+ value: "string",
96
+ format: "binary"
97
+ },
98
+ UploadFileDto: {
99
+ type: "UploadFileDto",
100
+ value: "string",
101
+ format: "binary"
102
+ },
103
+ File: {
104
+ type: "File",
105
+ value: "string",
106
+ format: "binary"
107
+ }
108
+ },
109
+ validatorDecorators: {
110
+ Length: {
111
+ name: "Length",
112
+ type: "string"
113
+ },
114
+ MinLength: {
115
+ name: "MinLength",
116
+ type: "string"
117
+ },
118
+ MaxLength: {
119
+ name: "MaxLength",
120
+ type: "string"
121
+ },
122
+ IsInt: {
123
+ name: "IsInt",
124
+ type: "integer",
125
+ format: "int32"
126
+ },
127
+ IsNumber: {
128
+ name: "IsNumber",
129
+ type: "integer",
130
+ format: "integer"
131
+ },
132
+ IsString: {
133
+ name: "IsString",
134
+ type: "string",
135
+ format: "string"
136
+ },
137
+ IsPositive: {
138
+ name: "IsPositive",
139
+ type: "integer"
140
+ },
141
+ IsDate: {
142
+ name: "IsDate",
143
+ type: "string",
144
+ format: "date-time"
145
+ },
146
+ IsEmail: {
147
+ name: "IsEmail",
148
+ type: "string",
149
+ format: "email"
150
+ },
151
+ IsNotEmpty: { name: "IsNotEmpty" },
152
+ IsOptional: { name: "IsOptional" },
153
+ IsBoolean: {
154
+ name: "IsBoolean",
155
+ type: "boolean"
156
+ },
157
+ IsArray: {
158
+ name: "IsArray",
159
+ type: "array"
160
+ },
161
+ Min: { name: "Min" },
162
+ Max: { name: "Max" },
163
+ ArrayNotEmpty: { name: "ArrayNotEmpty" },
164
+ ArrayMaxSize: { name: "ArrayMaxSize" },
165
+ ArrayMinSize: { name: "ArrayMinSize" },
166
+ IsEnum: {
167
+ name: "IsEnum",
168
+ type: "string"
169
+ }
170
+ },
171
+ tsUtilityTypes: {
172
+ Partial: {
173
+ type: "Partial",
174
+ value: "Partial<"
175
+ },
176
+ Required: {
177
+ type: "Required",
178
+ value: "Required<"
179
+ }
180
+ }
181
+ };
182
+ //#endregion
183
+ //#region src/transformer.ts
184
+ var SchemaTransformer = class SchemaTransformer {
185
+ static instance = null;
186
+ program;
187
+ checker;
188
+ classCache = /* @__PURE__ */ new WeakMap();
189
+ maxCacheSize;
190
+ autoCleanup;
191
+ classFileIndex = /* @__PURE__ */ new Map();
192
+ constructor(tsConfigPath = constants.TS_CONFIG_DEFAULT_PATH, options = {}) {
193
+ this.maxCacheSize = options.maxCacheSize ?? 100;
194
+ this.autoCleanup = options.autoCleanup ?? true;
195
+ const { config, error } = typescript.default.readConfigFile(tsConfigPath || "tsconfig.json", typescript.default.sys.readFile);
196
+ if (error) {
197
+ console.log((/* @__PURE__ */ new Error(`Error reading tsconfig file: ${error.messageText}`)).message);
198
+ throw new Error(`Error reading tsconfig file: ${error.messageText}`);
199
+ }
200
+ const { options: tsOptions, fileNames } = typescript.default.parseJsonConfigFileContent(config, typescript.default.sys, "./");
201
+ this.program = typescript.default.createProgram(fileNames, tsOptions);
202
+ this.checker = this.program.getTypeChecker();
203
+ this.program.getSourceFiles().forEach((sf) => {
204
+ sf.statements.forEach((stmt) => {
205
+ if (typescript.default.isClassDeclaration(stmt) && stmt.name) {
206
+ const name = stmt.name.text;
207
+ const entry = this.classFileIndex.get(name) || [];
208
+ entry.push({
209
+ sourceFile: sf,
210
+ node: stmt
211
+ });
212
+ this.classFileIndex.set(name, entry);
213
+ }
214
+ });
215
+ });
216
+ }
217
+ getPropertiesByClassDeclaration(classNode, visitedDeclarations = /* @__PURE__ */ new Set(), genericTypeMap = /* @__PURE__ */ new Map()) {
218
+ if (visitedDeclarations.has(classNode)) return [];
219
+ visitedDeclarations.add(classNode);
220
+ if (!classNode.heritageClauses) return this.getPropertiesByClassMembers(classNode.members, classNode, genericTypeMap);
221
+ else {
222
+ const heritageClause = classNode.heritageClauses[0];
223
+ if (heritageClause && heritageClause.token === typescript.default.SyntaxKind.ExtendsKeyword) {
224
+ var _symbol$declarations;
225
+ const type = heritageClause.types[0];
226
+ let properties = [];
227
+ let baseProperties = [];
228
+ if (!type) return [];
229
+ const symbol = this.checker.getSymbolAtLocation(type.expression);
230
+ if (!symbol) return [];
231
+ const declaration = (_symbol$declarations = symbol.declarations) === null || _symbol$declarations === void 0 ? void 0 : _symbol$declarations[0];
232
+ if (declaration && typescript.default.isClassDeclaration(declaration)) {
233
+ const newGenericTypeMap = /* @__PURE__ */ new Map();
234
+ if (declaration.typeParameters && type.typeArguments) declaration.typeParameters.forEach((param, index) => {
235
+ const arg = type.typeArguments[index];
236
+ if (arg) {
237
+ const resolvedArg = this.getTypeNodeToString(arg, genericTypeMap);
238
+ newGenericTypeMap.set(param.name.text, resolvedArg);
239
+ }
240
+ });
241
+ baseProperties = this.getPropertiesByClassDeclaration(declaration, visitedDeclarations, newGenericTypeMap);
242
+ }
243
+ properties = this.getPropertiesByClassMembers(classNode.members, classNode, genericTypeMap);
244
+ return baseProperties.concat(properties);
245
+ } else return this.getPropertiesByClassMembers(classNode.members, classNode, genericTypeMap);
246
+ }
247
+ }
248
+ getPropertiesByClassMembers(members, parentClassNode, genericTypeMap = /* @__PURE__ */ new Map()) {
249
+ const properties = [];
250
+ for (const member of members) {
251
+ var _member$name;
252
+ if (typescript.default.isPropertyDeclaration(member) && member.name && ((_member$name = member.name) === null || _member$name === void 0 ? void 0 : _member$name.text)) {
253
+ var _typeArguments;
254
+ if (member.modifiers) {
255
+ if (member.modifiers.some((m) => m.kind === typescript.default.SyntaxKind.PrivateKeyword || m.kind === typescript.default.SyntaxKind.ProtectedKeyword)) continue;
256
+ }
257
+ const propertyName = member.name.text;
258
+ const type = this.getPropertyType(member, genericTypeMap);
259
+ const decorators = this.extractDecorators(member);
260
+ const isOptional = !!member.questionToken;
261
+ const isGeneric = this.isPropertyTypeGeneric(member);
262
+ const isEnum = this.isEnum(member);
263
+ const property = {
264
+ name: propertyName,
265
+ type,
266
+ decorators,
267
+ isOptional,
268
+ isGeneric,
269
+ originalProperty: member,
270
+ isPrimitive: this.isPrimitiveType(type) || isEnum,
271
+ isClassType: this.isClassType(member),
272
+ isArray: this.isArrayProperty(member),
273
+ isEnum,
274
+ isRef: false,
275
+ isTypeLiteral: this.isTypeLiteral(member)
276
+ };
277
+ if (property.isClassType) {
278
+ const declaration = this.getDeclarationProperty(property);
279
+ if (parentClassNode) {
280
+ if (declaration && declaration.name && this.checker.getSymbolAtLocation(declaration.name) === this.checker.getSymbolAtLocation(parentClassNode.name)) property.isRef = true;
281
+ }
282
+ }
283
+ if (property.isTypeLiteral && property.originalProperty.type && ((_typeArguments = property.originalProperty.type.typeArguments) === null || _typeArguments === void 0 ? void 0 : _typeArguments.length) === 1) {
284
+ const typeArguments = property.originalProperty.type.typeArguments;
285
+ if (typeArguments && typeArguments[0]) {
286
+ const firstTypeArg = typeArguments[0];
287
+ if (typescript.default.isTypeReferenceNode(firstTypeArg)) {
288
+ const symbol = this.checker.getTypeAtLocation(firstTypeArg).getSymbol();
289
+ if (symbol && symbol.declarations) {
290
+ const classDeclaration = symbol.declarations.find((decl) => typescript.default.isClassDeclaration(decl));
291
+ if (classDeclaration && typescript.default.isClassDeclaration(classDeclaration)) property.typeLiteralClassReference = classDeclaration;
292
+ }
293
+ }
294
+ }
295
+ }
296
+ properties.push(property);
297
+ }
298
+ }
299
+ return properties;
300
+ }
301
+ getPropertyType(property, genericTypeMap = /* @__PURE__ */ new Map()) {
302
+ if (property.type) return this.getTypeNodeToString(property.type, genericTypeMap);
303
+ const type = this.checker.getTypeAtLocation(property);
304
+ return this.getStringFromType(type);
305
+ }
306
+ getTypeNodeToString(typeNode, genericTypeMap = /* @__PURE__ */ new Map()) {
307
+ if (typescript.default.isTypeReferenceNode(typeNode) && typescript.default.isIdentifier(typeNode.typeName)) {
308
+ const typeName = typeNode.typeName.text;
309
+ if (genericTypeMap.has(typeName)) return genericTypeMap.get(typeName);
310
+ if (typeName.toLowerCase() === "uploadfile") return "UploadFile";
311
+ if (typeName.toLowerCase() === "uploadfiledto") return "UploadFileDto";
312
+ if (typeNode.typeArguments && typeNode.typeArguments.length > 0) {
313
+ const firstTypeArg = typeNode.typeArguments[0];
314
+ if (firstTypeArg && typescript.default.isTypeReferenceNode(firstTypeArg) && typescript.default.isIdentifier(firstTypeArg.typeName)) {
315
+ if (firstTypeArg.typeName.text.toLowerCase() === "uploadfile") return "UploadFile";
316
+ }
317
+ return this.resolveGenericType(typeNode);
318
+ }
319
+ return typeNode.typeName.text;
320
+ }
321
+ switch (typeNode.kind) {
322
+ case typescript.default.SyntaxKind.StringKeyword: return constants.jsPrimitives.String.type;
323
+ case typescript.default.SyntaxKind.NumberKeyword: return constants.jsPrimitives.Number.type;
324
+ case typescript.default.SyntaxKind.BooleanKeyword: return constants.jsPrimitives.Boolean.type;
325
+ case typescript.default.SyntaxKind.ArrayType:
326
+ const arrayType = typeNode;
327
+ return `${this.getTypeNodeToString(arrayType.elementType, genericTypeMap)}[]`;
328
+ case typescript.default.SyntaxKind.UnionType:
329
+ const types = typeNode.types.map((t) => this.getTypeNodeToString(t, genericTypeMap));
330
+ const meaningfulTypes = types.filter((t) => t !== "null" && t !== "undefined");
331
+ if (meaningfulTypes.length > 0 && meaningfulTypes[0]) return meaningfulTypes[0];
332
+ if (types.length > 0 && types[0]) return types[0];
333
+ return "object";
334
+ default:
335
+ const typeText = typeNode.getText();
336
+ if (genericTypeMap && genericTypeMap.has(typeText)) return genericTypeMap.get(typeText);
337
+ if (typeText.startsWith("Date")) return constants.jsPrimitives.Date.type;
338
+ if (typeText.includes("Buffer") || typeText.includes("Uint8Array")) return constants.jsPrimitives.Buffer.type;
339
+ return typeText;
340
+ }
341
+ }
342
+ resolveGenericType(typeNode) {
343
+ const typeName = typeNode.typeName.text;
344
+ const typeArguments = typeNode.typeArguments;
345
+ if (!typeArguments || typeArguments.length === 0) return typeName;
346
+ const type = this.checker.getTypeAtLocation(typeNode);
347
+ const resolvedType = this.getStringFromType(type);
348
+ if (resolvedType && resolvedType !== typeName && !resolvedType.includes("any")) return resolvedType;
349
+ return typeName;
350
+ }
351
+ getStringFromType(type) {
352
+ return this.checker.typeToString(type);
353
+ }
354
+ extractDecorators(member) {
355
+ const decorators = [];
356
+ if (member.modifiers) {
357
+ for (const modifier of member.modifiers) if (typescript.default.isDecorator(modifier) && typescript.default.isCallExpression(modifier.expression)) {
358
+ const decoratorName = this.getDecoratorName(modifier.expression);
359
+ const args = this.getDecoratorArguments(modifier.expression);
360
+ decorators.push({
361
+ name: decoratorName,
362
+ arguments: args
363
+ });
364
+ } else if (typescript.default.isDecorator(modifier) && typescript.default.isIdentifier(modifier.expression)) decorators.push({
365
+ name: modifier.expression.text,
366
+ arguments: []
367
+ });
368
+ }
369
+ return decorators;
370
+ }
371
+ getDecoratorName(callExpression) {
372
+ if (typescript.default.isIdentifier(callExpression.expression)) return callExpression.expression.text;
373
+ return "unknown";
374
+ }
375
+ getDecoratorArguments(callExpression) {
376
+ return callExpression.arguments.map((arg) => {
377
+ if (typescript.default.isNumericLiteral(arg)) return Number(arg.text);
378
+ if (typescript.default.isStringLiteral(arg)) return arg.text;
379
+ if (arg.kind === typescript.default.SyntaxKind.TrueKeyword) return true;
380
+ if (arg.kind === typescript.default.SyntaxKind.FalseKeyword) return false;
381
+ return arg;
382
+ });
383
+ }
384
+ getSafeDecoratorArgument(arg) {
385
+ if (arg && typeof arg === "object" && "kind" in arg) return arg.getText();
386
+ return arg;
387
+ }
388
+ isPropertyTypeGeneric(property) {
389
+ if (property.type && this.isGenericTypeFromNode(property.type)) return true;
390
+ try {
391
+ const type = this.checker.getTypeAtLocation(property);
392
+ return this.isGenericTypeFromSymbol(type);
393
+ } catch (error) {
394
+ console.warn("Error analyzing property type for generics:", error);
395
+ return false;
396
+ }
397
+ }
398
+ isGenericTypeFromNode(typeNode) {
399
+ if (typescript.default.isTypeReferenceNode(typeNode) && typeNode.typeArguments) return typeNode.typeArguments.length > 0;
400
+ if (typescript.default.isMappedTypeNode(typeNode)) return true;
401
+ if (typescript.default.isConditionalTypeNode(typeNode)) return true;
402
+ if (typescript.default.isIndexedAccessTypeNode(typeNode)) return true;
403
+ if (typescript.default.isTypeOperatorNode(typeNode)) return true;
404
+ return false;
405
+ }
406
+ isGenericTypeFromSymbol(type) {
407
+ if (this.isSimpleArrayType(type)) return false;
408
+ if (type.aliasTypeArguments && type.aliasTypeArguments.length > 0) return true;
409
+ if (type.typeArguments && type.typeArguments.length > 0) {
410
+ const symbol = type.getSymbol();
411
+ if (symbol && symbol.getName() === "Array") {
412
+ const elementType = type.typeArguments[0];
413
+ if (elementType) return this.isUtilityTypeFromType(elementType);
414
+ return false;
415
+ }
416
+ const elementType = type.typeArguments[0];
417
+ return this.isUtilityTypeFromType(elementType);
418
+ }
419
+ if (type.flags & typescript.default.TypeFlags.TypeParameter) return true;
420
+ if (type.flags & typescript.default.TypeFlags.Conditional) return true;
421
+ if (type.flags & typescript.default.TypeFlags.Index) return true;
422
+ if (type.flags & typescript.default.TypeFlags.IndexedAccess) return true;
423
+ const symbol = type.getSymbol();
424
+ if (symbol && symbol.declarations) for (const declaration of symbol.declarations) {
425
+ if (typescript.default.isTypeAliasDeclaration(declaration) && declaration.typeParameters) return true;
426
+ if (typescript.default.isInterfaceDeclaration(declaration) && declaration.typeParameters) return true;
427
+ if (typescript.default.isClassDeclaration(declaration) && declaration.typeParameters) return true;
428
+ }
429
+ return false;
430
+ }
431
+ isUtilityTypeFromType(type) {
432
+ if (!type.aliasSymbol) return false;
433
+ const aliasName = type.aliasSymbol.getName();
434
+ return [
435
+ "Partial",
436
+ "Required",
437
+ "Readonly",
438
+ "Pick",
439
+ "Omit",
440
+ "Record",
441
+ "Exclude",
442
+ "Extract",
443
+ "NonNullable"
444
+ ].includes(aliasName);
445
+ }
446
+ isSimpleArrayType(type) {
447
+ const symbol = type.getSymbol();
448
+ if (!symbol || symbol.getName() !== "Array") return false;
449
+ if (type.typeArguments && type.typeArguments.length === 1) {
450
+ const elementType = type.typeArguments[0];
451
+ if (!elementType) return false;
452
+ if (this.isUtilityTypeFromType(elementType)) return false;
453
+ if (elementType.typeArguments && elementType.typeArguments.length > 0) return false;
454
+ return true;
455
+ }
456
+ return false;
457
+ }
458
+ isPrimitiveType(typeName) {
459
+ const lowerTypeName = typeName.toLowerCase();
460
+ const primitiveTypes = [
461
+ constants.jsPrimitives.String.type.toLowerCase(),
462
+ constants.jsPrimitives.Number.type.toLowerCase(),
463
+ constants.jsPrimitives.Boolean.type.toLowerCase(),
464
+ constants.jsPrimitives.Date.type.toLowerCase(),
465
+ constants.jsPrimitives.Buffer.type.toLowerCase(),
466
+ constants.jsPrimitives.Uint8Array.type.toLowerCase(),
467
+ constants.jsPrimitives.File.type.toLowerCase(),
468
+ constants.jsPrimitives.UploadFile.type.toLowerCase(),
469
+ constants.jsPrimitives.UploadFileDto.type.toLowerCase(),
470
+ constants.jsPrimitives.BigInt.type.toLowerCase(),
471
+ constants.jsPrimitives.Symbol.type.toLowerCase(),
472
+ constants.jsPrimitives.null.type.toLowerCase(),
473
+ constants.jsPrimitives.Object.type.toLowerCase(),
474
+ constants.jsPrimitives.Array.type.toLowerCase(),
475
+ constants.jsPrimitives.Any.type.toLowerCase(),
476
+ constants.jsPrimitives.Unknown.type.toLowerCase()
477
+ ];
478
+ const primitivesArray = primitiveTypes.map((t) => t.concat("[]"));
479
+ return primitiveTypes.includes(lowerTypeName) || primitivesArray.includes(lowerTypeName);
480
+ }
481
+ static getInstance(tsConfigPath, options) {
482
+ if (!SchemaTransformer.instance) SchemaTransformer.instance = new SchemaTransformer(tsConfigPath, options);
483
+ return SchemaTransformer.instance;
484
+ }
485
+ getSourceFileByClass(cls, sourceOptions) {
486
+ const className = cls.name;
487
+ let matches = [];
488
+ if (sourceOptions === null || sourceOptions === void 0 ? void 0 : sourceOptions.isExternal) {
489
+ const sourceFiles = this.getFilteredSourceFiles(sourceOptions);
490
+ for (const sourceFile of sourceFiles) {
491
+ const node = sourceFile.statements.find((stmt) => typescript.default.isClassDeclaration(stmt) && stmt.name && stmt.name.text === className);
492
+ if (node) matches.push({
493
+ sourceFile,
494
+ node
495
+ });
496
+ }
497
+ } else {
498
+ matches = this.classFileIndex.get(className) || [];
499
+ if (sourceOptions === null || sourceOptions === void 0 ? void 0 : sourceOptions.filePath) matches = matches.filter((m) => m.sourceFile.fileName.includes(sourceOptions.filePath));
500
+ }
501
+ if (matches.length === 0) return;
502
+ if (matches.length === 1) return matches[0];
503
+ if (matches.length > 1 && !(sourceOptions === null || sourceOptions === void 0 ? void 0 : sourceOptions.filePath)) {
504
+ const bestMatch = this.findBestMatch(cls, matches);
505
+ if (bestMatch) return bestMatch;
506
+ const firstMatch = matches[0];
507
+ if (firstMatch) console.warn(`[ts-class-to-openapi] Warning: Found multiple classes with name '${className}'. Using the first one found in '${firstMatch.sourceFile.fileName}'. To resolve this collision, provide 'sourceOptions.filePath'.`);
508
+ }
509
+ return matches[0];
510
+ }
511
+ checkTypeMatch(value, typeNode) {
512
+ const runtimeType = typeof value;
513
+ if (runtimeType === "string" && typeNode.kind === typescript.default.SyntaxKind.StringKeyword) return true;
514
+ if (runtimeType === "number" && typeNode.kind === typescript.default.SyntaxKind.NumberKeyword) return true;
515
+ if (runtimeType === "boolean" && typeNode.kind === typescript.default.SyntaxKind.BooleanKeyword) return true;
516
+ if (Array.isArray(value) && typescript.default.isArrayTypeNode(typeNode)) {
517
+ if (value.length === 0) return true;
518
+ const firstItem = value[0];
519
+ const elementType = typeNode.elementType;
520
+ return this.checkTypeMatch(firstItem, elementType);
521
+ }
522
+ if (runtimeType === "object" && value !== null && !Array.isArray(value)) {
523
+ if (typescript.default.isTypeReferenceNode(typeNode) || typeNode.kind === typescript.default.SyntaxKind.ObjectKeyword) return true;
524
+ }
525
+ return false;
526
+ }
527
+ findBestMatch(cls, matches) {
528
+ let instance = {};
529
+ try {
530
+ instance = new cls();
531
+ } catch {
532
+ instance = {};
533
+ }
534
+ const instanceProperties = Object.keys(instance);
535
+ let matchesMap = {};
536
+ matches.forEach((match, index) => {
537
+ let fountProperties = 0;
538
+ match.node.members.map((member) => {
539
+ if (member.name && instanceProperties.includes(member.name.getText())) fountProperties++;
540
+ });
541
+ matchesMap[index] = fountProperties;
542
+ });
543
+ const maxMatches = Math.max(...Object.values(matchesMap));
544
+ return matches[Object.values(matchesMap).findIndex((value) => value === maxMatches)];
545
+ }
546
+ getFilteredSourceFiles(sourceOptions) {
547
+ if (sourceOptions === null || sourceOptions === void 0 ? void 0 : sourceOptions.isExternal) return this.program.getSourceFiles().filter((sf) => {
548
+ return sf.fileName.includes(sourceOptions.packageName) && (!sourceOptions.filePath || sf.fileName === sourceOptions.filePath);
549
+ });
550
+ return this.program.getSourceFiles().filter((sf) => {
551
+ if ((sourceOptions === null || sourceOptions === void 0 ? void 0 : sourceOptions.filePath) && !sf.fileName.includes(sourceOptions.filePath)) return false;
552
+ return true;
553
+ });
554
+ }
555
+ isEnum(propertyDeclaration) {
556
+ if (!propertyDeclaration.type) return false;
557
+ let typeNode = propertyDeclaration.type;
558
+ if (typescript.default.isArrayTypeNode(typeNode)) typeNode = typeNode.elementType;
559
+ if (typescript.default.isTypeReferenceNode(typeNode)) {
560
+ const type = this.checker.getTypeAtLocation(typeNode);
561
+ return !!(type.flags & typescript.default.TypeFlags.Enum) || !!(type.flags & typescript.default.TypeFlags.EnumLiteral);
562
+ }
563
+ return false;
564
+ }
565
+ isClassType(propertyDeclaration) {
566
+ if (!propertyDeclaration.type) return false;
567
+ if (this.isArrayProperty(propertyDeclaration)) {
568
+ const elementType = propertyDeclaration.type.elementType;
569
+ if (typescript.default.isTypeReferenceNode(elementType) && elementType.typeArguments && elementType.typeArguments.length > 0) {
570
+ const firstTypeArg = elementType.typeArguments[0];
571
+ if (firstTypeArg) {
572
+ const argSymbol = this.checker.getTypeAtLocation(firstTypeArg).getSymbol();
573
+ if (argSymbol && argSymbol.declarations) {
574
+ if (argSymbol.declarations.some((decl) => typescript.default.isClassDeclaration(decl))) return true;
575
+ }
576
+ }
577
+ }
578
+ const symbol = this.checker.getTypeAtLocation(elementType).getSymbol();
579
+ if (symbol && symbol.declarations) return symbol.declarations.some((decl) => typescript.default.isClassDeclaration(decl));
580
+ return false;
581
+ } else {
582
+ if (typescript.default.isTypeReferenceNode(propertyDeclaration.type) && propertyDeclaration.type.typeArguments && propertyDeclaration.type.typeArguments.length > 0) {
583
+ const firstTypeArg = propertyDeclaration.type.typeArguments[0];
584
+ if (firstTypeArg) {
585
+ const argSymbol = this.checker.getTypeAtLocation(firstTypeArg).getSymbol();
586
+ if (argSymbol && argSymbol.declarations) {
587
+ if (argSymbol.declarations.some((decl) => typescript.default.isClassDeclaration(decl))) return true;
588
+ }
589
+ }
590
+ }
591
+ const symbol = this.checker.getTypeAtLocation(propertyDeclaration.type).getSymbol();
592
+ if (symbol && symbol.declarations) return symbol.declarations.some((decl) => typescript.default.isClassDeclaration(decl));
593
+ return false;
594
+ }
595
+ }
596
+ getDeclarationProperty(property) {
597
+ if (!property.originalProperty.type) return;
598
+ if (typescript.default.isArrayTypeNode(property.originalProperty.type)) {
599
+ const elementType = property.originalProperty.type.elementType;
600
+ if (typescript.default.isTypeReferenceNode(elementType) && elementType.typeArguments && elementType.typeArguments.length > 0) {
601
+ const firstTypeArg = elementType.typeArguments[0];
602
+ if (firstTypeArg) {
603
+ const argSymbol = this.checker.getTypeAtLocation(firstTypeArg).getSymbol();
604
+ if (argSymbol && argSymbol.declarations) {
605
+ const classDecl = argSymbol.declarations.find((decl) => typescript.default.isClassDeclaration(decl));
606
+ if (classDecl) return classDecl;
607
+ }
608
+ }
609
+ }
610
+ const symbol = this.checker.getTypeAtLocation(elementType).getSymbol();
611
+ if (symbol && symbol.declarations) return symbol.declarations.find((decl) => typescript.default.isClassDeclaration(decl)) || symbol.declarations[0];
612
+ return;
613
+ }
614
+ if (typescript.default.isTypeReferenceNode(property.originalProperty.type) && property.originalProperty.type.typeArguments && property.originalProperty.type.typeArguments.length > 0) {
615
+ const firstTypeArg = property.originalProperty.type.typeArguments[0];
616
+ if (firstTypeArg) {
617
+ const argSymbol = this.checker.getTypeAtLocation(firstTypeArg).getSymbol();
618
+ if (argSymbol && argSymbol.declarations) {
619
+ const classDecl = argSymbol.declarations.find((decl) => typescript.default.isClassDeclaration(decl));
620
+ if (classDecl) return classDecl;
621
+ }
622
+ }
623
+ }
624
+ const symbol = this.checker.getTypeAtLocation(property.originalProperty.type).getSymbol();
625
+ if (symbol && symbol.declarations) return symbol.declarations.find((decl) => typescript.default.isClassDeclaration(decl)) || symbol.declarations[0];
626
+ }
627
+ isArrayProperty(propertyDeclaration) {
628
+ if (!propertyDeclaration.type) return false;
629
+ return typescript.default.isArrayTypeNode(propertyDeclaration.type);
630
+ }
631
+ getSchemaFromProperties({ properties, visitedClass, transformedSchema, classDeclaration }) {
632
+ let schema = {};
633
+ const required = [];
634
+ for (const property of properties) {
635
+ schema[property.name] = this.getSchemaFromProperty({
636
+ property,
637
+ visitedClass,
638
+ transformedSchema,
639
+ classDeclaration
640
+ });
641
+ if (!property.isOptional) required.push(property.name);
642
+ }
643
+ return {
644
+ type: "object",
645
+ properties: schema,
646
+ required: required.length ? required : void 0
647
+ };
648
+ }
649
+ getSchemaFromProperty({ property, visitedClass, transformedSchema, classDeclaration }) {
650
+ let schema = {};
651
+ if (property.isPrimitive) schema = this.getSchemaFromPrimitive(property);
652
+ else if (property.isClassType) schema = this.buildSchemaFromClass({
653
+ property,
654
+ classDeclaration,
655
+ visitedClass,
656
+ transformedSchema
657
+ });
658
+ else if (property.isTypeLiteral && property.typeLiteralClassReference) schema = this.buildSchemaFromClass({
659
+ property,
660
+ classDeclaration: property.typeLiteralClassReference,
661
+ visitedClass,
662
+ transformedSchema
663
+ });
664
+ else schema = {
665
+ type: "object",
666
+ properties: {},
667
+ additionalProperties: true
668
+ };
669
+ this.applyDecorators(property, schema);
670
+ return schema;
671
+ }
672
+ buildSchemaFromClass({ property, classDeclaration, visitedClass, transformedSchema }) {
673
+ const declaration = this.getDeclarationProperty(property);
674
+ let schema = {};
675
+ if (property.isRef && classDeclaration.name) if (property.isArray) {
676
+ schema.type = "array";
677
+ schema.items = { $ref: `#/components/schemas/${classDeclaration.name.text}` };
678
+ } else schema = { $ref: `#/components/schemas/${classDeclaration.name.text}` };
679
+ else if (property.isTypeLiteral && property.typeLiteralClassReference) schema = this.getSchemaFromClass({
680
+ isArray: property.isArray,
681
+ visitedClass,
682
+ transformedSchema,
683
+ declaration: property.typeLiteralClassReference
684
+ });
685
+ else schema = this.getSchemaFromClass({
686
+ isArray: property.isArray,
687
+ visitedClass,
688
+ transformedSchema,
689
+ declaration
690
+ });
691
+ return schema;
692
+ }
693
+ getSchemaFromClass({ transformedSchema = /* @__PURE__ */ new Map(), visitedClass = /* @__PURE__ */ new Set(), declaration, isArray }) {
694
+ let schema = { type: "object" };
695
+ if (!declaration || !typescript.default.isClassDeclaration(declaration) || !declaration.name) return { type: "object" };
696
+ if (visitedClass.has(declaration)) {
697
+ if (isArray) {
698
+ schema.type = "array";
699
+ schema.items = { $ref: `#/components/schemas/${declaration.name.text}` };
700
+ } else schema = { $ref: `#/components/schemas/${declaration.name.text}` };
701
+ return schema;
702
+ }
703
+ visitedClass.add(declaration);
704
+ const properties = this.getPropertiesByClassDeclaration(declaration);
705
+ let transformerProps = this.getSchemaFromProperties({
706
+ properties,
707
+ visitedClass,
708
+ transformedSchema,
709
+ classDeclaration: declaration
710
+ });
711
+ if (isArray) {
712
+ schema.type = "array";
713
+ schema.items = {
714
+ type: transformerProps.type,
715
+ properties: transformerProps.properties,
716
+ required: transformerProps.required
717
+ };
718
+ } else {
719
+ schema.type = transformerProps.type;
720
+ schema.properties = transformerProps.properties;
721
+ schema.required = transformerProps.required;
722
+ }
723
+ transformedSchema.set(declaration.name.text, schema);
724
+ visitedClass.delete(declaration);
725
+ return schema;
726
+ }
727
+ getSchemaFromEnum(property) {
728
+ let typeNode = property.originalProperty.type;
729
+ if (typescript.default.isArrayTypeNode(typeNode)) typeNode = typeNode.elementType;
730
+ const type = this.checker.getTypeAtLocation(typeNode);
731
+ if (type.symbol && type.symbol.exports) {
732
+ const values = [];
733
+ type.symbol.exports.forEach((member) => {
734
+ const declaration = member.valueDeclaration;
735
+ if (declaration && typescript.default.isEnumMember(declaration)) {
736
+ const value = this.checker.getConstantValue(declaration);
737
+ if (value !== void 0) values.push(value);
738
+ }
739
+ });
740
+ if (values.length > 0) {
741
+ const propertySchema = { type: "object" };
742
+ propertySchema.enum = values;
743
+ const isString = values.every((v) => typeof v === "string");
744
+ const isNumber = values.every((v) => typeof v === "number");
745
+ if (isString) propertySchema.type = "string";
746
+ else if (isNumber) propertySchema.type = "number";
747
+ else propertySchema.type = "string";
748
+ if (property.isArray) {
749
+ const itemsSchema = { ...propertySchema };
750
+ propertySchema.type = "array";
751
+ propertySchema.items = itemsSchema;
752
+ delete propertySchema.enum;
753
+ return propertySchema;
754
+ } else return propertySchema;
755
+ }
756
+ }
757
+ }
758
+ getSchemaFromPrimitive(property) {
759
+ if (property.isEnum) {
760
+ const enumSchema = this.getSchemaFromEnum(property);
761
+ if (enumSchema) return enumSchema;
762
+ }
763
+ const propertySchema = { type: "object" };
764
+ const propertyType = property.type.toLowerCase().replace("[]", "").trim();
765
+ let isFile = false;
766
+ switch (propertyType) {
767
+ case constants.jsPrimitives.String.value:
768
+ propertySchema.type = constants.jsPrimitives.String.value;
769
+ break;
770
+ case constants.jsPrimitives.Number.value:
771
+ propertySchema.type = constants.jsPrimitives.Number.value;
772
+ propertySchema.format = constants.jsPrimitives.Number.format;
773
+ break;
774
+ case constants.jsPrimitives.BigInt.type.toLocaleLowerCase():
775
+ propertySchema.type = constants.jsPrimitives.BigInt.value;
776
+ propertySchema.format = constants.jsPrimitives.BigInt.format;
777
+ break;
778
+ case constants.jsPrimitives.Date.type.toLocaleLowerCase():
779
+ propertySchema.type = constants.jsPrimitives.Date.value;
780
+ propertySchema.format = constants.jsPrimitives.Date.format;
781
+ break;
782
+ case constants.jsPrimitives.Buffer.type.toLocaleLowerCase():
783
+ case constants.jsPrimitives.Uint8Array.type.toLocaleLowerCase():
784
+ case constants.jsPrimitives.File.type.toLocaleLowerCase():
785
+ case constants.jsPrimitives.UploadFile.type.toLocaleLowerCase():
786
+ case constants.jsPrimitives.UploadFileDto.type.toLocaleLowerCase():
787
+ propertySchema.type = constants.jsPrimitives.UploadFile.value;
788
+ propertySchema.format = constants.jsPrimitives.UploadFile.format;
789
+ isFile = true;
790
+ break;
791
+ case constants.jsPrimitives.Array.value:
792
+ propertySchema.type = constants.jsPrimitives.Array.value;
793
+ break;
794
+ case constants.jsPrimitives.Boolean.value:
795
+ propertySchema.type = constants.jsPrimitives.Boolean.value;
796
+ break;
797
+ case constants.jsPrimitives.Symbol.type.toLocaleLowerCase():
798
+ propertySchema.type = constants.jsPrimitives.Symbol.value;
799
+ break;
800
+ case constants.jsPrimitives.Object.value:
801
+ propertySchema.type = constants.jsPrimitives.Object.value;
802
+ break;
803
+ default: propertySchema.type = constants.jsPrimitives.String.value;
804
+ }
805
+ if (property.isArray) {
806
+ delete propertySchema.format;
807
+ propertySchema.type = `array`;
808
+ propertySchema.items = {
809
+ type: isFile ? constants.jsPrimitives.UploadFile.value : propertyType,
810
+ format: isFile ? constants.jsPrimitives.UploadFile.format : propertySchema.format
811
+ };
812
+ }
813
+ return propertySchema;
814
+ }
815
+ isTypeLiteral(property) {
816
+ if (!property.type) return false;
817
+ if (typescript.default.isTypeReferenceNode(property.type)) {
818
+ const symbol = this.checker.getSymbolAtLocation(property.type.typeName);
819
+ if (symbol) {
820
+ const declarations = symbol.getDeclarations();
821
+ if (declarations && declarations.length > 0) {
822
+ const typeAliasDecl = declarations.find((decl) => typescript.default.isTypeAliasDeclaration(decl));
823
+ if (typeAliasDecl && typeAliasDecl.type) return this.isLiteralTypeNode(typeAliasDecl.type);
824
+ }
825
+ }
826
+ }
827
+ return false;
828
+ }
829
+ /**
830
+ *
831
+ * @param typeNode
832
+ * @returns boolean - true si el typeNode representa un tipo literal complejo
833
+ */
834
+ isLiteralTypeNode(typeNode) {
835
+ return typescript.default.isIntersectionTypeNode(typeNode) || typescript.default.isUnionTypeNode(typeNode) || typescript.default.isMappedTypeNode(typeNode) || typescript.default.isTypeLiteralNode(typeNode) || typescript.default.isConditionalTypeNode(typeNode) || typescript.default.isIndexedAccessTypeNode(typeNode) || typescript.default.isTypeOperatorNode(typeNode) || typescript.default.isTypeReferenceNode(typeNode);
836
+ }
837
+ applyEnumDecorator(decorator, schema) {
838
+ if (decorator.arguments.length === 0) return;
839
+ const arg = decorator.arguments[0];
840
+ if (arg && typeof arg === "object" && "kind" in arg) {
841
+ const type = this.checker.getTypeAtLocation(arg);
842
+ if (type.symbol && type.symbol.exports) {
843
+ const values = [];
844
+ type.symbol.exports.forEach((member) => {
845
+ const declaration = member.valueDeclaration;
846
+ if (declaration && typescript.default.isEnumMember(declaration)) {
847
+ const value = this.checker.getConstantValue(declaration);
848
+ if (value !== void 0) values.push(value);
849
+ }
850
+ });
851
+ if (values.length > 0) {
852
+ schema.enum = values;
853
+ const isString = values.every((v) => typeof v === "string");
854
+ const isNumber = values.every((v) => typeof v === "number");
855
+ if (isString) schema.type = "string";
856
+ else if (isNumber) schema.type = "number";
857
+ else schema.type = "string";
858
+ }
859
+ }
860
+ }
861
+ }
862
+ applyDecorators(property, schema) {
863
+ for (const decorator of property.decorators) switch (decorator.name) {
864
+ case constants.validatorDecorators.IsString.name:
865
+ if (!property.isArray) schema.type = constants.validatorDecorators.IsString.type;
866
+ else if (schema.items) schema.items.type = constants.validatorDecorators.IsString.type;
867
+ break;
868
+ case constants.validatorDecorators.IsInt.name:
869
+ if (!property.isArray) {
870
+ schema.type = constants.validatorDecorators.IsInt.type;
871
+ schema.format = constants.validatorDecorators.IsInt.format;
872
+ } else if (schema.items) {
873
+ schema.items.type = constants.validatorDecorators.IsInt.type;
874
+ schema.items.format = constants.validatorDecorators.IsInt.format;
875
+ }
876
+ break;
877
+ case constants.validatorDecorators.IsNumber.name:
878
+ if (!property.isArray) schema.type = constants.validatorDecorators.IsNumber.type;
879
+ else if (schema.items) schema.items.type = constants.validatorDecorators.IsNumber.type;
880
+ break;
881
+ case constants.validatorDecorators.IsBoolean.name:
882
+ if (!property.isArray) schema.type = constants.validatorDecorators.IsBoolean.type;
883
+ else if (schema.items) schema.items.type = constants.validatorDecorators.IsBoolean.type;
884
+ break;
885
+ case constants.validatorDecorators.IsEmail.name:
886
+ if (!property.isArray) schema.format = constants.validatorDecorators.IsEmail.format;
887
+ else if (schema.items) schema.items.format = constants.validatorDecorators.IsEmail.format;
888
+ break;
889
+ case constants.validatorDecorators.IsDate.name:
890
+ if (!property.isArray) {
891
+ schema.type = constants.validatorDecorators.IsDate.type;
892
+ schema.format = constants.validatorDecorators.IsDate.format;
893
+ } else if (schema.items) {
894
+ schema.items.type = constants.validatorDecorators.IsDate.type;
895
+ schema.items.format = constants.validatorDecorators.IsDate.format;
896
+ }
897
+ break;
898
+ case constants.validatorDecorators.IsNotEmpty.name:
899
+ property.isOptional = false;
900
+ break;
901
+ case constants.validatorDecorators.IsOptional.name:
902
+ property.isOptional = true;
903
+ break;
904
+ case constants.validatorDecorators.MinLength.name:
905
+ schema.minLength = this.getSafeDecoratorArgument(decorator.arguments[0]);
906
+ break;
907
+ case constants.validatorDecorators.MaxLength.name:
908
+ schema.maxLength = this.getSafeDecoratorArgument(decorator.arguments[0]);
909
+ break;
910
+ case constants.validatorDecorators.Length.name:
911
+ schema.minLength = this.getSafeDecoratorArgument(decorator.arguments[0]);
912
+ if (decorator.arguments[1]) schema.maxLength = this.getSafeDecoratorArgument(decorator.arguments[1]);
913
+ break;
914
+ case constants.validatorDecorators.Min.name:
915
+ schema.minimum = this.getSafeDecoratorArgument(decorator.arguments[0]);
916
+ break;
917
+ case constants.validatorDecorators.Max.name:
918
+ schema.maximum = this.getSafeDecoratorArgument(decorator.arguments[0]);
919
+ break;
920
+ case constants.validatorDecorators.IsPositive.name:
921
+ schema.minimum = 0;
922
+ break;
923
+ case constants.validatorDecorators.IsArray.name:
924
+ schema.type = constants.jsPrimitives.Array.value;
925
+ break;
926
+ case constants.validatorDecorators.ArrayNotEmpty.name:
927
+ schema.minItems = 1;
928
+ property.isOptional = false;
929
+ break;
930
+ case constants.validatorDecorators.ArrayMinSize.name:
931
+ schema.minItems = this.getSafeDecoratorArgument(decorator.arguments[0]);
932
+ break;
933
+ case constants.validatorDecorators.ArrayMaxSize.name:
934
+ schema.maxItems = this.getSafeDecoratorArgument(decorator.arguments[0]);
935
+ break;
936
+ case constants.validatorDecorators.IsEnum.name:
937
+ if (!property.isArray) this.applyEnumDecorator(decorator, schema);
938
+ else if (schema.items) this.applyEnumDecorator(decorator, schema.items);
939
+ break;
940
+ }
941
+ }
942
+ transform(cls, sourceOptions) {
943
+ if (this.classCache.has(cls)) return this.classCache.get(cls);
944
+ let schema = {
945
+ type: "object",
946
+ properties: {}
947
+ };
948
+ const result = this.getSourceFileByClass(cls, sourceOptions);
949
+ if (!result || !(result === null || result === void 0 ? void 0 : result.sourceFile)) {
950
+ console.warn(`Class ${cls.name} not found in any source file.`);
951
+ return {
952
+ name: cls.name,
953
+ schema: {
954
+ type: "object",
955
+ required: [],
956
+ properties: {},
957
+ additionalProperties: true
958
+ }
959
+ };
960
+ }
961
+ const properties = this.getPropertiesByClassDeclaration(result.node);
962
+ schema = this.getSchemaFromProperties({
963
+ properties,
964
+ classDeclaration: result.node
965
+ });
966
+ return {
967
+ name: cls.name,
968
+ schema
969
+ };
970
+ }
971
+ };
972
+ function transform(cls, options) {
973
+ return SchemaTransformer.getInstance(void 0, options).transform(cls, options === null || options === void 0 ? void 0 : options.sourceOptions);
974
+ }
975
+ //#endregion
976
+ exports.transform = transform;