ts-class-to-openapi 1.0.5 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +368 -882
- package/dist/__test__/entities/additional-test-classes.d.ts +12 -0
- package/dist/__test__/entities/circular-reference-classes.d.ts +110 -0
- package/dist/__test__/entities/complex-circular-dependencies.d.ts +71 -0
- package/dist/__test__/entities/decorated-classes.d.ts +54 -0
- package/dist/__test__/entities/generic-circular-classes.d.ts +57 -0
- package/dist/__test__/entities/nested-classes.d.ts +70 -0
- package/dist/__test__/entities/pure-classes.d.ts +37 -0
- package/dist/__test__/entities/schema-validation-classes.d.ts +35 -0
- package/dist/__test__/index.d.ts +3 -9
- package/dist/__test__/testCases/schema-validation.test.d.ts +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.esm.js +546 -1319
- package/dist/index.js +545 -1319
- package/dist/run.d.ts +1 -1
- package/dist/run.js +1131 -1343
- package/dist/transformer.d.ts +1 -575
- package/dist/transformer.fixtures.d.ts +21 -0
- package/dist/types.d.ts +40 -3
- package/package.json +16 -15
- package/dist/__test__/entities/address.entity.d.ts +0 -5
- package/dist/__test__/entities/array.entity.d.ts +0 -7
- package/dist/__test__/entities/broken.entity.d.ts +0 -7
- package/dist/__test__/entities/circular.entity.d.ts +0 -59
- package/dist/__test__/entities/complete.entity.d.ts +0 -16
- package/dist/__test__/entities/complex-generics.entity.d.ts +0 -33
- package/dist/__test__/entities/comprehensive-enum.entity.d.ts +0 -23
- package/dist/__test__/entities/enum.entity.d.ts +0 -29
- package/dist/__test__/entities/generic.entity.d.ts +0 -11
- package/dist/__test__/entities/optional-properties.entity.d.ts +0 -11
- package/dist/__test__/entities/plain.entity.d.ts +0 -19
- package/dist/__test__/entities/simple.entity.d.ts +0 -5
- package/dist/__test__/entities/upload.entity.d.ts +0 -8
- package/dist/__test__/entities/user-role-generic.entity.d.ts +0 -13
- package/dist/__test__/test-entities/duplicate-name.entity.d.ts +0 -5
- package/dist/__test__/test-entities/generic.entity.d.ts +0 -11
- /package/dist/__test__/{circular-reference.test.d.ts → entities/circular-reference-cases.d.ts} +0 -0
- /package/dist/__test__/{enum.test.d.ts → entities/deep-nested-classes.d.ts} +0 -0
- /package/dist/__test__/{generic-types.test.d.ts → test.d.ts} +0 -0
- /package/dist/__test__/{integration.test.d.ts → testCases/circular-references.test.d.ts} +0 -0
- /package/dist/__test__/{main.test.d.ts → testCases/debug.test.d.ts} +0 -0
- /package/dist/__test__/{optional-properties.test.d.ts → testCases/decorated-classes.test.d.ts} +0 -0
- /package/dist/__test__/{plain.test.d.ts → testCases/edge-cases.test.d.ts} +0 -0
- /package/dist/__test__/{ref-pattern.test.d.ts → testCases/nested-classes.test.d.ts} +0 -0
- /package/dist/__test__/{singleton-behavior.test.d.ts → testCases/pure-classes.test.d.ts} +0 -0
package/dist/run.js
CHANGED
|
@@ -1,118 +1,65 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var node_test = require('node:test');
|
|
4
|
+
var assert = require('node:assert');
|
|
3
5
|
var ts = require('typescript');
|
|
4
6
|
var path = require('path');
|
|
7
|
+
var classValidator = require('class-validator');
|
|
5
8
|
|
|
6
9
|
const TS_CONFIG_DEFAULT_PATH = path.resolve(process.cwd(), 'tsconfig.json');
|
|
7
10
|
const jsPrimitives = {
|
|
8
11
|
String: { type: 'String', value: 'string' },
|
|
9
|
-
|
|
12
|
+
Any: { type: 'Any'},
|
|
13
|
+
Unknown: { type: 'Unknown'},
|
|
14
|
+
Number: { type: 'Number', value: 'number', format: 'double' },
|
|
10
15
|
Boolean: { type: 'Boolean', value: 'boolean' },
|
|
11
|
-
Symbol: { type: 'Symbol', value: '
|
|
16
|
+
Symbol: { type: 'Symbol', value: 'string' },
|
|
12
17
|
BigInt: { type: 'BigInt', value: 'integer', format: 'int64' },
|
|
13
|
-
null: { type: 'null'
|
|
18
|
+
null: { type: 'null'},
|
|
14
19
|
Object: { type: 'Object', value: 'object' },
|
|
15
20
|
Array: { type: 'Array', value: 'array' },
|
|
16
21
|
Date: { type: 'Date', value: 'string', format: 'date-time' },
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Uint8Array: { type: 'Uint8Array', value: 'string', format: 'binary' },
|
|
22
|
+
Buffer: { type: 'Buffer', value: 'string'},
|
|
23
|
+
Uint8Array: { type: 'Uint8Array', value: 'string'},
|
|
20
24
|
UploadFile: { type: 'UploadFile', value: 'string', format: 'binary' },
|
|
21
|
-
File: { type: 'File', value: 'string'
|
|
25
|
+
File: { type: 'File', value: 'string'},
|
|
22
26
|
};
|
|
23
27
|
const validatorDecorators = {
|
|
24
|
-
Length: { name: 'Length'
|
|
25
|
-
MinLength: { name: 'MinLength'
|
|
26
|
-
MaxLength: { name: 'MaxLength'
|
|
28
|
+
Length: { name: 'Length'},
|
|
29
|
+
MinLength: { name: 'MinLength'},
|
|
30
|
+
MaxLength: { name: 'MaxLength'},
|
|
27
31
|
IsInt: { name: 'IsInt', type: 'integer', format: 'int32' },
|
|
28
|
-
IsNumber: { name: 'IsNumber', type: 'number'
|
|
29
|
-
IsString: { name: 'IsString', type: 'string'
|
|
30
|
-
IsPositive: { name: 'IsPositive'
|
|
32
|
+
IsNumber: { name: 'IsNumber', type: 'number'},
|
|
33
|
+
IsString: { name: 'IsString', type: 'string'},
|
|
34
|
+
IsPositive: { name: 'IsPositive'},
|
|
31
35
|
IsDate: { name: 'IsDate', type: 'string', format: 'date-time' },
|
|
32
|
-
IsEmail: { name: 'IsEmail',
|
|
36
|
+
IsEmail: { name: 'IsEmail', format: 'email' },
|
|
33
37
|
IsNotEmpty: { name: 'IsNotEmpty' },
|
|
38
|
+
IsOptional: { name: 'IsOptional' },
|
|
34
39
|
IsBoolean: { name: 'IsBoolean', type: 'boolean' },
|
|
35
|
-
IsArray: { name: 'IsArray'
|
|
40
|
+
IsArray: { name: 'IsArray'},
|
|
36
41
|
Min: { name: 'Min' },
|
|
37
42
|
Max: { name: 'Max' },
|
|
38
43
|
ArrayNotEmpty: { name: 'ArrayNotEmpty' },
|
|
39
44
|
ArrayMaxSize: { name: 'ArrayMaxSize' },
|
|
40
45
|
ArrayMinSize: { name: 'ArrayMinSize' },
|
|
41
|
-
IsEnum: { name: 'IsEnum'
|
|
46
|
+
IsEnum: { name: 'IsEnum'},
|
|
42
47
|
};
|
|
43
48
|
const constants = {
|
|
44
49
|
TS_CONFIG_DEFAULT_PATH,
|
|
45
50
|
jsPrimitives,
|
|
46
|
-
validatorDecorators
|
|
47
|
-
};
|
|
51
|
+
validatorDecorators};
|
|
48
52
|
|
|
49
|
-
/**
|
|
50
|
-
* Transforms class-validator decorated classes into OpenAPI schema objects.
|
|
51
|
-
* Analyzes TypeScript source files directly using the TypeScript compiler API.
|
|
52
|
-
* Implemented as a singleton for performance optimization.
|
|
53
|
-
*
|
|
54
|
-
* @example
|
|
55
|
-
* ```typescript
|
|
56
|
-
* const transformer = SchemaTransformer.getInstance();
|
|
57
|
-
* const schema = transformer.transform(User);
|
|
58
|
-
* console.log(schema);
|
|
59
|
-
* ```
|
|
60
|
-
*
|
|
61
|
-
* @public
|
|
62
|
-
*/
|
|
63
53
|
class SchemaTransformer {
|
|
64
|
-
/**
|
|
65
|
-
* Singleton instance
|
|
66
|
-
* @private
|
|
67
|
-
*/
|
|
68
54
|
static instance = null;
|
|
69
|
-
/**
|
|
70
|
-
* TypeScript program instance for analyzing source files.
|
|
71
|
-
* @private
|
|
72
|
-
*/
|
|
73
55
|
program;
|
|
74
|
-
/**
|
|
75
|
-
* TypeScript type checker for resolving types.
|
|
76
|
-
* @private
|
|
77
|
-
*/
|
|
78
56
|
checker;
|
|
79
|
-
/**
|
|
80
|
-
* Cache for storing transformed class schemas to avoid reprocessing.
|
|
81
|
-
* Key format: "fileName:className" for uniqueness across different files.
|
|
82
|
-
* @private
|
|
83
|
-
*/
|
|
84
57
|
classCache = new Map();
|
|
85
|
-
/**
|
|
86
|
-
* Maximum number of entries to keep in cache before cleanup
|
|
87
|
-
* @private
|
|
88
|
-
*/
|
|
89
58
|
maxCacheSize;
|
|
90
|
-
/**
|
|
91
|
-
* Whether to automatically clean up cache
|
|
92
|
-
* @private
|
|
93
|
-
*/
|
|
94
59
|
autoCleanup;
|
|
95
|
-
/**
|
|
96
|
-
* Set of file paths that have been loaded to avoid redundant processing
|
|
97
|
-
* @private
|
|
98
|
-
*/
|
|
99
60
|
loadedFiles = new Set();
|
|
100
|
-
/**
|
|
101
|
-
* Set of class names currently being processed to prevent circular references
|
|
102
|
-
* Key format: "fileName:className" for uniqueness across different files
|
|
103
|
-
* @private
|
|
104
|
-
*/
|
|
105
61
|
processingClasses = new Set();
|
|
106
|
-
/**
|
|
107
|
-
* Private constructor for singleton pattern.
|
|
108
|
-
*
|
|
109
|
-
* @param tsConfigPath - Optional path to a specific TypeScript config file
|
|
110
|
-
* @param options - Configuration options for memory management
|
|
111
|
-
* @throws {Error} When TypeScript configuration cannot be loaded
|
|
112
|
-
* @private
|
|
113
|
-
*/
|
|
114
62
|
constructor(tsConfigPath = constants.TS_CONFIG_DEFAULT_PATH, options = {}) {
|
|
115
|
-
// Initialize configuration with defaults
|
|
116
63
|
this.maxCacheSize = options.maxCacheSize ?? 100;
|
|
117
64
|
this.autoCleanup = options.autoCleanup ?? true;
|
|
118
65
|
const { config, error } = ts.readConfigFile(tsConfigPath || 'tsconfig.json', ts.sys.readFile);
|
|
@@ -124,495 +71,42 @@ class SchemaTransformer {
|
|
|
124
71
|
this.program = ts.createProgram(fileNames, tsOptions);
|
|
125
72
|
this.checker = this.program.getTypeChecker();
|
|
126
73
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
* @param fileName - The source file name
|
|
131
|
-
* @param className - The class name
|
|
132
|
-
* @returns Unique cache key in format "fileName:className"
|
|
133
|
-
* @private
|
|
134
|
-
*/
|
|
135
|
-
getCacheKey(fileName, className) {
|
|
136
|
-
return `${fileName}:${className}`;
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Cleans up cache when it exceeds maximum size to prevent memory leaks.
|
|
140
|
-
* Removes oldest entries using LRU strategy.
|
|
141
|
-
* @private
|
|
142
|
-
*/
|
|
143
|
-
cleanupCache() {
|
|
144
|
-
if (!this.autoCleanup || this.classCache.size <= this.maxCacheSize) {
|
|
145
|
-
return;
|
|
74
|
+
getPropertiesByClassDeclaration(classNode, visitedDeclarations = new Set()) {
|
|
75
|
+
if (visitedDeclarations.has(classNode)) {
|
|
76
|
+
return [];
|
|
146
77
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
this.
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
*/
|
|
168
|
-
transformByName(className, contextFilePath) {
|
|
169
|
-
// Get all relevant source files (not declaration files and not in node_modules)
|
|
170
|
-
const sourceFiles = this.program.getSourceFiles().filter(sf => {
|
|
171
|
-
if (sf.isDeclarationFile)
|
|
172
|
-
return false;
|
|
173
|
-
if (sf.fileName.includes('.d.ts'))
|
|
174
|
-
return false;
|
|
175
|
-
if (sf.fileName.includes('node_modules'))
|
|
176
|
-
return false;
|
|
177
|
-
// Mark file as loaded for memory tracking
|
|
178
|
-
this.loadedFiles.add(sf.fileName);
|
|
179
|
-
return true;
|
|
180
|
-
});
|
|
181
|
-
// If we have a context file, try to find the class in that file first
|
|
182
|
-
if (contextFilePath) {
|
|
183
|
-
const contextSourceFile = this.program.getSourceFile(contextFilePath);
|
|
184
|
-
if (contextSourceFile) {
|
|
185
|
-
const classNode = this.findClassByName(contextSourceFile, className);
|
|
186
|
-
if (classNode) {
|
|
187
|
-
const cacheKey = this.getCacheKey(contextSourceFile.fileName, className);
|
|
188
|
-
// Check cache first
|
|
189
|
-
if (this.classCache.has(cacheKey)) {
|
|
190
|
-
return this.classCache.get(cacheKey);
|
|
191
|
-
}
|
|
192
|
-
// Check for circular reference before processing
|
|
193
|
-
if (this.processingClasses.has(cacheKey)) {
|
|
194
|
-
// Return a $ref reference to break circular dependency (OpenAPI 3.1 style)
|
|
195
|
-
return {
|
|
196
|
-
name: className,
|
|
197
|
-
schema: {
|
|
198
|
-
$ref: `#/components/schemas/${className}`,
|
|
199
|
-
description: `Reference to ${className} (circular reference detected)`,
|
|
200
|
-
},
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
// Mark this class as being processed
|
|
204
|
-
this.processingClasses.add(cacheKey);
|
|
205
|
-
try {
|
|
206
|
-
const result = this.transformClass(classNode, contextSourceFile);
|
|
207
|
-
this.classCache.set(cacheKey, result);
|
|
208
|
-
this.cleanupCache();
|
|
209
|
-
return result;
|
|
210
|
-
}
|
|
211
|
-
finally {
|
|
212
|
-
// Always remove from processing set when done
|
|
213
|
-
this.processingClasses.delete(cacheKey);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
// Fallback to searching all files, but prioritize files that are more likely to be relevant
|
|
219
|
-
const prioritizedFiles = this.prioritizeSourceFiles(sourceFiles, contextFilePath);
|
|
220
|
-
for (const sourceFile of prioritizedFiles) {
|
|
221
|
-
const classNode = this.findClassByName(sourceFile, className);
|
|
222
|
-
if (classNode && sourceFile?.fileName) {
|
|
223
|
-
const cacheKey = this.getCacheKey(sourceFile.fileName, className);
|
|
224
|
-
// Check cache first using fileName:className as key
|
|
225
|
-
if (this.classCache.has(cacheKey)) {
|
|
226
|
-
return this.classCache.get(cacheKey);
|
|
227
|
-
}
|
|
228
|
-
// Check for circular reference before processing
|
|
229
|
-
if (this.processingClasses.has(cacheKey)) {
|
|
230
|
-
// Return a $ref reference to break circular dependency (OpenAPI 3.1 style)
|
|
231
|
-
return {
|
|
232
|
-
name: className,
|
|
233
|
-
schema: {
|
|
234
|
-
$ref: `#/components/schemas/${className}`,
|
|
235
|
-
description: `Reference to ${className} (circular reference detected)`,
|
|
236
|
-
},
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
// Mark this class as being processed
|
|
240
|
-
this.processingClasses.add(cacheKey);
|
|
241
|
-
try {
|
|
242
|
-
const result = this.transformClass(classNode, sourceFile);
|
|
243
|
-
// Cache using fileName:className as key for uniqueness
|
|
244
|
-
this.classCache.set(cacheKey, result);
|
|
245
|
-
// Clean up cache if it gets too large
|
|
246
|
-
this.cleanupCache();
|
|
247
|
-
return result;
|
|
78
|
+
visitedDeclarations.add(classNode);
|
|
79
|
+
// if no heritage clauses, get properties directly from class
|
|
80
|
+
if (!classNode.heritageClauses) {
|
|
81
|
+
return this.getPropertiesByClassMembers(classNode.members, classNode);
|
|
82
|
+
} // use heritage clauses to get properties from base classes
|
|
83
|
+
else {
|
|
84
|
+
const heritageClause = classNode.heritageClauses[0];
|
|
85
|
+
if (heritageClause &&
|
|
86
|
+
heritageClause.token === ts.SyntaxKind.ExtendsKeyword) {
|
|
87
|
+
const type = heritageClause.types[0];
|
|
88
|
+
let properties = [];
|
|
89
|
+
let baseProperties = [];
|
|
90
|
+
if (!type)
|
|
91
|
+
return [];
|
|
92
|
+
const symbol = this.checker.getSymbolAtLocation(type.expression);
|
|
93
|
+
if (!symbol)
|
|
94
|
+
return [];
|
|
95
|
+
const declaration = symbol.declarations?.[0];
|
|
96
|
+
if (declaration && ts.isClassDeclaration(declaration)) {
|
|
97
|
+
baseProperties = this.getPropertiesByClassDeclaration(declaration, visitedDeclarations);
|
|
248
98
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
this.processingClasses.delete(cacheKey);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
throw new Error(`Class ${className} not found`);
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* Prioritizes source files based on context to resolve class name conflicts.
|
|
259
|
-
* Gives priority to files in the same directory or with similar names.
|
|
260
|
-
*
|
|
261
|
-
* @param sourceFiles - Array of source files to prioritize
|
|
262
|
-
* @param contextFilePath - Optional path to context file for prioritization
|
|
263
|
-
* @returns Prioritized array of source files
|
|
264
|
-
* @private
|
|
265
|
-
*/
|
|
266
|
-
prioritizeSourceFiles(sourceFiles, contextFilePath) {
|
|
267
|
-
if (!contextFilePath) {
|
|
268
|
-
return sourceFiles;
|
|
269
|
-
}
|
|
270
|
-
const contextDir = contextFilePath.substring(0, contextFilePath.lastIndexOf('/'));
|
|
271
|
-
return sourceFiles.sort((a, b) => {
|
|
272
|
-
const aDir = a.fileName.substring(0, a.fileName.lastIndexOf('/'));
|
|
273
|
-
const bDir = b.fileName.substring(0, b.fileName.lastIndexOf('/'));
|
|
274
|
-
// Prioritize files in the same directory as context
|
|
275
|
-
const aInSameDir = aDir === contextDir ? 1 : 0;
|
|
276
|
-
const bInSameDir = bDir === contextDir ? 1 : 0;
|
|
277
|
-
if (aInSameDir !== bInSameDir) {
|
|
278
|
-
return bInSameDir - aInSameDir; // Higher priority first
|
|
279
|
-
}
|
|
280
|
-
// Prioritize non-test files over test files
|
|
281
|
-
const aIsTest = a.fileName.includes('test') || a.fileName.includes('spec') ? 0 : 1;
|
|
282
|
-
const bIsTest = b.fileName.includes('test') || b.fileName.includes('spec') ? 0 : 1;
|
|
283
|
-
if (aIsTest !== bIsTest) {
|
|
284
|
-
return bIsTest - aIsTest; // Non-test files first
|
|
285
|
-
}
|
|
286
|
-
return 0;
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Gets the singleton instance of SchemaTransformer.
|
|
291
|
-
*
|
|
292
|
-
* @param tsConfigPath - Optional path to a specific TypeScript config file (only used on first call)
|
|
293
|
-
* @param options - Configuration options for memory management (only used on first call)
|
|
294
|
-
* @returns The singleton instance
|
|
295
|
-
*
|
|
296
|
-
* @example
|
|
297
|
-
* ```typescript
|
|
298
|
-
* const transformer = SchemaTransformer.getInstance();
|
|
299
|
-
* ```
|
|
300
|
-
*
|
|
301
|
-
* @example
|
|
302
|
-
* ```typescript
|
|
303
|
-
* // With memory optimization options
|
|
304
|
-
* const transformer = SchemaTransformer.getInstance('./tsconfig.json', {
|
|
305
|
-
* maxCacheSize: 50,
|
|
306
|
-
* autoCleanup: true
|
|
307
|
-
* });
|
|
308
|
-
* ```
|
|
309
|
-
*
|
|
310
|
-
* @public
|
|
311
|
-
*/
|
|
312
|
-
/**
|
|
313
|
-
* Clears the current singleton instance. Useful for testing or when you need
|
|
314
|
-
* to create a new instance with different configuration.
|
|
315
|
-
* @private
|
|
316
|
-
*/
|
|
317
|
-
static clearInstance() {
|
|
318
|
-
SchemaTransformer.instance = undefined;
|
|
319
|
-
}
|
|
320
|
-
/**
|
|
321
|
-
* Flag to prevent recursive disposal calls
|
|
322
|
-
* @private
|
|
323
|
-
*/
|
|
324
|
-
static disposingInProgress = false;
|
|
325
|
-
/**
|
|
326
|
-
* Completely disposes of the current singleton instance and releases all resources.
|
|
327
|
-
* This is a static method that can be called without having an instance reference.
|
|
328
|
-
* Ensures complete memory cleanup regardless of the current state.
|
|
329
|
-
*
|
|
330
|
-
* @example
|
|
331
|
-
* ```typescript
|
|
332
|
-
* SchemaTransformer.disposeInstance();
|
|
333
|
-
* // All resources released, next getInstance() will create fresh instance
|
|
334
|
-
* ```
|
|
335
|
-
*
|
|
336
|
-
* @public
|
|
337
|
-
*/
|
|
338
|
-
static disposeInstance() {
|
|
339
|
-
// Prevent recursive disposal calls
|
|
340
|
-
if (SchemaTransformer.disposingInProgress) {
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
SchemaTransformer.disposingInProgress = true;
|
|
344
|
-
try {
|
|
345
|
-
if (SchemaTransformer.instance) {
|
|
346
|
-
SchemaTransformer.instance.dispose();
|
|
99
|
+
properties = this.getPropertiesByClassMembers(classNode.members, classNode);
|
|
100
|
+
return baseProperties.concat(properties);
|
|
347
101
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
// Log any disposal errors but continue with cleanup
|
|
351
|
-
console.warn('Warning during static disposal:', error);
|
|
352
|
-
}
|
|
353
|
-
finally {
|
|
354
|
-
// Always ensure the static instance is cleared
|
|
355
|
-
SchemaTransformer.instance = undefined;
|
|
356
|
-
SchemaTransformer.disposingInProgress = false;
|
|
357
|
-
// Force garbage collection for cleanup
|
|
358
|
-
if (global.gc) {
|
|
359
|
-
global.gc();
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
/**
|
|
364
|
-
* @deprecated Use disposeInstance() instead for better clarity
|
|
365
|
-
* @private
|
|
366
|
-
*/
|
|
367
|
-
static dispose() {
|
|
368
|
-
SchemaTransformer.disposeInstance();
|
|
369
|
-
}
|
|
370
|
-
static getInstance(tsConfigPath, options) {
|
|
371
|
-
if (!SchemaTransformer.instance || SchemaTransformer.isInstanceDisposed()) {
|
|
372
|
-
SchemaTransformer.instance = new SchemaTransformer(tsConfigPath, options);
|
|
373
|
-
}
|
|
374
|
-
return SchemaTransformer.instance;
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* Internal method to check if current instance is disposed
|
|
378
|
-
* @private
|
|
379
|
-
*/
|
|
380
|
-
static isInstanceDisposed() {
|
|
381
|
-
return SchemaTransformer.instance
|
|
382
|
-
? SchemaTransformer.instance.isDisposed()
|
|
383
|
-
: true;
|
|
384
|
-
}
|
|
385
|
-
/**
|
|
386
|
-
* Transforms a class using the singleton instance
|
|
387
|
-
* @param cls - The class constructor function to transform
|
|
388
|
-
* @param options - Optional configuration for memory management (only used if no instance exists)
|
|
389
|
-
* @returns Object containing the class name and its corresponding JSON schema
|
|
390
|
-
* @public
|
|
391
|
-
*/
|
|
392
|
-
static transformClass(cls, options) {
|
|
393
|
-
// Use the singleton instance instead of creating a temporary one
|
|
394
|
-
const transformer = SchemaTransformer.getInstance(undefined, options);
|
|
395
|
-
return transformer.transform(cls);
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Transforms a class constructor function into an OpenAPI schema object.
|
|
399
|
-
*
|
|
400
|
-
* @param cls - The class constructor function to transform
|
|
401
|
-
* @returns Object containing the class name and its corresponding JSON schema
|
|
402
|
-
*
|
|
403
|
-
* @example
|
|
404
|
-
* ```typescript
|
|
405
|
-
* import { User } from './entities/user.js';
|
|
406
|
-
* const transformer = SchemaTransformer.getInstance();
|
|
407
|
-
* const schema = transformer.transform(User);
|
|
408
|
-
* ```
|
|
409
|
-
*
|
|
410
|
-
* @public
|
|
411
|
-
*/
|
|
412
|
-
transform(cls) {
|
|
413
|
-
return this.transformByName(cls.name);
|
|
414
|
-
}
|
|
415
|
-
/**
|
|
416
|
-
* Clears all cached schemas and loaded file references to free memory.
|
|
417
|
-
* Useful for long-running applications or when processing many different classes.
|
|
418
|
-
*
|
|
419
|
-
* @example
|
|
420
|
-
* ```typescript
|
|
421
|
-
* const transformer = SchemaTransformer.getInstance();
|
|
422
|
-
* // After processing many classes...
|
|
423
|
-
* transformer.clearCache();
|
|
424
|
-
* ```
|
|
425
|
-
*
|
|
426
|
-
* @public
|
|
427
|
-
*/
|
|
428
|
-
clearCache() {
|
|
429
|
-
this.classCache.clear();
|
|
430
|
-
this.loadedFiles.clear();
|
|
431
|
-
this.processingClasses.clear();
|
|
432
|
-
// Force garbage collection hint if available
|
|
433
|
-
if (global.gc) {
|
|
434
|
-
global.gc();
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* Completely disposes of the transformer instance and releases all resources.
|
|
439
|
-
* This includes clearing all caches, releasing TypeScript program resources,
|
|
440
|
-
* and resetting the singleton instance.
|
|
441
|
-
*
|
|
442
|
-
* After calling this method, you need to call getInstance() again to get a new instance.
|
|
443
|
-
*
|
|
444
|
-
* @example
|
|
445
|
-
* ```typescript
|
|
446
|
-
* const transformer = SchemaTransformer.getInstance();
|
|
447
|
-
* // ... use transformer
|
|
448
|
-
* transformer.dispose();
|
|
449
|
-
* // transformer is now unusable, need to get new instance
|
|
450
|
-
* const newTransformer = SchemaTransformer.getInstance();
|
|
451
|
-
* ```
|
|
452
|
-
*
|
|
453
|
-
* @private
|
|
454
|
-
*/
|
|
455
|
-
dispose() {
|
|
456
|
-
try {
|
|
457
|
-
// Clear all caches and sets completely
|
|
458
|
-
this.classCache.clear();
|
|
459
|
-
this.loadedFiles.clear();
|
|
460
|
-
this.processingClasses.clear();
|
|
461
|
-
// Release TypeScript program resources
|
|
462
|
-
// While TypeScript doesn't provide explicit disposal methods,
|
|
463
|
-
// we can help garbage collection by clearing all references
|
|
464
|
-
// Clear all references to TypeScript objects
|
|
465
|
-
// @ts-ignore - We're intentionally setting these to null for cleanup
|
|
466
|
-
this.program = null;
|
|
467
|
-
// @ts-ignore - We're intentionally setting these to null for cleanup
|
|
468
|
-
this.checker = null;
|
|
469
|
-
}
|
|
470
|
-
catch (error) {
|
|
471
|
-
// If there's any error during disposal, log it but continue
|
|
472
|
-
console.warn('Warning during transformer disposal:', error);
|
|
473
|
-
}
|
|
474
|
-
finally {
|
|
475
|
-
// Force garbage collection for cleanup
|
|
476
|
-
if (global.gc) {
|
|
477
|
-
global.gc();
|
|
102
|
+
else {
|
|
103
|
+
return this.getPropertiesByClassMembers(classNode.members, classNode);
|
|
478
104
|
}
|
|
479
105
|
}
|
|
480
106
|
}
|
|
481
|
-
|
|
482
|
-
* Completely resets the transformer by disposing current instance and creating a new one.
|
|
483
|
-
* This is useful when you need a fresh start with different TypeScript configuration
|
|
484
|
-
* or want to ensure all resources are properly released and recreated.
|
|
485
|
-
*
|
|
486
|
-
* @param tsConfigPath - Optional path to a specific TypeScript config file for the new instance
|
|
487
|
-
* @param options - Configuration options for memory management for the new instance
|
|
488
|
-
* @returns A fresh SchemaTransformer instance
|
|
489
|
-
*
|
|
490
|
-
* @example
|
|
491
|
-
* ```typescript
|
|
492
|
-
* const transformer = SchemaTransformer.getInstance();
|
|
493
|
-
* // ... use transformer
|
|
494
|
-
* const freshTransformer = transformer.reset('./new-tsconfig.json');
|
|
495
|
-
* ```
|
|
496
|
-
*
|
|
497
|
-
* @private
|
|
498
|
-
*/
|
|
499
|
-
reset(tsConfigPath, options) {
|
|
500
|
-
// Dispose current instance using static method to properly clear instance reference
|
|
501
|
-
SchemaTransformer.disposeInstance();
|
|
502
|
-
// Create and return new instance
|
|
503
|
-
return SchemaTransformer.getInstance(tsConfigPath, options);
|
|
504
|
-
}
|
|
505
|
-
/**
|
|
506
|
-
* Gets memory usage statistics for monitoring and debugging.
|
|
507
|
-
*
|
|
508
|
-
* @returns Object containing cache size, loaded files count, and processing status
|
|
509
|
-
*
|
|
510
|
-
* @example
|
|
511
|
-
* ```typescript
|
|
512
|
-
* const transformer = SchemaTransformer.getInstance();
|
|
513
|
-
* const stats = transformer.getMemoryStats();
|
|
514
|
-
* console.log(`Cache entries: ${stats.cacheSize}, Files loaded: ${stats.loadedFiles}`);
|
|
515
|
-
* console.log(`Currently processing: ${stats.currentlyProcessing} classes`);
|
|
516
|
-
* ```
|
|
517
|
-
*
|
|
518
|
-
* @private
|
|
519
|
-
*/
|
|
520
|
-
getMemoryStats() {
|
|
521
|
-
return {
|
|
522
|
-
cacheSize: this.classCache?.size || 0,
|
|
523
|
-
loadedFiles: this.loadedFiles?.size || 0,
|
|
524
|
-
currentlyProcessing: this.processingClasses?.size || 0,
|
|
525
|
-
maxCacheSize: this.maxCacheSize || 0,
|
|
526
|
-
autoCleanup: this.autoCleanup || false,
|
|
527
|
-
isDisposed: !this.program || !this.checker,
|
|
528
|
-
};
|
|
529
|
-
}
|
|
530
|
-
/**
|
|
531
|
-
* Checks if the transformer instance has been disposed and is no longer usable.
|
|
532
|
-
*
|
|
533
|
-
* @returns True if the instance has been disposed
|
|
534
|
-
*
|
|
535
|
-
* @example
|
|
536
|
-
* ```typescript
|
|
537
|
-
* const transformer = SchemaTransformer.getInstance();
|
|
538
|
-
* transformer.dispose();
|
|
539
|
-
* console.log(transformer.isDisposed()); // true
|
|
540
|
-
* ```
|
|
541
|
-
*
|
|
542
|
-
* @private
|
|
543
|
-
*/
|
|
544
|
-
isDisposed() {
|
|
545
|
-
return (!this.program ||
|
|
546
|
-
!this.checker ||
|
|
547
|
-
!this.classCache ||
|
|
548
|
-
!this.loadedFiles ||
|
|
549
|
-
!this.processingClasses);
|
|
550
|
-
}
|
|
551
|
-
/**
|
|
552
|
-
* Static method to check if there's an active singleton instance.
|
|
553
|
-
*
|
|
554
|
-
* @returns True if there's an active instance, false if disposed or never created
|
|
555
|
-
*
|
|
556
|
-
* @example
|
|
557
|
-
* ```typescript
|
|
558
|
-
* console.log(SchemaTransformer.hasActiveInstance()); // false
|
|
559
|
-
* const transformer = SchemaTransformer.getInstance();
|
|
560
|
-
* console.log(SchemaTransformer.hasActiveInstance()); // true
|
|
561
|
-
* SchemaTransformer.dispose();
|
|
562
|
-
* console.log(SchemaTransformer.hasActiveInstance()); // false
|
|
563
|
-
* ```
|
|
564
|
-
*
|
|
565
|
-
* @private
|
|
566
|
-
*/
|
|
567
|
-
static hasActiveInstance() {
|
|
568
|
-
return (SchemaTransformer.instance !== null &&
|
|
569
|
-
SchemaTransformer.instance !== undefined &&
|
|
570
|
-
!SchemaTransformer.isInstanceDisposed());
|
|
571
|
-
}
|
|
572
|
-
/**
|
|
573
|
-
* Finds a class declaration by name within a source file.
|
|
574
|
-
*
|
|
575
|
-
* @param sourceFile - The TypeScript source file to search in
|
|
576
|
-
* @param className - The name of the class to find
|
|
577
|
-
* @returns The class declaration node if found, undefined otherwise
|
|
578
|
-
* @private
|
|
579
|
-
*/
|
|
580
|
-
findClassByName(sourceFile, className) {
|
|
581
|
-
let result;
|
|
582
|
-
const visit = (node) => {
|
|
583
|
-
if (ts.isClassDeclaration(node) && node.name?.text === className) {
|
|
584
|
-
result = node;
|
|
585
|
-
return;
|
|
586
|
-
}
|
|
587
|
-
ts.forEachChild(node, visit);
|
|
588
|
-
};
|
|
589
|
-
visit(sourceFile);
|
|
590
|
-
return result;
|
|
591
|
-
}
|
|
592
|
-
/**
|
|
593
|
-
* Transforms a TypeScript class declaration into a schema object.
|
|
594
|
-
*
|
|
595
|
-
* @param classNode - The TypeScript class declaration node
|
|
596
|
-
* @param sourceFile - The source file containing the class (for context)
|
|
597
|
-
* @returns Object containing class name and generated schema
|
|
598
|
-
* @private
|
|
599
|
-
*/
|
|
600
|
-
transformClass(classNode, sourceFile) {
|
|
601
|
-
const className = classNode.name?.text || 'Unknown';
|
|
602
|
-
const properties = this.extractProperties(classNode);
|
|
603
|
-
const schema = this.generateSchema(properties, sourceFile?.fileName);
|
|
604
|
-
return { name: className, schema };
|
|
605
|
-
}
|
|
606
|
-
/**
|
|
607
|
-
* Extracts property information from a class declaration.
|
|
608
|
-
*
|
|
609
|
-
* @param classNode - The TypeScript class declaration node
|
|
610
|
-
* @returns Array of property information including names, types, decorators, and optional status
|
|
611
|
-
* @private
|
|
612
|
-
*/
|
|
613
|
-
extractProperties(classNode) {
|
|
107
|
+
getPropertiesByClassMembers(members, parentClassNode) {
|
|
614
108
|
const properties = [];
|
|
615
|
-
for (const member of
|
|
109
|
+
for (const member of members) {
|
|
616
110
|
if (ts.isPropertyDeclaration(member) &&
|
|
617
111
|
member.name &&
|
|
618
112
|
ts.isIdentifier(member.name)) {
|
|
@@ -620,272 +114,53 @@ class SchemaTransformer {
|
|
|
620
114
|
const type = this.getPropertyType(member);
|
|
621
115
|
const decorators = this.extractDecorators(member);
|
|
622
116
|
const isOptional = !!member.questionToken;
|
|
623
|
-
|
|
117
|
+
const isGeneric = this.isPropertyTypeGeneric(member);
|
|
118
|
+
const isPrimitive = this.isPrimitiveType(type);
|
|
119
|
+
const isClassType = this.isClassType(member);
|
|
120
|
+
const isArray = this.isArrayProperty(member);
|
|
121
|
+
const property = {
|
|
624
122
|
name: propertyName,
|
|
625
123
|
type,
|
|
626
124
|
decorators,
|
|
627
125
|
isOptional,
|
|
628
|
-
|
|
126
|
+
isGeneric,
|
|
127
|
+
originalProperty: member,
|
|
128
|
+
isPrimitive,
|
|
129
|
+
isClassType,
|
|
130
|
+
isArray,
|
|
131
|
+
isRef: false,
|
|
132
|
+
};
|
|
133
|
+
// Check for self-referencing properties to mark as $ref
|
|
134
|
+
if (property.isClassType) {
|
|
135
|
+
const declaration = this.getDeclarationProperty(property);
|
|
136
|
+
if (parentClassNode) {
|
|
137
|
+
if (declaration &&
|
|
138
|
+
declaration.name &&
|
|
139
|
+
this.checker.getSymbolAtLocation(declaration.name) ===
|
|
140
|
+
this.checker.getSymbolAtLocation(parentClassNode.name)) {
|
|
141
|
+
property.isRef = true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
debugger;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
properties.push(property);
|
|
629
149
|
}
|
|
630
150
|
}
|
|
631
151
|
return properties;
|
|
632
152
|
}
|
|
633
|
-
/**
|
|
634
|
-
* Gets the TypeScript type of a property as a string.
|
|
635
|
-
*
|
|
636
|
-
* @param property - The property declaration to analyze
|
|
637
|
-
* @returns String representation of the property's type
|
|
638
|
-
* @private
|
|
639
|
-
*/
|
|
640
153
|
getPropertyType(property) {
|
|
641
154
|
if (property.type) {
|
|
642
155
|
return this.getTypeNodeToString(property.type);
|
|
643
156
|
}
|
|
644
157
|
const type = this.checker.getTypeAtLocation(property);
|
|
645
|
-
return this.
|
|
158
|
+
return this.getStringFromType(type);
|
|
646
159
|
}
|
|
647
|
-
/**
|
|
648
|
-
* Resolves generic types by analyzing the type alias and its arguments.
|
|
649
|
-
* For example, User<Role> where User is a type alias will be resolved to its structure.
|
|
650
|
-
*
|
|
651
|
-
* @param typeNode - The TypeScript type reference node with generic arguments
|
|
652
|
-
* @returns String representation of the resolved type or schema
|
|
653
|
-
* @private
|
|
654
|
-
*/
|
|
655
|
-
resolveGenericType(typeNode) {
|
|
656
|
-
const typeName = typeNode.typeName.text;
|
|
657
|
-
const typeArguments = typeNode.typeArguments;
|
|
658
|
-
if (!typeArguments || typeArguments.length === 0) {
|
|
659
|
-
return typeName;
|
|
660
|
-
}
|
|
661
|
-
// Try to resolve the type using the TypeScript type checker
|
|
662
|
-
const type = this.checker.getTypeAtLocation(typeNode);
|
|
663
|
-
const resolvedType = this.checker.typeToString(type);
|
|
664
|
-
// If we can resolve it to a meaningful structure, use that
|
|
665
|
-
if (resolvedType &&
|
|
666
|
-
resolvedType !== typeName &&
|
|
667
|
-
!resolvedType.includes('any')) {
|
|
668
|
-
// For type aliases like User<Role>, we want to create a synthetic type name
|
|
669
|
-
// that represents the resolved structure
|
|
670
|
-
const typeArgNames = typeArguments.map(arg => {
|
|
671
|
-
if (ts.isTypeReferenceNode(arg) && ts.isIdentifier(arg.typeName)) {
|
|
672
|
-
return arg.typeName.text;
|
|
673
|
-
}
|
|
674
|
-
return this.getTypeNodeToString(arg);
|
|
675
|
-
});
|
|
676
|
-
return `${typeName}_${typeArgNames.join('_')}`;
|
|
677
|
-
}
|
|
678
|
-
return typeName;
|
|
679
|
-
}
|
|
680
|
-
/**
|
|
681
|
-
* Checks if a type string represents a resolved generic type.
|
|
682
|
-
*
|
|
683
|
-
* @param type - The type string to check
|
|
684
|
-
* @returns True if it's a resolved generic type
|
|
685
|
-
* @private
|
|
686
|
-
*/
|
|
687
|
-
isResolvedGenericType(type) {
|
|
688
|
-
// Simple heuristic: resolved generic types contain underscores and
|
|
689
|
-
// the parts after underscore should be known types
|
|
690
|
-
const parts = type.split('_');
|
|
691
|
-
return (parts.length > 1 &&
|
|
692
|
-
parts
|
|
693
|
-
.slice(1)
|
|
694
|
-
.every(part => this.isKnownType(part) || this.isPrimitiveType(part)));
|
|
695
|
-
}
|
|
696
|
-
/**
|
|
697
|
-
* Checks if a type is a known class or interface.
|
|
698
|
-
*
|
|
699
|
-
* @param typeName - The type name to check
|
|
700
|
-
* @returns True if it's a known type
|
|
701
|
-
* @private
|
|
702
|
-
*/
|
|
703
|
-
isKnownType(typeName) {
|
|
704
|
-
// First check if it's a primitive type to avoid unnecessary lookups
|
|
705
|
-
if (this.isPrimitiveType(typeName)) {
|
|
706
|
-
return true;
|
|
707
|
-
}
|
|
708
|
-
try {
|
|
709
|
-
// Use a more conservative approach - check if we can find the class
|
|
710
|
-
// without actually transforming it to avoid side effects
|
|
711
|
-
const found = this.findClassInProject(typeName);
|
|
712
|
-
return found !== null;
|
|
713
|
-
}
|
|
714
|
-
catch {
|
|
715
|
-
return false;
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
/**
|
|
719
|
-
* Finds a class by name in the project without transforming it.
|
|
720
|
-
*
|
|
721
|
-
* @param className - The class name to find
|
|
722
|
-
* @returns True if found, false otherwise
|
|
723
|
-
* @private
|
|
724
|
-
*/
|
|
725
|
-
findClassInProject(className) {
|
|
726
|
-
const sourceFiles = this.program.getSourceFiles().filter(sf => {
|
|
727
|
-
if (sf.isDeclarationFile)
|
|
728
|
-
return false;
|
|
729
|
-
if (sf.fileName.includes('.d.ts'))
|
|
730
|
-
return false;
|
|
731
|
-
if (sf.fileName.includes('node_modules'))
|
|
732
|
-
return false;
|
|
733
|
-
return true;
|
|
734
|
-
});
|
|
735
|
-
for (const sourceFile of sourceFiles) {
|
|
736
|
-
const found = this.findClassByName(sourceFile, className);
|
|
737
|
-
if (found)
|
|
738
|
-
return true;
|
|
739
|
-
}
|
|
740
|
-
return false;
|
|
741
|
-
}
|
|
742
|
-
/**
|
|
743
|
-
* Checks if a type is a primitive type.
|
|
744
|
-
*
|
|
745
|
-
* @param typeName - The type name to check
|
|
746
|
-
* @returns True if it's a primitive type
|
|
747
|
-
* @private
|
|
748
|
-
*/
|
|
749
|
-
isPrimitiveType(typeName) {
|
|
750
|
-
const lowerTypeName = typeName.toLowerCase();
|
|
751
|
-
// Check against all primitive types from constants
|
|
752
|
-
const primitiveTypes = [
|
|
753
|
-
constants.jsPrimitives.String.type.toLowerCase(),
|
|
754
|
-
constants.jsPrimitives.Number.type.toLowerCase(),
|
|
755
|
-
constants.jsPrimitives.Boolean.type.toLowerCase(),
|
|
756
|
-
constants.jsPrimitives.Date.type.toLowerCase(),
|
|
757
|
-
constants.jsPrimitives.Buffer.type.toLowerCase(),
|
|
758
|
-
constants.jsPrimitives.Uint8Array.type.toLowerCase(),
|
|
759
|
-
constants.jsPrimitives.File.type.toLowerCase(),
|
|
760
|
-
constants.jsPrimitives.UploadFile.type.toLowerCase(),
|
|
761
|
-
constants.jsPrimitives.BigInt.type.toLowerCase(),
|
|
762
|
-
];
|
|
763
|
-
return primitiveTypes.includes(lowerTypeName);
|
|
764
|
-
}
|
|
765
|
-
/**
|
|
766
|
-
* Resolves a generic type schema by analyzing the type alias structure.
|
|
767
|
-
*
|
|
768
|
-
* @param resolvedTypeName - The resolved generic type name (e.g., User_Role)
|
|
769
|
-
* @returns OpenAPI schema for the resolved generic type
|
|
770
|
-
* @private
|
|
771
|
-
*/
|
|
772
|
-
resolveGenericTypeSchema(resolvedTypeName) {
|
|
773
|
-
const parts = resolvedTypeName.split('_');
|
|
774
|
-
const baseTypeName = parts[0];
|
|
775
|
-
const typeArgNames = parts.slice(1);
|
|
776
|
-
if (!baseTypeName) {
|
|
777
|
-
return null;
|
|
778
|
-
}
|
|
779
|
-
// Find the original type alias declaration
|
|
780
|
-
const typeAliasSymbol = this.findTypeAliasDeclaration(baseTypeName);
|
|
781
|
-
if (!typeAliasSymbol) {
|
|
782
|
-
return null;
|
|
783
|
-
}
|
|
784
|
-
// Create a schema based on the type alias structure, substituting type parameters
|
|
785
|
-
return this.createSchemaFromTypeAlias(typeAliasSymbol, typeArgNames);
|
|
786
|
-
}
|
|
787
|
-
/**
|
|
788
|
-
* Finds a type alias declaration by name.
|
|
789
|
-
*
|
|
790
|
-
* @param typeName - The type alias name to find
|
|
791
|
-
* @returns The type alias declaration node or null
|
|
792
|
-
* @private
|
|
793
|
-
*/
|
|
794
|
-
findTypeAliasDeclaration(typeName) {
|
|
795
|
-
for (const sourceFile of this.program.getSourceFiles()) {
|
|
796
|
-
if (sourceFile.isDeclarationFile)
|
|
797
|
-
continue;
|
|
798
|
-
const findTypeAlias = (node) => {
|
|
799
|
-
if (ts.isTypeAliasDeclaration(node) && node.name.text === typeName) {
|
|
800
|
-
return node;
|
|
801
|
-
}
|
|
802
|
-
return ts.forEachChild(node, findTypeAlias) || null;
|
|
803
|
-
};
|
|
804
|
-
const result = findTypeAlias(sourceFile);
|
|
805
|
-
if (result)
|
|
806
|
-
return result;
|
|
807
|
-
}
|
|
808
|
-
return null;
|
|
809
|
-
}
|
|
810
|
-
/**
|
|
811
|
-
* Creates a schema from a type alias declaration, substituting type parameters.
|
|
812
|
-
*
|
|
813
|
-
* @param typeAlias - The type alias declaration
|
|
814
|
-
* @param typeArgNames - The concrete type arguments
|
|
815
|
-
* @returns OpenAPI schema for the type alias
|
|
816
|
-
* @private
|
|
817
|
-
*/
|
|
818
|
-
createSchemaFromTypeAlias(typeAlias, typeArgNames) {
|
|
819
|
-
const typeNode = typeAlias.type;
|
|
820
|
-
if (ts.isTypeLiteralNode(typeNode)) {
|
|
821
|
-
const schema = {
|
|
822
|
-
type: 'object',
|
|
823
|
-
properties: {},
|
|
824
|
-
required: [],
|
|
825
|
-
};
|
|
826
|
-
for (const member of typeNode.members) {
|
|
827
|
-
if (ts.isPropertySignature(member) &&
|
|
828
|
-
member.name &&
|
|
829
|
-
ts.isIdentifier(member.name)) {
|
|
830
|
-
const propertyName = member.name.text;
|
|
831
|
-
const isOptional = !!member.questionToken;
|
|
832
|
-
if (member.type) {
|
|
833
|
-
const propertyType = this.resolveTypeParameterInTypeAlias(member.type, typeAlias.typeParameters, typeArgNames);
|
|
834
|
-
const { type, format, nestedSchema } = this.mapTypeToSchema(propertyType);
|
|
835
|
-
if (nestedSchema) {
|
|
836
|
-
schema.properties[propertyName] = nestedSchema;
|
|
837
|
-
}
|
|
838
|
-
else {
|
|
839
|
-
schema.properties[propertyName] = { type };
|
|
840
|
-
if (format)
|
|
841
|
-
schema.properties[propertyName].format = format;
|
|
842
|
-
}
|
|
843
|
-
if (!isOptional) {
|
|
844
|
-
schema.required.push(propertyName);
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
return schema;
|
|
850
|
-
}
|
|
851
|
-
return null;
|
|
852
|
-
}
|
|
853
|
-
/**
|
|
854
|
-
* Resolves type parameters in a type alias to concrete types.
|
|
855
|
-
*
|
|
856
|
-
* @param typeNode - The type node to resolve
|
|
857
|
-
* @param typeParameters - The type parameters of the type alias
|
|
858
|
-
* @param typeArgNames - The concrete type arguments
|
|
859
|
-
* @returns The resolved type string
|
|
860
|
-
* @private
|
|
861
|
-
*/
|
|
862
|
-
resolveTypeParameterInTypeAlias(typeNode, typeParameters, typeArgNames) {
|
|
863
|
-
if (ts.isTypeReferenceNode(typeNode) &&
|
|
864
|
-
ts.isIdentifier(typeNode.typeName)) {
|
|
865
|
-
const typeName = typeNode.typeName.text;
|
|
866
|
-
// Check if this is a type parameter
|
|
867
|
-
if (typeParameters) {
|
|
868
|
-
const paramIndex = typeParameters.findIndex(param => param.name.text === typeName);
|
|
869
|
-
if (paramIndex !== -1 && paramIndex < typeArgNames.length) {
|
|
870
|
-
const resolvedType = typeArgNames[paramIndex];
|
|
871
|
-
return resolvedType || typeName;
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
return typeName;
|
|
875
|
-
}
|
|
876
|
-
return this.getTypeNodeToString(typeNode);
|
|
877
|
-
}
|
|
878
|
-
/**
|
|
879
|
-
* Converts a TypeScript type node to its string representation.
|
|
880
|
-
*
|
|
881
|
-
* @param typeNode - The TypeScript type node to convert
|
|
882
|
-
* @returns String representation of the type
|
|
883
|
-
* @private
|
|
884
|
-
*/
|
|
885
160
|
getTypeNodeToString(typeNode) {
|
|
886
161
|
if (ts.isTypeReferenceNode(typeNode) &&
|
|
887
162
|
ts.isIdentifier(typeNode.typeName)) {
|
|
888
|
-
if (typeNode.typeName.text.toLowerCase()
|
|
163
|
+
if (typeNode.typeName.text.toLowerCase() === 'uploadfile') {
|
|
889
164
|
return 'UploadFile';
|
|
890
165
|
}
|
|
891
166
|
if (typeNode.typeArguments && typeNode.typeArguments.length > 0) {
|
|
@@ -893,12 +168,9 @@ class SchemaTransformer {
|
|
|
893
168
|
if (firstTypeArg &&
|
|
894
169
|
ts.isTypeReferenceNode(firstTypeArg) &&
|
|
895
170
|
ts.isIdentifier(firstTypeArg.typeName)) {
|
|
896
|
-
if (firstTypeArg.typeName.text.toLowerCase()
|
|
171
|
+
if (firstTypeArg.typeName.text.toLowerCase() === 'uploadfile') {
|
|
897
172
|
return 'UploadFile';
|
|
898
173
|
}
|
|
899
|
-
if (typeNode.typeName.text === 'BaseDto') {
|
|
900
|
-
return firstTypeArg.typeName.text;
|
|
901
|
-
}
|
|
902
174
|
}
|
|
903
175
|
return this.resolveGenericType(typeNode);
|
|
904
176
|
}
|
|
@@ -937,13 +209,24 @@ class SchemaTransformer {
|
|
|
937
209
|
return typeText;
|
|
938
210
|
}
|
|
939
211
|
}
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
212
|
+
resolveGenericType(typeNode) {
|
|
213
|
+
const typeName = typeNode.typeName.text;
|
|
214
|
+
const typeArguments = typeNode.typeArguments;
|
|
215
|
+
if (!typeArguments || typeArguments.length === 0) {
|
|
216
|
+
return typeName;
|
|
217
|
+
}
|
|
218
|
+
const type = this.checker.getTypeAtLocation(typeNode);
|
|
219
|
+
const resolvedType = this.getStringFromType(type);
|
|
220
|
+
if (resolvedType &&
|
|
221
|
+
resolvedType !== typeName &&
|
|
222
|
+
!resolvedType.includes('any')) {
|
|
223
|
+
return resolvedType;
|
|
224
|
+
}
|
|
225
|
+
return typeName;
|
|
226
|
+
}
|
|
227
|
+
getStringFromType(type) {
|
|
228
|
+
return this.checker.typeToString(type);
|
|
229
|
+
}
|
|
947
230
|
extractDecorators(member) {
|
|
948
231
|
const decorators = [];
|
|
949
232
|
if (member.modifiers) {
|
|
@@ -962,26 +245,12 @@ class SchemaTransformer {
|
|
|
962
245
|
}
|
|
963
246
|
return decorators;
|
|
964
247
|
}
|
|
965
|
-
/**
|
|
966
|
-
* Gets the name of a decorator from a call expression.
|
|
967
|
-
*
|
|
968
|
-
* @param callExpression - The decorator call expression
|
|
969
|
-
* @returns The decorator name or "unknown" if not identifiable
|
|
970
|
-
* @private
|
|
971
|
-
*/
|
|
972
248
|
getDecoratorName(callExpression) {
|
|
973
249
|
if (ts.isIdentifier(callExpression.expression)) {
|
|
974
250
|
return callExpression.expression.text;
|
|
975
251
|
}
|
|
976
252
|
return 'unknown';
|
|
977
253
|
}
|
|
978
|
-
/**
|
|
979
|
-
* Extracts arguments from a decorator call expression.
|
|
980
|
-
*
|
|
981
|
-
* @param callExpression - The decorator call expression
|
|
982
|
-
* @returns Array of parsed decorator arguments
|
|
983
|
-
* @private
|
|
984
|
-
*/
|
|
985
254
|
getDecoratorArguments(callExpression) {
|
|
986
255
|
return callExpression.arguments.map(arg => {
|
|
987
256
|
if (ts.isNumericLiteral(arg))
|
|
@@ -995,606 +264,1125 @@ class SchemaTransformer {
|
|
|
995
264
|
return arg.getText();
|
|
996
265
|
});
|
|
997
266
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
267
|
+
isPropertyTypeGeneric(property) {
|
|
268
|
+
if (property.type && this.isGenericTypeFromNode(property.type)) {
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
try {
|
|
272
|
+
const type = this.checker.getTypeAtLocation(property);
|
|
273
|
+
return this.isGenericTypeFromSymbol(type);
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
console.warn('Error analyzing property type for generics:', error);
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
isGenericTypeFromNode(typeNode) {
|
|
281
|
+
if (ts.isTypeReferenceNode(typeNode) && typeNode.typeArguments) {
|
|
282
|
+
return typeNode.typeArguments.length > 0;
|
|
283
|
+
}
|
|
284
|
+
// Check for mapped types (e.g., { [K in keyof T]: T[K] })
|
|
285
|
+
if (ts.isMappedTypeNode(typeNode)) {
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
// Check for conditional types (e.g., T extends U ? X : Y)
|
|
289
|
+
if (ts.isConditionalTypeNode(typeNode)) {
|
|
290
|
+
return true;
|
|
291
|
+
}
|
|
292
|
+
// Check for indexed access types (e.g., T[K])
|
|
293
|
+
if (ts.isIndexedAccessTypeNode(typeNode)) {
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
// Check for type operators like keyof, typeof
|
|
297
|
+
if (ts.isTypeOperatorNode(typeNode)) {
|
|
298
|
+
return true;
|
|
299
|
+
}
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
isGenericTypeFromSymbol(type) {
|
|
303
|
+
// First check if it's a simple array type - these should NOT be considered generic
|
|
304
|
+
if (this.isSimpleArrayType(type)) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
// Check if the type has type parameters
|
|
308
|
+
if (type.aliasTypeArguments && type.aliasTypeArguments.length > 0) {
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
// Check if it's a type reference with type arguments
|
|
312
|
+
// But exclude simple arrays which internally use Array<T> representation
|
|
313
|
+
if (type.typeArguments && type.typeArguments.length > 0) {
|
|
314
|
+
const symbol = type.getSymbol();
|
|
315
|
+
if (symbol && symbol.getName() === 'Array') {
|
|
316
|
+
// This is Array<T> - only consider it generic if T itself is a utility type
|
|
317
|
+
const elementType = type.typeArguments[0];
|
|
318
|
+
if (elementType) {
|
|
319
|
+
return this.isUtilityTypeFromType(elementType);
|
|
320
|
+
}
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
const elementType = type.typeArguments[0];
|
|
324
|
+
return this.isUtilityTypeFromType(elementType);
|
|
325
|
+
}
|
|
326
|
+
// Check type flags for generic indicators
|
|
327
|
+
if (type.flags & ts.TypeFlags.TypeParameter) {
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
if (type.flags & ts.TypeFlags.Conditional) {
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
if (type.flags & ts.TypeFlags.Index) {
|
|
334
|
+
return true;
|
|
335
|
+
}
|
|
336
|
+
if (type.flags & ts.TypeFlags.IndexedAccess) {
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
// Check if the type symbol indicates a generic type
|
|
340
|
+
const symbol = type.getSymbol();
|
|
341
|
+
if (symbol && symbol.declarations) {
|
|
342
|
+
for (const declaration of symbol.declarations) {
|
|
343
|
+
// Check for type alias declarations with type parameters
|
|
344
|
+
if (ts.isTypeAliasDeclaration(declaration) &&
|
|
345
|
+
declaration.typeParameters) {
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
// Check for interface declarations with type parameters
|
|
349
|
+
if (ts.isInterfaceDeclaration(declaration) &&
|
|
350
|
+
declaration.typeParameters) {
|
|
351
|
+
return true;
|
|
352
|
+
}
|
|
353
|
+
// Check for class declarations with type parameters
|
|
354
|
+
if (ts.isClassDeclaration(declaration) && declaration.typeParameters) {
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
isUtilityTypeFromType(type) {
|
|
362
|
+
if (!type.aliasSymbol)
|
|
363
|
+
return false;
|
|
364
|
+
const aliasName = type.aliasSymbol.getName();
|
|
365
|
+
const utilityTypes = [
|
|
366
|
+
'Partial',
|
|
367
|
+
'Required',
|
|
368
|
+
'Readonly',
|
|
369
|
+
'Pick',
|
|
370
|
+
'Omit',
|
|
371
|
+
'Record',
|
|
372
|
+
'Exclude',
|
|
373
|
+
'Extract',
|
|
374
|
+
'NonNullable',
|
|
375
|
+
];
|
|
376
|
+
return utilityTypes.includes(aliasName);
|
|
377
|
+
}
|
|
378
|
+
isSimpleArrayType(type) {
|
|
379
|
+
const symbol = type.getSymbol();
|
|
380
|
+
if (!symbol || symbol.getName() !== 'Array') {
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
// Check if this is Array<T> where T is a simple, non-generic type
|
|
384
|
+
if (type.typeArguments &&
|
|
385
|
+
type.typeArguments.length === 1) {
|
|
386
|
+
const elementType = type.typeArguments[0];
|
|
387
|
+
if (!elementType)
|
|
388
|
+
return false;
|
|
389
|
+
// If the element type is a utility type, then this array should be considered generic
|
|
390
|
+
if (this.isUtilityTypeFromType(elementType)) {
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
// If the element type itself has generic parameters, this array is generic
|
|
394
|
+
if (elementType.typeArguments &&
|
|
395
|
+
elementType.typeArguments.length > 0) {
|
|
396
|
+
return false;
|
|
397
|
+
}
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
isPrimitiveType(typeName) {
|
|
403
|
+
const lowerTypeName = typeName.toLowerCase();
|
|
404
|
+
// Check against all primitive types from constants
|
|
405
|
+
const primitiveTypes = [
|
|
406
|
+
constants.jsPrimitives.String.type.toLowerCase(),
|
|
407
|
+
constants.jsPrimitives.Number.type.toLowerCase(),
|
|
408
|
+
constants.jsPrimitives.Boolean.type.toLowerCase(),
|
|
409
|
+
constants.jsPrimitives.Date.type.toLowerCase(),
|
|
410
|
+
constants.jsPrimitives.Buffer.type.toLowerCase(),
|
|
411
|
+
constants.jsPrimitives.Uint8Array.type.toLowerCase(),
|
|
412
|
+
constants.jsPrimitives.File.type.toLowerCase(),
|
|
413
|
+
constants.jsPrimitives.UploadFile.type.toLowerCase(),
|
|
414
|
+
constants.jsPrimitives.BigInt.type.toLowerCase(),
|
|
415
|
+
constants.jsPrimitives.Symbol.type.toLowerCase(),
|
|
416
|
+
constants.jsPrimitives.null.type.toLowerCase(),
|
|
417
|
+
constants.jsPrimitives.Object.type.toLowerCase(),
|
|
418
|
+
constants.jsPrimitives.Array.type.toLowerCase(),
|
|
419
|
+
constants.jsPrimitives.Any.type.toLowerCase(),
|
|
420
|
+
constants.jsPrimitives.Unknown.type.toLowerCase(),
|
|
421
|
+
];
|
|
422
|
+
const primitivesArray = primitiveTypes.map(t => t.concat('[]'));
|
|
423
|
+
return (primitiveTypes.includes(lowerTypeName) ||
|
|
424
|
+
primitivesArray.includes(lowerTypeName));
|
|
425
|
+
}
|
|
426
|
+
static getInstance(tsConfigPath, options) {
|
|
427
|
+
if (!SchemaTransformer.instance) {
|
|
428
|
+
SchemaTransformer.instance = new SchemaTransformer(tsConfigPath, options);
|
|
429
|
+
}
|
|
430
|
+
return SchemaTransformer.instance;
|
|
431
|
+
}
|
|
432
|
+
getSourceFileByClassName(className, sourceOptions) {
|
|
433
|
+
let sourceFiles = [];
|
|
434
|
+
if (sourceOptions?.isExternal) {
|
|
435
|
+
sourceFiles = this.program.getSourceFiles().filter(sf => {
|
|
436
|
+
return (sf.fileName.includes(sourceOptions.packageName) &&
|
|
437
|
+
(!sourceOptions.filePath || sf.fileName === sourceOptions.filePath));
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
sourceFiles = this.program.getSourceFiles().filter(sf => {
|
|
442
|
+
if (sf.isDeclarationFile)
|
|
443
|
+
return false;
|
|
444
|
+
if (sf.fileName.includes('.d.ts'))
|
|
445
|
+
return false;
|
|
446
|
+
if (sf.fileName.includes('node_modules'))
|
|
447
|
+
return false;
|
|
448
|
+
return true;
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
for (const sourceFile of sourceFiles) {
|
|
452
|
+
let node;
|
|
453
|
+
const found = sourceFile.statements.some(stmt => {
|
|
454
|
+
node = stmt;
|
|
455
|
+
return (ts.isClassDeclaration(stmt) &&
|
|
456
|
+
stmt.name &&
|
|
457
|
+
stmt.name.text === className);
|
|
458
|
+
});
|
|
459
|
+
if (found) {
|
|
460
|
+
return { sourceFile, node: node };
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
isClassType(propertyDeclaration) {
|
|
465
|
+
// If there's no explicit type annotation, we can't determine reliably
|
|
466
|
+
if (!propertyDeclaration.type) {
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
// Check if the original property type is an array type
|
|
470
|
+
if (this.isArrayProperty(propertyDeclaration) &&
|
|
471
|
+
ts.isTypeReferenceNode(propertyDeclaration.type
|
|
472
|
+
.elementType)) {
|
|
473
|
+
const type = this.checker.getTypeAtLocation(propertyDeclaration.type.elementType);
|
|
474
|
+
const symbol = type.getSymbol();
|
|
475
|
+
if (symbol && symbol.declarations) {
|
|
476
|
+
return symbol.declarations.some(decl => ts.isClassDeclaration(decl));
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
else if (ts.isTypeReferenceNode(propertyDeclaration.type)) {
|
|
480
|
+
const type = this.checker.getTypeAtLocation(propertyDeclaration.type);
|
|
481
|
+
const symbol = type.getSymbol();
|
|
482
|
+
if (symbol && symbol.declarations) {
|
|
483
|
+
return symbol.declarations.some(decl => ts.isClassDeclaration(decl));
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
return false;
|
|
487
|
+
}
|
|
488
|
+
getDeclarationProperty(property) {
|
|
489
|
+
if (!property.originalProperty.type) {
|
|
490
|
+
return undefined;
|
|
491
|
+
}
|
|
492
|
+
if (ts.isArrayTypeNode(property.originalProperty.type) &&
|
|
493
|
+
ts.isTypeReferenceNode(property.originalProperty.type.elementType)) {
|
|
494
|
+
const type = this.checker.getTypeAtLocation(property.originalProperty.type.elementType);
|
|
495
|
+
const symbol = type.getSymbol();
|
|
496
|
+
if (symbol && symbol.declarations) {
|
|
497
|
+
return symbol.declarations[0];
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
else if (ts.isTypeReferenceNode(property.originalProperty.type)) {
|
|
501
|
+
const type = this.checker.getTypeAtLocation(property.originalProperty.type);
|
|
502
|
+
const symbol = type.getSymbol();
|
|
503
|
+
if (symbol && symbol.declarations) {
|
|
504
|
+
return symbol.declarations[0];
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return undefined;
|
|
508
|
+
}
|
|
509
|
+
isArrayProperty(propertyDeclaration) {
|
|
510
|
+
if (!propertyDeclaration.type) {
|
|
511
|
+
return false;
|
|
512
|
+
}
|
|
513
|
+
return ts.isArrayTypeNode(propertyDeclaration.type);
|
|
514
|
+
}
|
|
515
|
+
getSchemaFromProperties({ properties, visitedClass, transformedSchema, classDeclaration, }) {
|
|
516
|
+
let schema = {};
|
|
517
|
+
const required = [];
|
|
518
|
+
for (const property of properties) {
|
|
519
|
+
schema[property.name] = this.getSchemaFromProperty({
|
|
520
|
+
property,
|
|
521
|
+
visitedClass,
|
|
522
|
+
transformedSchema,
|
|
523
|
+
classDeclaration,
|
|
524
|
+
});
|
|
525
|
+
// this.applyDecorators(property, schema as SchemaType)
|
|
526
|
+
if (!property.isOptional) {
|
|
527
|
+
required.push(property.name);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return {
|
|
1008
531
|
type: 'object',
|
|
1009
|
-
properties:
|
|
1010
|
-
required:
|
|
532
|
+
properties: schema,
|
|
533
|
+
required: required.length ? required : undefined,
|
|
1011
534
|
};
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
535
|
+
}
|
|
536
|
+
getSchemaFromProperty({ property, visitedClass, transformedSchema, classDeclaration, }) {
|
|
537
|
+
let schema = {};
|
|
538
|
+
if (property.isPrimitive) {
|
|
539
|
+
schema = this.getSchemaFromPrimitive(property);
|
|
540
|
+
}
|
|
541
|
+
else if (property.isClassType) {
|
|
542
|
+
const declaration = this.getDeclarationProperty(property);
|
|
543
|
+
if (property.isRef && classDeclaration.name) {
|
|
544
|
+
// Self-referencing property, handle as a reference to avoid infinite recursion
|
|
545
|
+
if (property.isArray) {
|
|
546
|
+
schema.type = 'array';
|
|
547
|
+
schema.items = {
|
|
548
|
+
$ref: `#/components/schemas/${classDeclaration.name.text}`,
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
else {
|
|
552
|
+
schema = {
|
|
553
|
+
$ref: `#/components/schemas/${classDeclaration.name.text}`,
|
|
554
|
+
};
|
|
1019
555
|
}
|
|
1020
556
|
}
|
|
1021
557
|
else {
|
|
1022
|
-
schema
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
// If no decorators are present, apply type-based format specifications
|
|
1029
|
-
if (property.decorators.length === 0) {
|
|
1030
|
-
this.applyTypeBasedFormats(property, schema);
|
|
558
|
+
schema = this.getSchemaFromClass({
|
|
559
|
+
isArray: property.isArray,
|
|
560
|
+
visitedClass,
|
|
561
|
+
transformedSchema,
|
|
562
|
+
declaration,
|
|
563
|
+
});
|
|
1031
564
|
}
|
|
1032
|
-
// Determine if property should be required based on decorators and optional status
|
|
1033
|
-
this.determineRequiredStatus(property, schema);
|
|
1034
565
|
}
|
|
566
|
+
else {
|
|
567
|
+
schema = { type: 'object', properties: {}, additionalProperties: true };
|
|
568
|
+
}
|
|
569
|
+
this.applyDecorators(property, schema);
|
|
1035
570
|
return schema;
|
|
1036
571
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
* @returns Object containing OpenAPI type, optional format, and nested schema
|
|
1044
|
-
* @private
|
|
1045
|
-
*/
|
|
1046
|
-
mapTypeToSchema(type, contextFilePath) {
|
|
1047
|
-
// Handle arrays
|
|
1048
|
-
if (type.endsWith('[]')) {
|
|
1049
|
-
const elementType = type.slice(0, -2);
|
|
1050
|
-
const elementSchema = this.mapTypeToSchema(elementType, contextFilePath);
|
|
1051
|
-
const items = elementSchema.nestedSchema || {
|
|
1052
|
-
type: elementSchema.type,
|
|
1053
|
-
};
|
|
1054
|
-
if (elementSchema.format)
|
|
1055
|
-
items.format = elementSchema.format;
|
|
1056
|
-
return {
|
|
1057
|
-
type: 'array',
|
|
1058
|
-
nestedSchema: {
|
|
1059
|
-
type: 'array',
|
|
1060
|
-
items,
|
|
1061
|
-
properties: {},
|
|
1062
|
-
required: [],
|
|
1063
|
-
},
|
|
1064
|
-
};
|
|
572
|
+
getSchemaFromClass({ transformedSchema = new Map(), visitedClass = new Set(), declaration, isArray, }) {
|
|
573
|
+
let schema = { type: 'object' };
|
|
574
|
+
if (!declaration ||
|
|
575
|
+
!ts.isClassDeclaration(declaration) ||
|
|
576
|
+
!declaration.name) {
|
|
577
|
+
return { type: 'object' };
|
|
1065
578
|
}
|
|
1066
|
-
if (
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
return { type: constants.jsPrimitives.String.value };
|
|
1072
|
-
case constants.jsPrimitives.Number.type.toLowerCase():
|
|
1073
|
-
return { type: constants.jsPrimitives.Number.value };
|
|
1074
|
-
case constants.jsPrimitives.Boolean.type.toLowerCase():
|
|
1075
|
-
return { type: constants.jsPrimitives.Boolean.value };
|
|
1076
|
-
case constants.jsPrimitives.Date.type.toLowerCase():
|
|
1077
|
-
return {
|
|
1078
|
-
type: constants.jsPrimitives.Date.value,
|
|
1079
|
-
format: constants.jsPrimitives.Date.format,
|
|
1080
|
-
};
|
|
1081
|
-
case constants.jsPrimitives.Buffer.type.toLowerCase():
|
|
1082
|
-
case constants.jsPrimitives.Uint8Array.type.toLowerCase():
|
|
1083
|
-
case constants.jsPrimitives.File.type.toLowerCase():
|
|
1084
|
-
return {
|
|
1085
|
-
type: constants.jsPrimitives.Buffer.value,
|
|
1086
|
-
format: constants.jsPrimitives.Buffer.format,
|
|
579
|
+
if (visitedClass.has(declaration)) {
|
|
580
|
+
if (isArray) {
|
|
581
|
+
schema.type = 'array';
|
|
582
|
+
schema.items = {
|
|
583
|
+
$ref: `#/components/schemas/${declaration.name.text}`,
|
|
1087
584
|
};
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
585
|
+
}
|
|
586
|
+
else {
|
|
587
|
+
schema = {
|
|
588
|
+
$ref: `#/components/schemas/${declaration.name.text}`,
|
|
1092
589
|
};
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
if (type.includes('_') && this.isResolvedGenericType(type)) {
|
|
1096
|
-
try {
|
|
1097
|
-
const genericSchema = this.resolveGenericTypeSchema(type);
|
|
1098
|
-
if (genericSchema) {
|
|
1099
|
-
return {
|
|
1100
|
-
type: constants.jsPrimitives.Object.value,
|
|
1101
|
-
nestedSchema: genericSchema,
|
|
1102
|
-
};
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
catch (error) {
|
|
1106
|
-
console.warn(`Failed to resolve generic type ${type}:`, error);
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1109
|
-
// Handle nested objects
|
|
1110
|
-
try {
|
|
1111
|
-
const nestedResult = this.transformByName(type, contextFilePath);
|
|
1112
|
-
// Check if it's a $ref schema (circular reference)
|
|
1113
|
-
if (nestedResult.schema.$ref) {
|
|
1114
|
-
return {
|
|
1115
|
-
type: constants.jsPrimitives.Object.value,
|
|
1116
|
-
nestedSchema: nestedResult.schema,
|
|
1117
|
-
};
|
|
1118
|
-
}
|
|
1119
|
-
return {
|
|
1120
|
-
type: constants.jsPrimitives.Object.value,
|
|
1121
|
-
nestedSchema: nestedResult.schema,
|
|
1122
|
-
};
|
|
1123
|
-
}
|
|
1124
|
-
catch {
|
|
1125
|
-
return { type: constants.jsPrimitives.Object.value };
|
|
1126
|
-
}
|
|
590
|
+
}
|
|
591
|
+
return schema;
|
|
1127
592
|
}
|
|
593
|
+
visitedClass.add(declaration);
|
|
594
|
+
const properties = this.getPropertiesByClassDeclaration(declaration);
|
|
595
|
+
let transformerProps = this.getSchemaFromProperties({
|
|
596
|
+
properties,
|
|
597
|
+
visitedClass,
|
|
598
|
+
transformedSchema: transformedSchema,
|
|
599
|
+
classDeclaration: declaration,
|
|
600
|
+
});
|
|
601
|
+
if (isArray) {
|
|
602
|
+
schema.type = 'array';
|
|
603
|
+
schema.items = {
|
|
604
|
+
type: transformerProps.type,
|
|
605
|
+
properties: transformerProps.properties,
|
|
606
|
+
required: transformerProps.required,
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
else {
|
|
610
|
+
schema.type = transformerProps.type;
|
|
611
|
+
schema.properties = transformerProps.properties;
|
|
612
|
+
schema.required = transformerProps.required;
|
|
613
|
+
}
|
|
614
|
+
transformedSchema.set(declaration.name.text, schema);
|
|
615
|
+
return schema;
|
|
1128
616
|
}
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
617
|
+
getSchemaFromPrimitive(property) {
|
|
618
|
+
const propertySchema = { type: 'object' };
|
|
619
|
+
const propertyType = property.type.toLowerCase().replace('[]', '').trim();
|
|
620
|
+
switch (propertyType) {
|
|
621
|
+
case constants.jsPrimitives.String.value:
|
|
622
|
+
propertySchema.type = constants.jsPrimitives.String.value;
|
|
623
|
+
break;
|
|
624
|
+
case constants.jsPrimitives.Number.value:
|
|
625
|
+
propertySchema.type = constants.jsPrimitives.Number.value;
|
|
626
|
+
propertySchema.format = constants.jsPrimitives.Number.format;
|
|
627
|
+
break;
|
|
628
|
+
case constants.jsPrimitives.BigInt.type.toLocaleLowerCase():
|
|
629
|
+
propertySchema.type = constants.jsPrimitives.BigInt.value;
|
|
630
|
+
propertySchema.format = constants.jsPrimitives.BigInt.format;
|
|
631
|
+
break;
|
|
632
|
+
case constants.jsPrimitives.Date.type.toLocaleLowerCase():
|
|
633
|
+
propertySchema.type = constants.jsPrimitives.Date.value;
|
|
634
|
+
propertySchema.format = constants.jsPrimitives.Date.format;
|
|
635
|
+
break;
|
|
636
|
+
case constants.jsPrimitives.Buffer.value:
|
|
637
|
+
case constants.jsPrimitives.Uint8Array.value:
|
|
638
|
+
case constants.jsPrimitives.File.value:
|
|
639
|
+
case constants.jsPrimitives.UploadFile.value:
|
|
640
|
+
propertySchema.type = constants.jsPrimitives.UploadFile.value;
|
|
641
|
+
propertySchema.format = constants.jsPrimitives.UploadFile.format;
|
|
642
|
+
break;
|
|
643
|
+
case constants.jsPrimitives.Array.value:
|
|
644
|
+
propertySchema.type = constants.jsPrimitives.Array.value;
|
|
645
|
+
break;
|
|
646
|
+
case constants.jsPrimitives.Boolean.value:
|
|
647
|
+
propertySchema.type = constants.jsPrimitives.Boolean.value;
|
|
648
|
+
break;
|
|
649
|
+
case constants.jsPrimitives.Symbol.type.toLocaleLowerCase():
|
|
650
|
+
propertySchema.type = constants.jsPrimitives.Symbol.value;
|
|
651
|
+
break;
|
|
652
|
+
case constants.jsPrimitives.Object.value:
|
|
653
|
+
propertySchema.type = constants.jsPrimitives.Object.value;
|
|
654
|
+
break;
|
|
655
|
+
default:
|
|
656
|
+
propertySchema.type = constants.jsPrimitives.String.value;
|
|
657
|
+
}
|
|
658
|
+
if (property.isArray) {
|
|
659
|
+
propertySchema.type = `array`;
|
|
660
|
+
propertySchema.items = { type: propertyType };
|
|
1152
661
|
}
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
662
|
+
return propertySchema;
|
|
663
|
+
}
|
|
664
|
+
//Todo: implement properly
|
|
665
|
+
applyEnumDecorator(decorator, schema) { }
|
|
666
|
+
applyDecorators(property, schema) {
|
|
667
|
+
for (const decorator of property.decorators) {
|
|
1156
668
|
const decoratorName = decorator.name;
|
|
1157
669
|
switch (decoratorName) {
|
|
1158
670
|
case constants.validatorDecorators.IsString.name:
|
|
1159
|
-
if (!
|
|
1160
|
-
schema.
|
|
1161
|
-
constants.validatorDecorators.IsString.type;
|
|
671
|
+
if (!property.isArray) {
|
|
672
|
+
schema.type = constants.validatorDecorators.IsString.type;
|
|
1162
673
|
}
|
|
1163
|
-
else if (schema.
|
|
1164
|
-
schema.
|
|
1165
|
-
constants.validatorDecorators.IsString.type;
|
|
674
|
+
else if (schema.items) {
|
|
675
|
+
schema.items.type = constants.validatorDecorators.IsString.type;
|
|
1166
676
|
}
|
|
1167
677
|
break;
|
|
1168
678
|
case constants.validatorDecorators.IsInt.name:
|
|
1169
|
-
if (!
|
|
1170
|
-
schema.
|
|
1171
|
-
|
|
1172
|
-
schema.properties[propertyName].format =
|
|
1173
|
-
constants.validatorDecorators.IsInt.format;
|
|
679
|
+
if (!property.isArray) {
|
|
680
|
+
schema.type = constants.validatorDecorators.IsInt.type;
|
|
681
|
+
schema.format = constants.validatorDecorators.IsInt.format;
|
|
1174
682
|
}
|
|
1175
|
-
else if (schema.
|
|
1176
|
-
schema.
|
|
1177
|
-
|
|
1178
|
-
schema.properties[propertyName].items.format =
|
|
1179
|
-
constants.validatorDecorators.IsInt.format;
|
|
683
|
+
else if (schema.items) {
|
|
684
|
+
schema.items.type = constants.validatorDecorators.IsInt.type;
|
|
685
|
+
schema.items.format = constants.validatorDecorators.IsInt.format;
|
|
1180
686
|
}
|
|
1181
687
|
break;
|
|
1182
688
|
case constants.validatorDecorators.IsNumber.name:
|
|
1183
|
-
if (!
|
|
1184
|
-
schema.
|
|
1185
|
-
constants.validatorDecorators.IsNumber.type;
|
|
689
|
+
if (!property.isArray) {
|
|
690
|
+
schema.type = constants.validatorDecorators.IsNumber.type;
|
|
1186
691
|
}
|
|
1187
|
-
else if (schema.
|
|
1188
|
-
schema.
|
|
1189
|
-
constants.validatorDecorators.IsNumber.type;
|
|
692
|
+
else if (schema.items) {
|
|
693
|
+
schema.items.type = constants.validatorDecorators.IsNumber.type;
|
|
1190
694
|
}
|
|
1191
695
|
break;
|
|
1192
696
|
case constants.validatorDecorators.IsBoolean.name:
|
|
1193
|
-
if (!
|
|
1194
|
-
schema.
|
|
1195
|
-
constants.validatorDecorators.IsBoolean.type;
|
|
697
|
+
if (!property.isArray) {
|
|
698
|
+
schema.type = constants.validatorDecorators.IsBoolean.type;
|
|
1196
699
|
}
|
|
1197
|
-
else if (schema.
|
|
1198
|
-
schema.
|
|
1199
|
-
constants.validatorDecorators.IsBoolean.type;
|
|
700
|
+
else if (schema.items) {
|
|
701
|
+
schema.items.type = constants.validatorDecorators.IsBoolean.type;
|
|
1200
702
|
}
|
|
1201
703
|
break;
|
|
1202
704
|
case constants.validatorDecorators.IsEmail.name:
|
|
1203
|
-
if (!
|
|
1204
|
-
schema.
|
|
1205
|
-
constants.validatorDecorators.IsEmail.format;
|
|
705
|
+
if (!property.isArray) {
|
|
706
|
+
schema.format = constants.validatorDecorators.IsEmail.format;
|
|
1206
707
|
}
|
|
1207
|
-
else if (schema.
|
|
1208
|
-
schema.
|
|
1209
|
-
constants.validatorDecorators.IsEmail.format;
|
|
708
|
+
else if (schema.items) {
|
|
709
|
+
schema.items.format = constants.validatorDecorators.IsEmail.format;
|
|
1210
710
|
}
|
|
1211
711
|
break;
|
|
1212
712
|
case constants.validatorDecorators.IsDate.name:
|
|
1213
|
-
if (!
|
|
1214
|
-
schema.
|
|
1215
|
-
|
|
1216
|
-
schema.properties[propertyName].format =
|
|
1217
|
-
constants.validatorDecorators.IsDate.format;
|
|
713
|
+
if (!property.isArray) {
|
|
714
|
+
schema.type = constants.validatorDecorators.IsDate.type;
|
|
715
|
+
schema.format = constants.validatorDecorators.IsDate.format;
|
|
1218
716
|
}
|
|
1219
|
-
else if (schema.
|
|
1220
|
-
schema.
|
|
1221
|
-
|
|
1222
|
-
schema.properties[propertyName].items.format =
|
|
1223
|
-
constants.validatorDecorators.IsDate.format;
|
|
717
|
+
else if (schema.items) {
|
|
718
|
+
schema.items.type = constants.validatorDecorators.IsDate.type;
|
|
719
|
+
schema.items.format = constants.validatorDecorators.IsDate.format;
|
|
1224
720
|
}
|
|
1225
721
|
break;
|
|
1226
722
|
case constants.validatorDecorators.IsNotEmpty.name:
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
723
|
+
property.isOptional = false;
|
|
724
|
+
break;
|
|
725
|
+
case constants.validatorDecorators.IsOptional.name:
|
|
726
|
+
property.isOptional = true;
|
|
1230
727
|
break;
|
|
1231
728
|
case constants.validatorDecorators.MinLength.name:
|
|
1232
|
-
schema.
|
|
729
|
+
schema.minLength = decorator.arguments[0];
|
|
1233
730
|
break;
|
|
1234
731
|
case constants.validatorDecorators.MaxLength.name:
|
|
1235
|
-
schema.
|
|
732
|
+
schema.maxLength = decorator.arguments[0];
|
|
1236
733
|
break;
|
|
1237
734
|
case constants.validatorDecorators.Length.name:
|
|
1238
|
-
schema.
|
|
735
|
+
schema.minLength = decorator.arguments[0];
|
|
1239
736
|
if (decorator.arguments[1]) {
|
|
1240
|
-
schema.
|
|
737
|
+
schema.maxLength = decorator.arguments[1];
|
|
1241
738
|
}
|
|
1242
739
|
break;
|
|
1243
740
|
case constants.validatorDecorators.Min.name:
|
|
1244
|
-
schema.
|
|
741
|
+
schema.minimum = decorator.arguments[0];
|
|
1245
742
|
break;
|
|
1246
743
|
case constants.validatorDecorators.Max.name:
|
|
1247
|
-
schema.
|
|
744
|
+
schema.maximum = decorator.arguments[0];
|
|
1248
745
|
break;
|
|
1249
746
|
case constants.validatorDecorators.IsPositive.name:
|
|
1250
|
-
schema.
|
|
747
|
+
schema.minimum = 0;
|
|
1251
748
|
break;
|
|
1252
749
|
case constants.validatorDecorators.IsArray.name:
|
|
1253
|
-
schema.
|
|
1254
|
-
constants.jsPrimitives.Array.value;
|
|
750
|
+
schema.type = constants.jsPrimitives.Array.value;
|
|
1255
751
|
break;
|
|
1256
752
|
case constants.validatorDecorators.ArrayNotEmpty.name:
|
|
1257
|
-
schema.
|
|
1258
|
-
|
|
1259
|
-
schema.required.push(propertyName);
|
|
1260
|
-
}
|
|
753
|
+
schema.minItems = 1;
|
|
754
|
+
property.isOptional = false;
|
|
1261
755
|
break;
|
|
1262
756
|
case constants.validatorDecorators.ArrayMinSize.name:
|
|
1263
|
-
schema.
|
|
757
|
+
schema.minItems = decorator.arguments[0];
|
|
1264
758
|
break;
|
|
1265
759
|
case constants.validatorDecorators.ArrayMaxSize.name:
|
|
1266
|
-
schema.
|
|
760
|
+
schema.maxItems = decorator.arguments[0];
|
|
1267
761
|
break;
|
|
1268
762
|
case constants.validatorDecorators.IsEnum.name:
|
|
1269
|
-
this.applyEnumDecorator(decorator, schema
|
|
763
|
+
this.applyEnumDecorator(decorator, schema);
|
|
1270
764
|
break;
|
|
1271
765
|
}
|
|
1272
766
|
}
|
|
1273
767
|
}
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
* @param propertyName - The name of the property
|
|
1281
|
-
* @param isArrayType - Whether the property is an array type
|
|
1282
|
-
* @private
|
|
1283
|
-
*/
|
|
1284
|
-
applyEnumDecorator(decorator, schema, propertyName, isArrayType) {
|
|
1285
|
-
if (!decorator.arguments || decorator.arguments.length === 0) {
|
|
1286
|
-
return;
|
|
1287
|
-
}
|
|
1288
|
-
const enumArg = decorator.arguments[0];
|
|
1289
|
-
let enumValues = [];
|
|
1290
|
-
// Handle different enum argument types
|
|
1291
|
-
if (typeof enumArg === 'string') {
|
|
1292
|
-
// This is likely a reference to an enum type name
|
|
1293
|
-
// We need to try to resolve this to actual enum values
|
|
1294
|
-
enumValues = this.resolveEnumValues(enumArg);
|
|
1295
|
-
}
|
|
1296
|
-
else if (typeof enumArg === 'object' && enumArg !== null) {
|
|
1297
|
-
// Object enum - extract values
|
|
1298
|
-
if (Array.isArray(enumArg)) {
|
|
1299
|
-
// Already an array of values
|
|
1300
|
-
enumValues = enumArg;
|
|
1301
|
-
}
|
|
1302
|
-
else {
|
|
1303
|
-
// Enum object - get all values
|
|
1304
|
-
enumValues = Object.values(enumArg);
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
// If we couldn't resolve enum values, fall back to string type without enum constraint
|
|
1308
|
-
if (enumValues.length === 0) {
|
|
1309
|
-
if (!isArrayType) {
|
|
1310
|
-
schema.properties[propertyName].type = 'string';
|
|
1311
|
-
}
|
|
1312
|
-
else if (schema.properties[propertyName].items) {
|
|
1313
|
-
schema.properties[propertyName].items.type = 'string';
|
|
1314
|
-
}
|
|
1315
|
-
return;
|
|
1316
|
-
}
|
|
1317
|
-
// Determine the type based on enum values
|
|
1318
|
-
let enumType = 'string';
|
|
1319
|
-
if (enumValues.length > 0) {
|
|
1320
|
-
const firstValue = enumValues[0];
|
|
1321
|
-
if (typeof firstValue === 'number') {
|
|
1322
|
-
enumType = 'number';
|
|
1323
|
-
}
|
|
1324
|
-
else if (typeof firstValue === 'boolean') {
|
|
1325
|
-
enumType = 'boolean';
|
|
1326
|
-
}
|
|
1327
|
-
}
|
|
1328
|
-
// Apply enum to schema
|
|
1329
|
-
if (!isArrayType) {
|
|
1330
|
-
schema.properties[propertyName].type = enumType;
|
|
1331
|
-
schema.properties[propertyName].enum = enumValues;
|
|
1332
|
-
}
|
|
1333
|
-
else if (schema.properties[propertyName].items) {
|
|
1334
|
-
schema.properties[propertyName].items.type = enumType;
|
|
1335
|
-
schema.properties[propertyName].items.enum = enumValues;
|
|
1336
|
-
}
|
|
1337
|
-
}
|
|
1338
|
-
/**
|
|
1339
|
-
* Attempts to resolve enum values from an enum type name.
|
|
1340
|
-
* This searches through the TypeScript AST to find the enum declaration
|
|
1341
|
-
* and extract its values.
|
|
1342
|
-
*
|
|
1343
|
-
* @param enumTypeName - The name of the enum type
|
|
1344
|
-
* @returns Array of enum values if found, empty array otherwise
|
|
1345
|
-
* @private
|
|
1346
|
-
*/
|
|
1347
|
-
resolveEnumValues(enumTypeName) {
|
|
1348
|
-
// Search for enum declarations in source files
|
|
1349
|
-
for (const sourceFile of this.program.getSourceFiles()) {
|
|
1350
|
-
if (sourceFile.isDeclarationFile)
|
|
1351
|
-
continue;
|
|
1352
|
-
if (sourceFile.fileName.includes('node_modules'))
|
|
1353
|
-
continue;
|
|
1354
|
-
const enumValues = this.findEnumValues(sourceFile, enumTypeName);
|
|
1355
|
-
if (enumValues.length > 0) {
|
|
1356
|
-
return enumValues;
|
|
1357
|
-
}
|
|
768
|
+
transform(cls, sourceOptions) {
|
|
769
|
+
let schema = { type: 'object', properties: {} };
|
|
770
|
+
const result = this.getSourceFileByClassName(cls.name, sourceOptions);
|
|
771
|
+
if (!result?.sourceFile) {
|
|
772
|
+
console.warn(`Class ${cls.name} not found in any source file.`);
|
|
773
|
+
return { name: cls.name, schema: {} };
|
|
1358
774
|
}
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
* @param enumTypeName - The name of the enum to find
|
|
1366
|
-
* @returns Array of enum values if found, empty array otherwise
|
|
1367
|
-
* @private
|
|
1368
|
-
*/
|
|
1369
|
-
findEnumValues(sourceFile, enumTypeName) {
|
|
1370
|
-
let enumValues = [];
|
|
1371
|
-
const visit = (node) => {
|
|
1372
|
-
// Handle TypeScript enum declarations
|
|
1373
|
-
if (ts.isEnumDeclaration(node) && node.name?.text === enumTypeName) {
|
|
1374
|
-
enumValues = this.extractEnumValues(node);
|
|
1375
|
-
return;
|
|
1376
|
-
}
|
|
1377
|
-
// Handle const object declarations (like const Status = { ... } as const)
|
|
1378
|
-
if (ts.isVariableStatement(node)) {
|
|
1379
|
-
for (const declaration of node.declarationList.declarations) {
|
|
1380
|
-
if (ts.isVariableDeclaration(declaration) &&
|
|
1381
|
-
ts.isIdentifier(declaration.name) &&
|
|
1382
|
-
declaration.name.text === enumTypeName &&
|
|
1383
|
-
declaration.initializer) {
|
|
1384
|
-
let initializer = declaration.initializer;
|
|
1385
|
-
// Handle "as const" assertions
|
|
1386
|
-
if (ts.isAsExpression(initializer) && initializer.expression) {
|
|
1387
|
-
initializer = initializer.expression;
|
|
1388
|
-
}
|
|
1389
|
-
enumValues = this.extractObjectEnumValues(initializer);
|
|
1390
|
-
return;
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
ts.forEachChild(node, visit);
|
|
1395
|
-
};
|
|
1396
|
-
visit(sourceFile);
|
|
1397
|
-
return enumValues;
|
|
1398
|
-
}
|
|
1399
|
-
/**
|
|
1400
|
-
* Extracts values from a TypeScript enum declaration.
|
|
1401
|
-
*
|
|
1402
|
-
* @param enumNode - The enum declaration node
|
|
1403
|
-
* @returns Array of enum values
|
|
1404
|
-
* @private
|
|
1405
|
-
*/
|
|
1406
|
-
extractEnumValues(enumNode) {
|
|
1407
|
-
const values = [];
|
|
1408
|
-
for (const member of enumNode.members) {
|
|
1409
|
-
if (member.initializer) {
|
|
1410
|
-
// Handle initialized enum members
|
|
1411
|
-
if (ts.isStringLiteral(member.initializer)) {
|
|
1412
|
-
values.push(member.initializer.text);
|
|
1413
|
-
}
|
|
1414
|
-
else if (ts.isNumericLiteral(member.initializer)) {
|
|
1415
|
-
values.push(Number(member.initializer.text));
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
else {
|
|
1419
|
-
// Handle auto-incremented numeric enums
|
|
1420
|
-
if (values.length === 0) {
|
|
1421
|
-
values.push(0);
|
|
1422
|
-
}
|
|
1423
|
-
else {
|
|
1424
|
-
const lastValue = values[values.length - 1];
|
|
1425
|
-
if (typeof lastValue === 'number') {
|
|
1426
|
-
values.push(lastValue + 1);
|
|
1427
|
-
}
|
|
1428
|
-
}
|
|
1429
|
-
}
|
|
1430
|
-
}
|
|
1431
|
-
return values;
|
|
1432
|
-
}
|
|
1433
|
-
/**
|
|
1434
|
-
* Extracts values from object literal enum (const object as const).
|
|
1435
|
-
*
|
|
1436
|
-
* @param initializer - The object literal initializer
|
|
1437
|
-
* @returns Array of enum values
|
|
1438
|
-
* @private
|
|
1439
|
-
*/
|
|
1440
|
-
extractObjectEnumValues(initializer) {
|
|
1441
|
-
const values = [];
|
|
1442
|
-
if (ts.isObjectLiteralExpression(initializer)) {
|
|
1443
|
-
for (const property of initializer.properties) {
|
|
1444
|
-
if (ts.isPropertyAssignment(property) && property.initializer) {
|
|
1445
|
-
if (ts.isStringLiteral(property.initializer)) {
|
|
1446
|
-
values.push(property.initializer.text);
|
|
1447
|
-
}
|
|
1448
|
-
else if (ts.isNumericLiteral(property.initializer)) {
|
|
1449
|
-
values.push(Number(property.initializer.text));
|
|
1450
|
-
}
|
|
1451
|
-
}
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
return values;
|
|
1455
|
-
}
|
|
1456
|
-
/**
|
|
1457
|
-
* Applies sensible default behaviors for properties without class-validator decorators.
|
|
1458
|
-
* This allows the schema generator to work with plain TypeScript classes.
|
|
1459
|
-
*
|
|
1460
|
-
* @param property - The property information
|
|
1461
|
-
* @param schema - The schema object to modify
|
|
1462
|
-
* @private
|
|
1463
|
-
*/
|
|
1464
|
-
/**
|
|
1465
|
-
* Applies OpenAPI format specifications based on TypeScript types.
|
|
1466
|
-
* This method is called when no decorators are present to set appropriate
|
|
1467
|
-
* format values for primitive types according to OpenAPI specification.
|
|
1468
|
-
*
|
|
1469
|
-
* @param property - The property information containing type details
|
|
1470
|
-
* @param schema - The schema object to modify
|
|
1471
|
-
* @private
|
|
1472
|
-
*/
|
|
1473
|
-
applyTypeBasedFormats(property, schema) {
|
|
1474
|
-
// Skip applying type-based formats to $ref schemas
|
|
1475
|
-
if (this.isRefSchema(schema)) {
|
|
1476
|
-
return;
|
|
1477
|
-
}
|
|
1478
|
-
const propertyName = property.name;
|
|
1479
|
-
const propertyType = property.type.toLowerCase();
|
|
1480
|
-
const propertySchema = schema.properties[propertyName];
|
|
1481
|
-
switch (propertyType) {
|
|
1482
|
-
case constants.jsPrimitives.Number.value:
|
|
1483
|
-
propertySchema.format = constants.jsPrimitives.Number.format;
|
|
1484
|
-
break;
|
|
1485
|
-
case constants.jsPrimitives.BigInt.value:
|
|
1486
|
-
propertySchema.format = constants.jsPrimitives.BigInt.format;
|
|
1487
|
-
break;
|
|
1488
|
-
case constants.jsPrimitives.Date.value:
|
|
1489
|
-
propertySchema.format = constants.jsPrimitives.Date.format;
|
|
1490
|
-
break;
|
|
1491
|
-
case constants.jsPrimitives.Buffer.value:
|
|
1492
|
-
case constants.jsPrimitives.Uint8Array.value:
|
|
1493
|
-
case constants.jsPrimitives.File.value:
|
|
1494
|
-
case constants.jsPrimitives.UploadFile.value:
|
|
1495
|
-
propertySchema.format = constants.jsPrimitives.UploadFile.format;
|
|
1496
|
-
break;
|
|
1497
|
-
}
|
|
1498
|
-
}
|
|
1499
|
-
/**
|
|
1500
|
-
* Determines if a property should be required based on decorators and optional status.
|
|
1501
|
-
*
|
|
1502
|
-
* Logic:
|
|
1503
|
-
* - If property has IsNotEmpty or ArrayNotEmpty decorator, it's required (handled in applyDecorators)
|
|
1504
|
-
* - Otherwise, the property is not required (preserving original behavior)
|
|
1505
|
-
* - The isOptional information is stored for future use and documentation
|
|
1506
|
-
*
|
|
1507
|
-
* @param property - The property information
|
|
1508
|
-
* @param schema - The schema object to modify
|
|
1509
|
-
* @private
|
|
1510
|
-
*/
|
|
1511
|
-
determineRequiredStatus(property, schema) {
|
|
1512
|
-
// Skip determining required status for $ref schemas
|
|
1513
|
-
if (this.isRefSchema(schema)) {
|
|
1514
|
-
return;
|
|
1515
|
-
}
|
|
1516
|
-
const propertyName = property.name;
|
|
1517
|
-
// Check if already marked as required by IsNotEmpty or ArrayNotEmpty decorator
|
|
1518
|
-
const isAlreadyRequired = schema.required.includes(propertyName);
|
|
1519
|
-
// If already required by decorators, don't change it
|
|
1520
|
-
if (isAlreadyRequired) {
|
|
1521
|
-
return;
|
|
1522
|
-
}
|
|
1523
|
-
// If property is optional (has ?), it should not be required unless explicitly marked
|
|
1524
|
-
if (property.isOptional) {
|
|
1525
|
-
return;
|
|
1526
|
-
}
|
|
1527
|
-
// If property is not optional and not already required, make it required
|
|
1528
|
-
schema.required.push(propertyName);
|
|
775
|
+
const properties = this.getPropertiesByClassDeclaration(result.node);
|
|
776
|
+
schema = this.getSchemaFromProperties({
|
|
777
|
+
properties,
|
|
778
|
+
classDeclaration: result.node,
|
|
779
|
+
});
|
|
780
|
+
return { name: cls.name, schema };
|
|
1529
781
|
}
|
|
1530
782
|
}
|
|
783
|
+
function transform(cls, options) {
|
|
784
|
+
// Use the singleton instance instead of creating a temporary one
|
|
785
|
+
const transformer = SchemaTransformer.getInstance(undefined, options);
|
|
786
|
+
return transformer.transform(cls, options?.sourceOptions);
|
|
787
|
+
}
|
|
788
|
+
|
|
1531
789
|
/**
|
|
1532
|
-
*
|
|
1533
|
-
*
|
|
1534
|
-
* @param cls - The class constructor function to transform
|
|
1535
|
-
* @param options - Optional configuration for memory management
|
|
1536
|
-
* @returns Object containing the class name and its corresponding JSON schema
|
|
1537
|
-
*
|
|
1538
|
-
* @example
|
|
1539
|
-
* ```typescript
|
|
1540
|
-
* import { transform } from 'class-validator-to-open-api'
|
|
1541
|
-
* import { User } from './entities/user.js'
|
|
1542
|
-
*
|
|
1543
|
-
* const schema = transform(User)
|
|
1544
|
-
* console.log(schema)
|
|
1545
|
-
* ```
|
|
1546
|
-
*
|
|
1547
|
-
* @example
|
|
1548
|
-
* ```typescript
|
|
1549
|
-
* // With memory optimization
|
|
1550
|
-
* const schema = transform(User, { maxCacheSize: 50, autoCleanup: true })
|
|
1551
|
-
* ```
|
|
1552
|
-
*
|
|
1553
|
-
* @public
|
|
790
|
+
* Pure TypeScript class without any decorators
|
|
791
|
+
* Used to test basic type inference and transformation
|
|
1554
792
|
*/
|
|
1555
|
-
|
|
1556
|
-
|
|
793
|
+
class PureUser {
|
|
794
|
+
id;
|
|
795
|
+
name;
|
|
796
|
+
email;
|
|
797
|
+
age;
|
|
798
|
+
isActive;
|
|
799
|
+
tags;
|
|
800
|
+
metadata;
|
|
801
|
+
createdAt;
|
|
802
|
+
phone;
|
|
803
|
+
bio;
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Pure TypeScript class with primitive types only
|
|
807
|
+
*/
|
|
808
|
+
class SimplePerson {
|
|
809
|
+
firstName;
|
|
810
|
+
lastName;
|
|
811
|
+
age;
|
|
812
|
+
isEmployed;
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Pure TypeScript class with arrays
|
|
816
|
+
*/
|
|
817
|
+
class Product {
|
|
818
|
+
id;
|
|
819
|
+
name;
|
|
820
|
+
price;
|
|
821
|
+
categories;
|
|
822
|
+
scores;
|
|
823
|
+
isAvailable;
|
|
824
|
+
description;
|
|
1557
825
|
}
|
|
1558
826
|
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
827
|
+
/**
|
|
828
|
+
* Additional test classes for pure TypeScript classes tests
|
|
829
|
+
* These classes are used in the pure-classes.test.ts file
|
|
830
|
+
*/
|
|
831
|
+
class OptionalOnlyClass {
|
|
832
|
+
optionalProp;
|
|
833
|
+
anotherOptional;
|
|
1562
834
|
}
|
|
1563
|
-
|
|
1564
|
-
|
|
835
|
+
class UnionTypeClass {
|
|
836
|
+
stringOrNumber;
|
|
837
|
+
optionalUnion;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/**
|
|
841
|
+
* Test cases for pure TypeScript classes (without decorators)
|
|
842
|
+
*/
|
|
843
|
+
node_test.describe('Pure TypeScript Classes', () => {
|
|
844
|
+
node_test.test('should transform PureUser class correctly', () => {
|
|
845
|
+
const result = transform(PureUser);
|
|
846
|
+
const schema = result.schema;
|
|
847
|
+
assert.strictEqual(schema.type, 'object');
|
|
848
|
+
assert.ok(schema.properties);
|
|
849
|
+
// Check basic properties
|
|
850
|
+
assert.strictEqual(schema.properties.id.type, 'number');
|
|
851
|
+
assert.strictEqual(schema.properties.name.type, 'string');
|
|
852
|
+
assert.strictEqual(schema.properties.email.type, 'string');
|
|
853
|
+
assert.strictEqual(schema.properties.age.type, 'number');
|
|
854
|
+
assert.strictEqual(schema.properties.isActive.type, 'boolean');
|
|
855
|
+
// Check array properties
|
|
856
|
+
assert.strictEqual(schema.properties.tags.type, 'array');
|
|
857
|
+
assert.strictEqual(schema.properties.tags.items.type, 'string');
|
|
858
|
+
// Check required fields (all non-optional fields should be required)
|
|
859
|
+
const expectedRequired = [
|
|
860
|
+
'id',
|
|
861
|
+
'name',
|
|
862
|
+
'email',
|
|
863
|
+
'age',
|
|
864
|
+
'isActive',
|
|
865
|
+
'tags',
|
|
866
|
+
'metadata',
|
|
867
|
+
'createdAt',
|
|
868
|
+
];
|
|
869
|
+
assert.deepStrictEqual(schema.required?.sort(), expectedRequired.sort());
|
|
870
|
+
});
|
|
871
|
+
node_test.test('should transform SimplePerson class correctly', () => {
|
|
872
|
+
const result = transform(SimplePerson);
|
|
873
|
+
const schema = result.schema;
|
|
874
|
+
assert.strictEqual(schema.type, 'object');
|
|
875
|
+
assert.ok(schema.properties);
|
|
876
|
+
assert.strictEqual(schema.properties.firstName.type, 'string');
|
|
877
|
+
assert.strictEqual(schema.properties.lastName.type, 'string');
|
|
878
|
+
assert.strictEqual(schema.properties.age.type, 'number');
|
|
879
|
+
assert.strictEqual(schema.properties.isEmployed.type, 'boolean');
|
|
880
|
+
assert.deepStrictEqual(schema.required?.sort(), ['firstName', 'lastName', 'age', 'isEmployed'].sort());
|
|
881
|
+
});
|
|
882
|
+
node_test.test('should transform Product class correctly', () => {
|
|
883
|
+
const result = transform(Product);
|
|
884
|
+
const schema = result.schema;
|
|
885
|
+
assert.strictEqual(schema.type, 'object');
|
|
886
|
+
assert.ok(schema.properties);
|
|
887
|
+
// Check basic properties
|
|
888
|
+
assert.strictEqual(schema.properties.id.type, 'number');
|
|
889
|
+
assert.strictEqual(schema.properties.name.type, 'string');
|
|
890
|
+
assert.strictEqual(schema.properties.price.type, 'number');
|
|
891
|
+
assert.strictEqual(schema.properties.isAvailable.type, 'boolean');
|
|
892
|
+
// Check array property
|
|
893
|
+
assert.strictEqual(schema.properties.categories.type, 'array');
|
|
894
|
+
assert.strictEqual(schema.properties.categories.items.type, 'string');
|
|
895
|
+
assert.strictEqual(schema.properties.scores.type, 'array');
|
|
896
|
+
assert.strictEqual(schema.properties.scores.items.type, 'number');
|
|
897
|
+
// Check optional fields are not in required
|
|
898
|
+
const requiredFields = schema.required || [];
|
|
899
|
+
assert.ok(!requiredFields.includes('description'));
|
|
900
|
+
});
|
|
901
|
+
node_test.test('should handle class with only optional properties', () => {
|
|
902
|
+
const result = transform(OptionalOnlyClass);
|
|
903
|
+
const schema = result.schema;
|
|
904
|
+
assert.strictEqual(schema.type, 'object');
|
|
905
|
+
assert.ok(schema.properties);
|
|
906
|
+
assert.strictEqual(schema.properties.optionalProp.type, 'string');
|
|
907
|
+
assert.strictEqual(schema.properties.anotherOptional.type, 'number');
|
|
908
|
+
// Should have no required fields
|
|
909
|
+
assert.ok(!schema.required || schema.required.length === 0);
|
|
910
|
+
});
|
|
911
|
+
node_test.test('should handle union types', () => {
|
|
912
|
+
const result = transform(UnionTypeClass);
|
|
913
|
+
const schema = result.schema;
|
|
914
|
+
assert.strictEqual(schema.type, 'object');
|
|
915
|
+
assert.ok(schema.properties);
|
|
916
|
+
// Union types should be handled appropriately
|
|
917
|
+
assert.ok(schema.properties.stringOrNumber);
|
|
918
|
+
assert.ok(schema.properties.optionalUnion);
|
|
919
|
+
});
|
|
920
|
+
});
|
|
921
|
+
|
|
922
|
+
/******************************************************************************
|
|
923
|
+
Copyright (c) Microsoft Corporation.
|
|
924
|
+
|
|
925
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
926
|
+
purpose with or without fee is hereby granted.
|
|
927
|
+
|
|
928
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
929
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
930
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
931
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
932
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
933
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
934
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
935
|
+
***************************************************************************** */
|
|
936
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
function __decorate(decorators, target, key, desc) {
|
|
940
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
941
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
942
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
943
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
947
|
+
var e = new Error(message);
|
|
948
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
949
|
+
};
|
|
950
|
+
|
|
951
|
+
var UserStatus;
|
|
952
|
+
(function (UserStatus) {
|
|
953
|
+
UserStatus["ACTIVE"] = "active";
|
|
954
|
+
UserStatus["INACTIVE"] = "inactive";
|
|
955
|
+
UserStatus["PENDING"] = "pending";
|
|
956
|
+
UserStatus["SUSPENDED"] = "suspended";
|
|
957
|
+
})(UserStatus || (UserStatus = {}));
|
|
958
|
+
var Priority;
|
|
959
|
+
(function (Priority) {
|
|
960
|
+
Priority[Priority["LOW"] = 1] = "LOW";
|
|
961
|
+
Priority[Priority["MEDIUM"] = 2] = "MEDIUM";
|
|
962
|
+
Priority[Priority["HIGH"] = 3] = "HIGH";
|
|
963
|
+
Priority[Priority["CRITICAL"] = 4] = "CRITICAL";
|
|
964
|
+
})(Priority || (Priority = {}));
|
|
965
|
+
class DecoratedAddress {
|
|
966
|
+
street;
|
|
967
|
+
city;
|
|
968
|
+
state;
|
|
969
|
+
zipCode;
|
|
970
|
+
country;
|
|
971
|
+
}
|
|
972
|
+
__decorate([
|
|
973
|
+
classValidator.IsString(),
|
|
974
|
+
classValidator.Length(5, 100)
|
|
975
|
+
], DecoratedAddress.prototype, "street", void 0);
|
|
976
|
+
__decorate([
|
|
977
|
+
classValidator.IsString(),
|
|
978
|
+
classValidator.Length(2, 50)
|
|
979
|
+
], DecoratedAddress.prototype, "city", void 0);
|
|
980
|
+
__decorate([
|
|
981
|
+
classValidator.IsString(),
|
|
982
|
+
classValidator.Length(2, 50)
|
|
983
|
+
], DecoratedAddress.prototype, "state", void 0);
|
|
984
|
+
__decorate([
|
|
985
|
+
classValidator.IsString(),
|
|
986
|
+
classValidator.Matches(/^\d{5}(-\d{4})?$/)
|
|
987
|
+
], DecoratedAddress.prototype, "zipCode", void 0);
|
|
988
|
+
__decorate([
|
|
989
|
+
classValidator.IsString(),
|
|
990
|
+
classValidator.Length(2, 50)
|
|
991
|
+
], DecoratedAddress.prototype, "country", void 0);
|
|
992
|
+
class DecoratedUser {
|
|
1565
993
|
id;
|
|
1566
994
|
name;
|
|
1567
995
|
email;
|
|
1568
996
|
age;
|
|
997
|
+
status;
|
|
1569
998
|
isActive;
|
|
1570
999
|
tags;
|
|
1000
|
+
address;
|
|
1571
1001
|
createdAt;
|
|
1572
|
-
|
|
1002
|
+
updatedAt;
|
|
1573
1003
|
}
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1004
|
+
__decorate([
|
|
1005
|
+
classValidator.IsNumber(),
|
|
1006
|
+
classValidator.IsPositive()
|
|
1007
|
+
], DecoratedUser.prototype, "id", void 0);
|
|
1008
|
+
__decorate([
|
|
1009
|
+
classValidator.IsString(),
|
|
1010
|
+
classValidator.Length(2, 50)
|
|
1011
|
+
], DecoratedUser.prototype, "name", void 0);
|
|
1012
|
+
__decorate([
|
|
1013
|
+
classValidator.IsEmail()
|
|
1014
|
+
], DecoratedUser.prototype, "email", void 0);
|
|
1015
|
+
__decorate([
|
|
1016
|
+
classValidator.IsNumber(),
|
|
1017
|
+
classValidator.Min(18),
|
|
1018
|
+
classValidator.Max(120)
|
|
1019
|
+
], DecoratedUser.prototype, "age", void 0);
|
|
1020
|
+
__decorate([
|
|
1021
|
+
classValidator.IsEnum(UserStatus)
|
|
1022
|
+
], DecoratedUser.prototype, "status", void 0);
|
|
1023
|
+
__decorate([
|
|
1024
|
+
classValidator.IsBoolean(),
|
|
1025
|
+
classValidator.IsOptional()
|
|
1026
|
+
], DecoratedUser.prototype, "isActive", void 0);
|
|
1027
|
+
__decorate([
|
|
1028
|
+
classValidator.IsArray(),
|
|
1029
|
+
classValidator.IsString({ each: true })
|
|
1030
|
+
], DecoratedUser.prototype, "tags", void 0);
|
|
1031
|
+
__decorate([
|
|
1032
|
+
classValidator.ValidateNested()
|
|
1033
|
+
], DecoratedUser.prototype, "address", void 0);
|
|
1034
|
+
__decorate([
|
|
1035
|
+
classValidator.IsDate()
|
|
1036
|
+
], DecoratedUser.prototype, "createdAt", void 0);
|
|
1037
|
+
__decorate([
|
|
1038
|
+
classValidator.IsOptional(),
|
|
1039
|
+
classValidator.IsDate()
|
|
1040
|
+
], DecoratedUser.prototype, "updatedAt", void 0);
|
|
1041
|
+
class DecoratedProduct {
|
|
1042
|
+
id;
|
|
1043
|
+
name;
|
|
1044
|
+
description;
|
|
1045
|
+
price;
|
|
1046
|
+
currency;
|
|
1047
|
+
categories;
|
|
1048
|
+
inStock;
|
|
1049
|
+
quantity;
|
|
1050
|
+
images;
|
|
1577
1051
|
}
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1052
|
+
__decorate([
|
|
1053
|
+
classValidator.IsNumber(),
|
|
1054
|
+
classValidator.IsPositive()
|
|
1055
|
+
], DecoratedProduct.prototype, "id", void 0);
|
|
1056
|
+
__decorate([
|
|
1057
|
+
classValidator.IsString(),
|
|
1058
|
+
classValidator.Length(3, 100)
|
|
1059
|
+
], DecoratedProduct.prototype, "name", void 0);
|
|
1060
|
+
__decorate([
|
|
1061
|
+
classValidator.IsString(),
|
|
1062
|
+
classValidator.Length(10, 500)
|
|
1063
|
+
], DecoratedProduct.prototype, "description", void 0);
|
|
1064
|
+
__decorate([
|
|
1065
|
+
classValidator.IsNumber(),
|
|
1066
|
+
classValidator.Min(0)
|
|
1067
|
+
], DecoratedProduct.prototype, "price", void 0);
|
|
1068
|
+
__decorate([
|
|
1069
|
+
classValidator.IsString(),
|
|
1070
|
+
classValidator.Length(3, 20)
|
|
1071
|
+
], DecoratedProduct.prototype, "currency", void 0);
|
|
1072
|
+
__decorate([
|
|
1073
|
+
classValidator.IsArray(),
|
|
1074
|
+
classValidator.IsString({ each: true })
|
|
1075
|
+
], DecoratedProduct.prototype, "categories", void 0);
|
|
1076
|
+
__decorate([
|
|
1077
|
+
classValidator.IsBoolean()
|
|
1078
|
+
], DecoratedProduct.prototype, "inStock", void 0);
|
|
1079
|
+
__decorate([
|
|
1080
|
+
classValidator.IsOptional(),
|
|
1081
|
+
classValidator.IsNumber(),
|
|
1082
|
+
classValidator.Min(0)
|
|
1083
|
+
], DecoratedProduct.prototype, "quantity", void 0);
|
|
1084
|
+
__decorate([
|
|
1085
|
+
classValidator.IsOptional(),
|
|
1086
|
+
classValidator.IsArray(),
|
|
1087
|
+
classValidator.IsString({ each: true })
|
|
1088
|
+
], DecoratedProduct.prototype, "images", void 0);
|
|
1089
|
+
class DecoratedTask {
|
|
1090
|
+
id;
|
|
1091
|
+
title;
|
|
1092
|
+
description;
|
|
1093
|
+
priority;
|
|
1094
|
+
completed;
|
|
1095
|
+
dueDate;
|
|
1096
|
+
assignedTo;
|
|
1097
|
+
tags;
|
|
1098
|
+
createdAt;
|
|
1099
|
+
completedAt;
|
|
1587
1100
|
}
|
|
1588
|
-
|
|
1589
|
-
|
|
1101
|
+
__decorate([
|
|
1102
|
+
classValidator.IsNumber(),
|
|
1103
|
+
classValidator.IsPositive()
|
|
1104
|
+
], DecoratedTask.prototype, "id", void 0);
|
|
1105
|
+
__decorate([
|
|
1106
|
+
classValidator.IsString(),
|
|
1107
|
+
classValidator.Length(5, 100)
|
|
1108
|
+
], DecoratedTask.prototype, "title", void 0);
|
|
1109
|
+
__decorate([
|
|
1110
|
+
classValidator.IsString(),
|
|
1111
|
+
classValidator.Length(10, 1000)
|
|
1112
|
+
], DecoratedTask.prototype, "description", void 0);
|
|
1113
|
+
__decorate([
|
|
1114
|
+
classValidator.IsEnum(Priority)
|
|
1115
|
+
], DecoratedTask.prototype, "priority", void 0);
|
|
1116
|
+
__decorate([
|
|
1117
|
+
classValidator.IsBoolean()
|
|
1118
|
+
], DecoratedTask.prototype, "completed", void 0);
|
|
1119
|
+
__decorate([
|
|
1120
|
+
classValidator.IsDate()
|
|
1121
|
+
], DecoratedTask.prototype, "dueDate", void 0);
|
|
1122
|
+
__decorate([
|
|
1123
|
+
classValidator.IsOptional(),
|
|
1124
|
+
classValidator.ValidateNested()
|
|
1125
|
+
], DecoratedTask.prototype, "assignedTo", void 0);
|
|
1126
|
+
__decorate([
|
|
1127
|
+
classValidator.IsArray(),
|
|
1128
|
+
classValidator.IsString({ each: true }),
|
|
1129
|
+
classValidator.IsOptional()
|
|
1130
|
+
], DecoratedTask.prototype, "tags", void 0);
|
|
1131
|
+
__decorate([
|
|
1132
|
+
classValidator.IsDate()
|
|
1133
|
+
], DecoratedTask.prototype, "createdAt", void 0);
|
|
1134
|
+
__decorate([
|
|
1135
|
+
classValidator.IsOptional(),
|
|
1136
|
+
classValidator.IsDate()
|
|
1137
|
+
], DecoratedTask.prototype, "completedAt", void 0);
|
|
1138
|
+
|
|
1139
|
+
/**
|
|
1140
|
+
* Test cases for decorated classes using class-validator
|
|
1141
|
+
*/
|
|
1142
|
+
node_test.describe('Decorated Classes with class-validator', () => {
|
|
1143
|
+
node_test.test('should transform DecoratedAddress with validation constraints', () => {
|
|
1144
|
+
const result = transform(DecoratedAddress);
|
|
1145
|
+
const schema = result.schema;
|
|
1146
|
+
assert.strictEqual(schema.type, 'object');
|
|
1147
|
+
assert.ok(schema.properties);
|
|
1148
|
+
assert.strictEqual(schema.properties.street.minLength, 5);
|
|
1149
|
+
assert.strictEqual(schema.properties.street.maxLength, 100);
|
|
1150
|
+
assert.strictEqual(schema.properties.city.minLength, 2);
|
|
1151
|
+
assert.strictEqual(schema.properties.city.maxLength, 50);
|
|
1152
|
+
assert.strictEqual(schema.properties.state.minLength, 2);
|
|
1153
|
+
assert.strictEqual(schema.properties.state.maxLength, 50);
|
|
1154
|
+
assert.strictEqual(schema.properties.country.minLength, 2);
|
|
1155
|
+
assert.strictEqual(schema.properties.country.maxLength, 50);
|
|
1156
|
+
assert.strictEqual(schema.properties.zipCode.type, 'string');
|
|
1157
|
+
});
|
|
1158
|
+
node_test.test('should transform DecoratedUser with comprehensive validation', () => {
|
|
1159
|
+
const result = transform(DecoratedUser);
|
|
1160
|
+
const schema = result.schema;
|
|
1161
|
+
assert.strictEqual(schema.type, 'object');
|
|
1162
|
+
assert.ok(schema.properties);
|
|
1163
|
+
assert.strictEqual(schema.properties.email.format, 'email');
|
|
1164
|
+
assert.strictEqual(schema.properties.age.minimum, 18);
|
|
1165
|
+
assert.strictEqual(schema.properties.age.maximum, 120);
|
|
1166
|
+
assert.strictEqual(schema.properties.id.minimum, 0);
|
|
1167
|
+
assert.strictEqual(schema.properties.name.minLength, 2);
|
|
1168
|
+
assert.strictEqual(schema.properties.name.maxLength, 50);
|
|
1169
|
+
assert.ok(schema.properties.status);
|
|
1170
|
+
assert.strictEqual(schema.properties.tags.type, 'array');
|
|
1171
|
+
assert.strictEqual(schema.properties.tags.items.type, 'string');
|
|
1172
|
+
assert.strictEqual(schema.properties.address.type, 'object');
|
|
1173
|
+
assert.strictEqual(schema.properties.createdAt.type, 'string');
|
|
1174
|
+
assert.strictEqual(schema.properties.createdAt.format, 'date-time');
|
|
1175
|
+
const requiredFields = schema.required || [];
|
|
1176
|
+
assert.ok(!requiredFields.includes('isActive'));
|
|
1177
|
+
assert.ok(!requiredFields.includes('updatedAt'));
|
|
1178
|
+
});
|
|
1179
|
+
node_test.test('should transform DecoratedProduct with validation constraints', () => {
|
|
1180
|
+
const result = transform(DecoratedProduct);
|
|
1181
|
+
const schema = result.schema;
|
|
1182
|
+
assert.strictEqual(schema.type, 'object');
|
|
1183
|
+
assert.ok(schema.properties);
|
|
1184
|
+
assert.strictEqual(schema.properties.id.minimum, 0);
|
|
1185
|
+
assert.strictEqual(schema.properties.price.minimum, 0);
|
|
1186
|
+
// Check string length constraints
|
|
1187
|
+
assert.strictEqual(schema.properties.name.minLength, 3);
|
|
1188
|
+
assert.strictEqual(schema.properties.name.maxLength, 100);
|
|
1189
|
+
assert.strictEqual(schema.properties.description.minLength, 10);
|
|
1190
|
+
assert.strictEqual(schema.properties.description.maxLength, 500);
|
|
1191
|
+
assert.strictEqual(schema.properties.currency.minLength, 3);
|
|
1192
|
+
assert.strictEqual(schema.properties.currency.maxLength, 20);
|
|
1193
|
+
assert.strictEqual(schema.properties.categories.type, 'array');
|
|
1194
|
+
assert.strictEqual(schema.properties.categories.items.type, 'string');
|
|
1195
|
+
assert.strictEqual(schema.properties.inStock.type, 'boolean');
|
|
1196
|
+
const requiredFields = schema.required || [];
|
|
1197
|
+
assert.ok(!requiredFields.includes('quantity'));
|
|
1198
|
+
assert.ok(!requiredFields.includes('images'));
|
|
1199
|
+
});
|
|
1200
|
+
node_test.test('should transform DecoratedTask with enum and nested validation', () => {
|
|
1201
|
+
const result = transform(DecoratedTask);
|
|
1202
|
+
const schema = result.schema;
|
|
1203
|
+
assert.strictEqual(schema.type, 'object');
|
|
1204
|
+
assert.ok(schema.properties);
|
|
1205
|
+
// Check string length constraints
|
|
1206
|
+
assert.strictEqual(schema.properties.title.minLength, 5);
|
|
1207
|
+
assert.strictEqual(schema.properties.title.maxLength, 100);
|
|
1208
|
+
assert.strictEqual(schema.properties.description.minLength, 10);
|
|
1209
|
+
assert.strictEqual(schema.properties.description.maxLength, 1000);
|
|
1210
|
+
assert.ok(schema.properties.priority);
|
|
1211
|
+
assert.strictEqual(schema.properties.completed.type, 'boolean');
|
|
1212
|
+
assert.strictEqual(schema.properties.assignedTo?.type, 'object');
|
|
1213
|
+
assert.strictEqual(schema.properties.dueDate.type, 'string');
|
|
1214
|
+
assert.strictEqual(schema.properties.dueDate.format, 'date-time');
|
|
1215
|
+
assert.strictEqual(schema.properties.createdAt.type, 'string');
|
|
1216
|
+
assert.strictEqual(schema.properties.createdAt.format, 'date-time');
|
|
1217
|
+
const requiredFields = schema.required || [];
|
|
1218
|
+
assert.ok(!requiredFields.includes('assignedTo'));
|
|
1219
|
+
assert.ok(!requiredFields.includes('tags'));
|
|
1220
|
+
assert.ok(!requiredFields.includes('completedAt'));
|
|
1221
|
+
});
|
|
1222
|
+
/* Las pruebas de enums se omiten ya que el decorador @IsEnum no está implementado aún */
|
|
1223
|
+
});
|
|
1224
|
+
|
|
1225
|
+
/**
|
|
1226
|
+
* Nested TypeScript classes to test object relationships
|
|
1227
|
+
*/
|
|
1228
|
+
class Address {
|
|
1229
|
+
street;
|
|
1230
|
+
city;
|
|
1231
|
+
state;
|
|
1232
|
+
zipCode;
|
|
1233
|
+
country;
|
|
1234
|
+
}
|
|
1235
|
+
class Role {
|
|
1236
|
+
id;
|
|
1237
|
+
name;
|
|
1238
|
+
permissions;
|
|
1239
|
+
level;
|
|
1240
|
+
}
|
|
1241
|
+
class Company {
|
|
1242
|
+
name;
|
|
1243
|
+
industry;
|
|
1244
|
+
foundedYear;
|
|
1245
|
+
employees;
|
|
1246
|
+
}
|
|
1247
|
+
class NestedUser {
|
|
1248
|
+
id;
|
|
1249
|
+
name;
|
|
1250
|
+
email;
|
|
1251
|
+
address;
|
|
1252
|
+
roles;
|
|
1253
|
+
company;
|
|
1254
|
+
alternativeAddresses;
|
|
1255
|
+
emergencyContact;
|
|
1256
|
+
}
|
|
1257
|
+
/**
|
|
1258
|
+
* Deep nesting example
|
|
1259
|
+
*/
|
|
1260
|
+
class Department {
|
|
1261
|
+
id;
|
|
1262
|
+
name;
|
|
1263
|
+
budget;
|
|
1590
1264
|
}
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1265
|
+
class Team {
|
|
1266
|
+
id;
|
|
1267
|
+
name;
|
|
1268
|
+
department;
|
|
1269
|
+
members;
|
|
1270
|
+
}
|
|
1271
|
+
class TeamMember {
|
|
1272
|
+
id;
|
|
1273
|
+
name;
|
|
1274
|
+
email;
|
|
1275
|
+
role;
|
|
1276
|
+
startDate;
|
|
1596
1277
|
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1278
|
+
class Organization {
|
|
1279
|
+
id;
|
|
1280
|
+
name;
|
|
1281
|
+
teams;
|
|
1282
|
+
headquarters;
|
|
1283
|
+
subsidiaries;
|
|
1599
1284
|
}
|
|
1600
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVuLmpzIiwic291cmNlcyI6WyIuLi9zcmMvdHJhbnNmb3JtZXIuZml4dHVyZXMudHMiLCIuLi9zcmMvdHJhbnNmb3JtZXIudHMiLCIuLi9zcmMvcnVuLnRzIl0sInNvdXJjZXNDb250ZW50IjpbbnVsbCxudWxsLG51bGxdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQVdBLE1BQU0sc0JBQXNCLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsZUFBZSxDQUFDO0FBRTNFLE1BQU0sWUFBWSxHQUFHO0lBQ25CLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRTtBQUMzQyxJQUFBLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFO0lBQzVELE9BQU8sRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRTtJQUM5QyxNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUU7QUFDM0MsSUFBQSxNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRTtJQUM3RCxJQUFJLEVBQUUsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUU7SUFDckMsTUFBTSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFO0lBQzNDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRTtBQUN4QyxJQUFBLElBQUksRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFO0lBQzVELFFBQVEsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRTtBQUNqRCxJQUFBLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFO0FBQzdELElBQUEsVUFBVSxFQUFFLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUU7QUFDckUsSUFBQSxVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRTtBQUNyRSxJQUFBLElBQUksRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFO0NBQzFEO0FBRUQsTUFBTSxtQkFBbUIsR0FBRztJQUMxQixNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUU7SUFDMUMsU0FBUyxFQUFFLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFO0lBQ2hELFNBQVMsRUFBRSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtBQUNoRCxJQUFBLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFO0FBQzFELElBQUEsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUU7QUFDaEUsSUFBQSxRQUFRLEVBQUUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRTtJQUNoRSxVQUFVLEVBQUUsRUFBRSxJQUFJLEVB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
|
|
1285
|
+
|
|
1286
|
+
/**
|
|
1287
|
+
* Test cases for nested TypeScript classes (complex object relationships)
|
|
1288
|
+
*/
|
|
1289
|
+
node_test.describe('Nested TypeScript Classes', () => {
|
|
1290
|
+
node_test.test('should transform Address class correctly', () => {
|
|
1291
|
+
const result = transform(Address);
|
|
1292
|
+
const schema = result.schema;
|
|
1293
|
+
assert.strictEqual(schema.type, 'object');
|
|
1294
|
+
assert.ok(schema.properties);
|
|
1295
|
+
const expectedProperties = ['street', 'city', 'state', 'zipCode', 'country'];
|
|
1296
|
+
expectedProperties.forEach(prop => {
|
|
1297
|
+
assert.ok(schema.properties[prop]);
|
|
1298
|
+
assert.strictEqual(schema.properties[prop].type, 'string');
|
|
1299
|
+
});
|
|
1300
|
+
assert.deepStrictEqual(schema.required?.sort(), expectedProperties.sort());
|
|
1301
|
+
});
|
|
1302
|
+
node_test.test('should transform Role class correctly', () => {
|
|
1303
|
+
const result = transform(Role);
|
|
1304
|
+
const schema = result.schema;
|
|
1305
|
+
assert.strictEqual(schema.type, 'object');
|
|
1306
|
+
assert.ok(schema.properties);
|
|
1307
|
+
assert.strictEqual(schema.properties.id.type, 'number');
|
|
1308
|
+
assert.strictEqual(schema.properties.name.type, 'string');
|
|
1309
|
+
assert.strictEqual(schema.properties.permissions.type, 'array');
|
|
1310
|
+
assert.strictEqual(schema.properties.permissions.items.type, 'string');
|
|
1311
|
+
assert.strictEqual(schema.properties.level.type, 'number');
|
|
1312
|
+
});
|
|
1313
|
+
node_test.test('should transform Company class correctly', () => {
|
|
1314
|
+
const result = transform(Company);
|
|
1315
|
+
const schema = result.schema;
|
|
1316
|
+
assert.strictEqual(schema.type, 'object');
|
|
1317
|
+
assert.ok(schema.properties);
|
|
1318
|
+
assert.strictEqual(schema.properties.name.type, 'string');
|
|
1319
|
+
assert.strictEqual(schema.properties.industry.type, 'string');
|
|
1320
|
+
assert.strictEqual(schema.properties.foundedYear.type, 'number');
|
|
1321
|
+
assert.strictEqual(schema.properties.employees.type, 'number');
|
|
1322
|
+
});
|
|
1323
|
+
node_test.test('should transform NestedUser class correctly', () => {
|
|
1324
|
+
const result = transform(NestedUser);
|
|
1325
|
+
const schema = result.schema;
|
|
1326
|
+
assert.strictEqual(schema.type, 'object');
|
|
1327
|
+
assert.ok(schema.properties);
|
|
1328
|
+
// Check nested object property
|
|
1329
|
+
assert.strictEqual(schema.properties.address.type, 'object');
|
|
1330
|
+
assert.ok(schema.properties.address.properties);
|
|
1331
|
+
// Check array of objects
|
|
1332
|
+
assert.strictEqual(schema.properties.roles.type, 'array');
|
|
1333
|
+
assert.strictEqual(schema.properties.roles.items.type, 'object');
|
|
1334
|
+
// Check company nested object
|
|
1335
|
+
assert.strictEqual(schema.properties.company.type, 'object');
|
|
1336
|
+
assert.ok(schema.properties.company.properties);
|
|
1337
|
+
// Check array of nested objects
|
|
1338
|
+
assert.strictEqual(schema.properties.alternativeAddresses.type, 'array');
|
|
1339
|
+
assert.strictEqual(schema.properties.alternativeAddresses.items.type, 'object');
|
|
1340
|
+
// Check optional nested object
|
|
1341
|
+
const requiredFields = schema.required || [];
|
|
1342
|
+
assert.ok(!requiredFields.includes('emergencyContact'));
|
|
1343
|
+
});
|
|
1344
|
+
node_test.test('should transform Organization class with deep nesting correctly', () => {
|
|
1345
|
+
const result = transform(Organization);
|
|
1346
|
+
const schema = result.schema;
|
|
1347
|
+
assert.strictEqual(schema.type, 'object');
|
|
1348
|
+
assert.ok(schema.properties);
|
|
1349
|
+
// Check teams array with nested objects
|
|
1350
|
+
assert.strictEqual(schema.properties.teams.type, 'array');
|
|
1351
|
+
assert.strictEqual(schema.properties.teams.items.type, 'object');
|
|
1352
|
+
// Check headquarters nested object
|
|
1353
|
+
assert.strictEqual(schema.properties.headquarters.type, 'object');
|
|
1354
|
+
// Check subsidiaries array with inline objects
|
|
1355
|
+
assert.strictEqual(schema.properties.subsidiaries.type, 'array');
|
|
1356
|
+
assert.strictEqual(schema.properties.subsidiaries.items.type, 'object');
|
|
1357
|
+
});
|
|
1358
|
+
node_test.test('should transform Team class with multiple nested levels', () => {
|
|
1359
|
+
const result = transform(Team);
|
|
1360
|
+
const schema = result.schema;
|
|
1361
|
+
assert.strictEqual(schema.type, 'object');
|
|
1362
|
+
assert.ok(schema.properties);
|
|
1363
|
+
// Check nested department
|
|
1364
|
+
assert.strictEqual(schema.properties.department.type, 'object');
|
|
1365
|
+
// Check array of team members
|
|
1366
|
+
assert.strictEqual(schema.properties.members.type, 'array');
|
|
1367
|
+
assert.strictEqual(schema.properties.members.items.type, 'object');
|
|
1368
|
+
});
|
|
1369
|
+
node_test.test('should transform TeamMember class correctly', () => {
|
|
1370
|
+
const result = transform(TeamMember);
|
|
1371
|
+
const schema = result.schema;
|
|
1372
|
+
assert.strictEqual(schema.type, 'object');
|
|
1373
|
+
assert.ok(schema.properties);
|
|
1374
|
+
// Check Date type transformation
|
|
1375
|
+
assert.strictEqual(schema.properties.startDate.type, 'string');
|
|
1376
|
+
assert.strictEqual(schema.properties.startDate.format, 'date-time');
|
|
1377
|
+
});
|
|
1378
|
+
node_test.test('should transform Department class correctly', () => {
|
|
1379
|
+
const result = transform(Department);
|
|
1380
|
+
const schema = result.schema;
|
|
1381
|
+
assert.strictEqual(schema.type, 'object');
|
|
1382
|
+
assert.ok(schema.properties);
|
|
1383
|
+
assert.strictEqual(schema.properties.id.type, 'number');
|
|
1384
|
+
assert.strictEqual(schema.properties.name.type, 'string');
|
|
1385
|
+
assert.strictEqual(schema.properties.budget.type, 'number');
|
|
1386
|
+
});
|
|
1387
|
+
});
|
|
1388
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVuLmpzIiwic291cmNlcyI6WyIuLi9zcmMvdHJhbnNmb3JtZXIuZml4dHVyZXMudHMiLCIuLi9zcmMvdHJhbnNmb3JtZXIudHMiLCIuLi9zcmMvX190ZXN0X18vZW50aXRpZXMvcHVyZS1jbGFzc2VzLnRzIiwiLi4vc3JjL19fdGVzdF9fL2VudGl0aWVzL2FkZGl0aW9uYWwtdGVzdC1jbGFzc2VzLnRzIiwiLi4vc3JjL19fdGVzdF9fL3Rlc3RDYXNlcy9wdXJlLWNsYXNzZXMudGVzdC50cyIsIi4uL25vZGVfbW9kdWxlcy8ucG5wbS9Acm9sbHVwK3BsdWdpbi10eXBlc2NyaXB0QDEyLjEuNF9yb2xsdXBANC40Ni4yX3RzbGliQDIuOC4xX3R5cGVzY3JpcHRANS4wLjIvbm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsIi4uL3NyYy9fX3Rlc3RfXy9lbnRpdGllcy9kZWNvcmF0ZWQtY2xhc3Nlcy50cyIsIi4uL3NyYy9fX3Rlc3RfXy90ZXN0Q2FzZXMvZGVjb3JhdGVkLWNsYXNzZXMudGVzdC50cyIsIi4uL3NyYy9fX3Rlc3RfXy9lbnRpdGllcy9uZXN0ZWQtY2xhc3Nlcy50cyIsIi4uL3NyYy9fX3Rlc3RfXy90ZXN0Q2FzZXMvbmVzdGVkLWNsYXNzZXMudGVzdC50cyJdLCJzb3VyY2VzQ29udGVudCI6W251bGwsbnVsbCxudWxsLG51bGwsbnVsbCwiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlLCBTdXBwcmVzc2VkRXJyb3IsIFN5bWJvbCwgSXRlcmF0b3IgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24oZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXHJcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xyXG4gICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxyXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fYXNzaWduID0gZnVuY3Rpb24oKSB7XHJcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xyXG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdDtcclxuICAgIH1cclxuICAgIHJldHVybiBfX2Fzc2lnbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHtcclxuICAgIHZhciB0ID0ge307XHJcbiAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkgJiYgZS5pbmRleE9mKHApIDwgMClcclxuICAgICAgICB0W3BdID0gc1twXTtcclxuICAgIGlmIChzICE9IG51bGwgJiYgdHlwZW9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPT09IFwiZnVuY3Rpb25cIilcclxuICAgICAgICBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmIChlLmluZGV4T2YocFtpXSkgPCAwICYmIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChzLCBwW2ldKSlcclxuICAgICAgICAgICAgICAgIHRbcFtpXV0gPSBzW3BbaV1dO1xyXG4gICAgICAgIH1cclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xyXG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XHJcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xyXG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcGFyYW0ocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXNEZWNvcmF0ZShjdG9yLCBkZXNjcmlwdG9ySW4sIGRlY29yYXRvcnMsIGNvbnRleHRJbiwgaW5pdGlhbGl6ZXJzLCBleHRyYUluaXRpYWxpemVycykge1xyXG4gICAgZnVuY3Rpb24gYWNjZXB0KGYpIHsgaWYgKGYgIT09IHZvaWQgMCAmJiB0eXBlb2YgZiAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiRnVuY3Rpb24gZXhwZWN0ZWRcIik7IHJldHVybiBmOyB9XHJcbiAgICB2YXIga2luZCA9IGNvbnRleHRJbi5raW5kLCBrZXkgPSBraW5kID09PSBcImdldHRlclwiID8gXCJnZXRcIiA6IGtpbmQgPT09IFwic2V0dGVyXCIgPyBcInNldFwiIDogXCJ2YWx1ZVwiO1xyXG4gICAgdmFyIHRhcmdldCA9ICFkZXNjcmlwdG9ySW4gJiYgY3RvciA/IGNvbnRleHRJbltcInN0YXRpY1wiXSA/IGN0b3IgOiBjdG9yLnByb3RvdHlwZSA6IG51bGw7XHJcbiAgICB2YXIgZGVzY3JpcHRvciA9IGRlc2NyaXB0b3JJbiB8fCAodGFyZ2V0ID8gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGNvbnRleHRJbi5uYW1lKSA6IHt9KTtcclxuICAgIHZhciBfLCBkb25lID0gZmFsc2U7XHJcbiAgICBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gICAgICAgIHZhciBjb250ZXh0ID0ge307XHJcbiAgICAgICAgZm9yICh2YXIgcCBpbiBjb250ZXh0SW4pIGNvbnRleHRbcF0gPSBwID09PSBcImFjY2Vzc1wiID8ge30gOiBjb250ZXh0SW5bcF07XHJcbiAgICAgICAgZm9yICh2YXIgcCBpbiBjb250ZXh0SW4uYWNjZXNzKSBjb250ZXh0LmFjY2Vzc1twXSA9IGNvbnRleHRJbi5hY2Nlc3NbcF07XHJcbiAgICAgICAgY29udGV4dC5hZGRJbml0aWFsaXplciA9IGZ1bmN0aW9uIChmKSB7IGlmIChkb25lKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGFkZCBpbml0aWFsaXplcnMgYWZ0ZXIgZGVjb3JhdGlvbiBoYXMgY29tcGxldGVkXCIpOyBleHRyYUluaXRpYWxpemVycy5wdXNoKGFjY2VwdChmIHx8IG51bGwpKTsgfTtcclxuICAgICAgICB2YXIgcmVzdWx0ID0gKDAsIGRlY29yYXRvcnNbaV0pKGtpbmQgPT09IFwiYWNjZXNzb3JcIiA/IHsgZ2V0OiBkZXNjcmlwdG9yLmdldCwgc2V0OiBkZXNjcmlwdG9yLnNldCB9IDogZGVzY3JpcHRvcltrZXldLCBjb250ZXh0KTtcclxuICAgICAgICBpZiAoa2luZCA9PT0gXCJhY2Nlc3NvclwiKSB7XHJcbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IHZvaWQgMCkgY29udGludWU7XHJcbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IG51bGwgfHwgdHlwZW9mIHJlc3VsdCAhPT0gXCJvYmplY3RcIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk9iamVjdCBleHBlY3RlZFwiKTtcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LmdldCkpIGRlc2NyaXB0b3IuZ2V0ID0gXztcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LnNldCkpIGRlc2NyaXB0b3Iuc2V0ID0gXztcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LmluaXQpKSBpbml0aWFsaXplcnMudW5zaGlmdChfKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAoXyA9IGFjY2VwdChyZXN1bHQpKSB7XHJcbiAgICAgICAgICAgIGlmIChraW5kID09PSBcImZpZWxkXCIpIGluaXRpYWxpemVycy51bnNoaWZ0KF8pO1xyXG4gICAgICAgICAgICBlbHNlIGRlc2NyaXB0b3Jba2V5XSA9IF87XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKHRhcmdldCkgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgY29udGV4dEluLm5hbWUsIGRlc2NyaXB0b3IpO1xyXG4gICAgZG9uZSA9IHRydWU7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19ydW5Jbml0aWFsaXplcnModGhpc0FyZywgaW5pdGlhbGl6ZXJzLCB2YWx1ZSkge1xyXG4gICAgdmFyIHVzZVZhbHVlID0gYXJndW1lbnRzLmxlbmd0aCA+IDI7XHJcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluaXRpYWxpemVycy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIHZhbHVlID0gdXNlVmFsdWUgPyBpbml0aWFsaXplcnNbaV0uY2FsbCh0aGlzQXJnLCB2YWx1ZSkgOiBpbml0aWFsaXplcnNbaV0uY2FsbCh0aGlzQXJnKTtcclxuICAgIH1cclxuICAgIHJldHVybiB1c2VWYWx1ZSA/IHZhbHVlIDogdm9pZCAwO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcHJvcEtleSh4KSB7XHJcbiAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3ltYm9sXCIgPyB4IDogXCJcIi5jb25jYXQoeCk7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zZXRGdW5jdGlvbk5hbWUoZiwgbmFtZSwgcHJlZml4KSB7XHJcbiAgICBpZiAodHlwZW9mIG5hbWUgPT09IFwic3ltYm9sXCIpIG5hbWUgPSBuYW1lLmRlc2NyaXB0aW9uID8gXCJbXCIuY29uY2F0KG5hbWUuZGVzY3JpcHRpb24sIFwiXVwiKSA6IFwiXCI7XHJcbiAgICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KGYsIFwibmFtZVwiLCB7IGNvbmZpZ3VyYWJsZTogdHJ1ZSwgdmFsdWU6IHByZWZpeCA/IFwiXCIuY29uY2F0KHByZWZpeCwgXCIgXCIsIG5hbWUpIDogbmFtZSB9KTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKSB7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QubWV0YWRhdGEgPT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIFJlZmxlY3QubWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdGVyKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xyXG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZ2VuZXJhdG9yKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGcgPSBPYmplY3QuY3JlYXRlKCh0eXBlb2YgSXRlcmF0b3IgPT09IFwiZnVuY3Rpb25cIiA/IEl0ZXJhdG9yIDogT2JqZWN0KS5wcm90b3R5cGUpO1xyXG4gICAgcmV0dXJuIGcubmV4dCA9IHZlcmIoMCksIGdbXCJ0aHJvd1wiXSA9IHZlcmIoMSksIGdbXCJyZXR1cm5cIl0gPSB2ZXJiKDIpLCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcclxuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XHJcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fY3JlYXRlQmluZGluZyA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcclxuICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XHJcbiAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XHJcbiAgICBpZiAoIWRlc2MgfHwgKFwiZ2V0XCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xyXG4gICAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XHJcbiAgICB9XHJcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xyXG59KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xyXG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcclxuICAgIG9bazJdID0gbVtrXTtcclxufSk7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHBvcnRTdGFyKG0sIG8pIHtcclxuICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobywgcCkpIF9fY3JlYXRlQmluZGluZyhvLCBtLCBwKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fdmFsdWVzKG8pIHtcclxuICAgIHZhciBzID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIFN5bWJvbC5pdGVyYXRvciwgbSA9IHMgJiYgb1tzXSwgaSA9IDA7XHJcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcclxuICAgIGlmIChvICYmIHR5cGVvZiBvLmxlbmd0aCA9PT0gXCJudW1iZXJcIikgcmV0dXJuIHtcclxuICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XHJcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihzID8gXCJPYmplY3QgaXMgbm90IGl0ZXJhYmxlLlwiIDogXCJTeW1ib2wuaXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZWFkKG8sIG4pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcclxuICAgIGlmICghbSkgcmV0dXJuIG87XHJcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XHJcbiAgICB9XHJcbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cclxuICAgIGZpbmFsbHkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cclxuICAgIH1cclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZCgpIHtcclxuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTtcclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZEFycmF5cygpIHtcclxuICAgIGZvciAodmFyIHMgPSAwLCBpID0gMCwgaWwgPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgaWw7IGkrKykgcyArPSBhcmd1bWVudHNbaV0ubGVuZ3RoO1xyXG4gICAgZm9yICh2YXIgciA9IEFycmF5KHMpLCBrID0gMCwgaSA9IDA7IGkgPCBpbDsgaSsrKVxyXG4gICAgICAgIGZvciAodmFyIGEgPSBhcmd1bWVudHNbaV0sIGogPSAwLCBqbCA9IGEubGVuZ3RoOyBqIDwgamw7IGorKywgaysrKVxyXG4gICAgICAgICAgICByW2tdID0gYVtqXTtcclxuICAgIHJldHVybiByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWRBcnJheSh0bywgZnJvbSwgcGFjaykge1xyXG4gICAgaWYgKHBhY2sgfHwgYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgZm9yICh2YXIgaSA9IDAsIGwgPSBmcm9tLmxlbmd0aCwgYXI7IGkgPCBsOyBpKyspIHtcclxuICAgICAgICBpZiAoYXIgfHwgIShpIGluIGZyb20pKSB7XHJcbiAgICAgICAgICAgIGlmICghYXIpIGFyID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZnJvbSwgMCwgaSk7XHJcbiAgICAgICAgICAgIGFyW2ldID0gZnJvbVtpXTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdG8uY29uY2F0KGFyIHx8IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGZyb20pKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXQodikge1xyXG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBfX2F3YWl0ID8gKHRoaXMudiA9IHYsIHRoaXMpIDogbmV3IF9fYXdhaXQodik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jR2VuZXJhdG9yKHRoaXNBcmcsIF9hcmd1bWVudHMsIGdlbmVyYXRvcikge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBnID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pLCBpLCBxID0gW107XHJcbiAgICByZXR1cm4gaSA9IE9iamVjdC5jcmVhdGUoKHR5cGVvZiBBc3luY0l0ZXJhdG9yID09PSBcImZ1bmN0aW9uXCIgPyBBc3luY0l0ZXJhdG9yIDogT2JqZWN0KS5wcm90b3R5cGUpLCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIsIGF3YWl0UmV0dXJuKSwgaVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpO1xyXG4gICAgZnVuY3Rpb24gYXdhaXRSZXR1cm4oZikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh2KS50aGVuKGYsIHJlamVjdCk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpZiAoZ1tuXSkgeyBpW25dID0gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChhLCBiKSB7IHEucHVzaChbbiwgdiwgYSwgYl0pID4gMSB8fCByZXN1bWUobiwgdik7IH0pOyB9OyBpZiAoZikgaVtuXSA9IGYoaVtuXSk7IH0gfVxyXG4gICAgZnVuY3Rpb24gcmVzdW1lKG4sIHYpIHsgdHJ5IHsgc3RlcChnW25dKHYpKTsgfSBjYXRjaCAoZSkgeyBzZXR0bGUocVswXVszXSwgZSk7IH0gfVxyXG4gICAgZnVuY3Rpb24gc3RlcChyKSB7IHIudmFsdWUgaW5zdGFuY2VvZiBfX2F3YWl0ID8gUHJvbWlzZS5yZXNvbHZlKHIudmFsdWUudikudGhlbihmdWxmaWxsLCByZWplY3QpIDogc2V0dGxlKHFbMF1bMl0sIHIpOyB9XHJcbiAgICBmdW5jdGlvbiBmdWxmaWxsKHZhbHVlKSB7IHJlc3VtZShcIm5leHRcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiByZWplY3QodmFsdWUpIHsgcmVzdW1lKFwidGhyb3dcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUoZiwgdikgeyBpZiAoZih2KSwgcS5zaGlmdCgpLCBxLmxlbmd0aCkgcmVzdW1lKHFbMF1bMF0sIHFbMF1bMV0pOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jRGVsZWdhdG9yKG8pIHtcclxuICAgIHZhciBpLCBwO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiLCBmdW5jdGlvbiAoZSkgeyB0aHJvdyBlOyB9KSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpW25dID0gb1tuXSA/IGZ1bmN0aW9uICh2KSB7IHJldHVybiAocCA9ICFwKSA/IHsgdmFsdWU6IF9fYXdhaXQob1tuXSh2KSksIGRvbmU6IGZhbHNlIH0gOiBmID8gZih2KSA6IHY7IH0gOiBmOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jVmFsdWVzKG8pIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgbSA9IG9bU3ltYm9sLmFzeW5jSXRlcmF0b3JdLCBpO1xyXG4gICAgcmV0dXJuIG0gPyBtLmNhbGwobykgOiAobyA9IHR5cGVvZiBfX3ZhbHVlcyA9PT0gXCJmdW5jdGlvblwiID8gX192YWx1ZXMobykgOiBvW1N5bWJvbC5pdGVyYXRvcl0oKSwgaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGkpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlbbl0gPSBvW25dICYmIGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7IHYgPSBvW25dKHYpLCBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCB2LmRvbmUsIHYudmFsdWUpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgZCwgdikgeyBQcm9taXNlLnJlc29sdmUodikudGhlbihmdW5jdGlvbih2KSB7IHJlc29sdmUoeyB2YWx1ZTogdiwgZG9uZTogZCB9KTsgfSwgcmVqZWN0KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tYWtlVGVtcGxhdGVPYmplY3QoY29va2VkLCByYXcpIHtcclxuICAgIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvb2tlZCwgXCJyYXdcIiwgeyB2YWx1ZTogcmF3IH0pOyB9IGVsc2UgeyBjb29rZWQucmF3ID0gcmF3OyB9XHJcbiAgICByZXR1cm4gY29va2VkO1xyXG59O1xyXG5cclxudmFyIF9fc2V0TW9kdWxlRGVmYXVsdCA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgdikge1xyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIFwiZGVmYXVsdFwiLCB7IGVudW1lcmFibGU6IHRydWUsIHZhbHVlOiB2IH0pO1xyXG59KSA6IGZ1bmN0aW9uKG8sIHYpIHtcclxuICAgIG9bXCJkZWZhdWx0XCJdID0gdjtcclxufTtcclxuXHJcbnZhciBvd25LZXlzID0gZnVuY3Rpb24obykge1xyXG4gICAgb3duS2V5cyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzIHx8IGZ1bmN0aW9uIChvKSB7XHJcbiAgICAgICAgdmFyIGFyID0gW107XHJcbiAgICAgICAgZm9yICh2YXIgayBpbiBvKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG8sIGspKSBhclthci5sZW5ndGhdID0gaztcclxuICAgICAgICByZXR1cm4gYXI7XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIG93bktleXMobyk7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnRTdGFyKG1vZCkge1xyXG4gICAgaWYgKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgcmV0dXJuIG1vZDtcclxuICAgIHZhciByZXN1bHQgPSB7fTtcclxuICAgIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayA9IG93bktleXMobW9kKSwgaSA9IDA7IGkgPCBrLmxlbmd0aDsgaSsrKSBpZiAoa1tpXSAhPT0gXCJkZWZhdWx0XCIpIF9fY3JlYXRlQmluZGluZyhyZXN1bHQsIG1vZCwga1tpXSk7XHJcbiAgICBfX3NldE1vZHVsZURlZmF1bHQocmVzdWx0LCBtb2QpO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9faW1wb3J0RGVmYXVsdChtb2QpIHtcclxuICAgIHJldHVybiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSA/IG1vZCA6IHsgZGVmYXVsdDogbW9kIH07XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xyXG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xyXG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XHJcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZFNldChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XHJcbiAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XHJcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXJcIik7XHJcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xyXG4gICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2NsYXNzUHJpdmF0ZUZpZWxkSW4oc3RhdGUsIHJlY2VpdmVyKSB7XHJcbiAgICBpZiAocmVjZWl2ZXIgPT09IG51bGwgfHwgKHR5cGVvZiByZWNlaXZlciAhPT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgcmVjZWl2ZXIgIT09IFwiZnVuY3Rpb25cIikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgdXNlICdpbicgb3BlcmF0b3Igb24gbm9uLW9iamVjdFwiKTtcclxuICAgIHJldHVybiB0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyID09PSBzdGF0ZSA6IHN0YXRlLmhhcyhyZWNlaXZlcik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FkZERpc3Bvc2FibGVSZXNvdXJjZShlbnYsIHZhbHVlLCBhc3luYykge1xyXG4gICAgaWYgKHZhbHVlICE9PSBudWxsICYmIHZhbHVlICE9PSB2b2lkIDApIHtcclxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSBcIm9iamVjdFwiICYmIHR5cGVvZiB2YWx1ZSAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiT2JqZWN0IGV4cGVjdGVkLlwiKTtcclxuICAgICAgICB2YXIgZGlzcG9zZSwgaW5uZXI7XHJcbiAgICAgICAgaWYgKGFzeW5jKSB7XHJcbiAgICAgICAgICAgIGlmICghU3ltYm9sLmFzeW5jRGlzcG9zZSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0Rpc3Bvc2UgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgICAgICAgICBkaXNwb3NlID0gdmFsdWVbU3ltYm9sLmFzeW5jRGlzcG9zZV07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChkaXNwb3NlID09PSB2b2lkIDApIHtcclxuICAgICAgICAgICAgaWYgKCFTeW1ib2wuZGlzcG9zZSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5kaXNwb3NlIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgICAgICAgICAgZGlzcG9zZSA9IHZhbHVlW1N5bWJvbC5kaXNwb3NlXTtcclxuICAgICAgICAgICAgaWYgKGFzeW5jKSBpbm5lciA9IGRpc3Bvc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICh0eXBlb2YgZGlzcG9zZSAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiT2JqZWN0IG5vdCBkaXNwb3NhYmxlLlwiKTtcclxuICAgICAgICBpZiAoaW5uZXIpIGRpc3Bvc2UgPSBmdW5jdGlvbigpIHsgdHJ5IHsgaW5uZXIuY2FsbCh0aGlzKTsgfSBjYXRjaCAoZSkgeyByZXR1cm4gUHJvbWlzZS5yZWplY3QoZSk7IH0gfTtcclxuICAgICAgICBlbnYuc3RhY2sucHVzaCh7IHZhbHVlOiB2YWx1ZSwgZGlzcG9zZTogZGlzcG9zZSwgYXN5bmM6IGFzeW5jIH0pO1xyXG4gICAgfVxyXG4gICAgZWxzZSBpZiAoYXN5bmMpIHtcclxuICAgICAgICBlbnYuc3RhY2sucHVzaCh7IGFzeW5jOiB0cnVlIH0pO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHZhbHVlO1xyXG5cclxufVxyXG5cclxudmFyIF9TdXBwcmVzc2VkRXJyb3IgPSB0eXBlb2YgU3VwcHJlc3NlZEVycm9yID09PSBcImZ1bmN0aW9uXCIgPyBTdXBwcmVzc2VkRXJyb3IgOiBmdW5jdGlvbiAoZXJyb3IsIHN1cHByZXNzZWQsIG1lc3NhZ2UpIHtcclxuICAgIHZhciBlID0gbmV3IEVycm9yKG1lc3NhZ2UpO1xyXG4gICAgcmV0dXJuIGUubmFtZSA9IFwiU3VwcHJlc3NlZEVycm9yXCIsIGUuZXJyb3IgPSBlcnJvciwgZS5zdXBwcmVzc2VkID0gc3VwcHJlc3NlZCwgZTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2Rpc3Bvc2VSZXNvdXJjZXMoZW52KSB7XHJcbiAgICBmdW5jdGlvbiBmYWlsKGUpIHtcclxuICAgICAgICBlbnYuZXJyb3IgPSBlbnYuaGFzRXJyb3IgPyBuZXcgX1N1cHByZXNzZWRFcnJvcihlLCBlbnYuZXJyb3IsIFwiQW4gZXJyb3Igd2FzIHN1cHByZXNzZWQgZHVyaW5nIGRpc3Bvc2FsLlwiKSA6IGU7XHJcbiAgICAgICAgZW52Lmhhc0Vycm9yID0gdHJ1ZTtcclxuICAgIH1cclxuICAgIHZhciByLCBzID0gMDtcclxuICAgIGZ1bmN0aW9uIG5leHQoKSB7XHJcbiAgICAgICAgd2hpbGUgKHIgPSBlbnYuc3RhY2sucG9wKCkpIHtcclxuICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgIGlmICghci5hc3luYyAmJiBzID09PSAxKSByZXR1cm4gcyA9IDAsIGVudi5zdGFjay5wdXNoKHIpLCBQcm9taXNlLnJlc29sdmUoKS50aGVuKG5leHQpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHIuZGlzcG9zZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSByLmRpc3Bvc2UuY2FsbChyLnZhbHVlKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoci5hc3luYykgcmV0dXJuIHMgfD0gMiwgUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCkudGhlbihuZXh0LCBmdW5jdGlvbihlKSB7IGZhaWwoZSk7IHJldHVybiBuZXh0KCk7IH0pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZWxzZSBzIHw9IDE7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgIGZhaWwoZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHMgPT09IDEpIHJldHVybiBlbnYuaGFzRXJyb3IgPyBQcm9taXNlLnJlamVjdChlbnYuZXJyb3IpIDogUHJvbWlzZS5yZXNvbHZlKCk7XHJcbiAgICAgICAgaWYgKGVudi5oYXNFcnJvcikgdGhyb3cgZW52LmVycm9yO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5leHQoKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmV3cml0ZVJlbGF0aXZlSW1wb3J0RXh0ZW5zaW9uKHBhdGgsIHByZXNlcnZlSnN4KSB7XHJcbiAgICBpZiAodHlwZW9mIHBhdGggPT09IFwic3RyaW5nXCIgJiYgL15cXC5cXC4/XFwvLy50ZXN0KHBhdGgpKSB7XHJcbiAgICAgICAgcmV0dXJuIHBhdGgucmVwbGFjZSgvXFwuKHRzeCkkfCgoPzpcXC5kKT8pKCg/OlxcLlteLi9dKz8pPylcXC4oW2NtXT8pdHMkL2ksIGZ1bmN0aW9uIChtLCB0c3gsIGQsIGV4dCwgY20pIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRzeCA/IHByZXNlcnZlSnN4ID8gXCIuanN4XCIgOiBcIi5qc1wiIDogZCAmJiAoIWV4dCB8fCAhY20pID8gbSA6IChkICsgZXh0ICsgXCIuXCIgKyBjbS50b0xvd2VyQ2FzZSgpICsgXCJqc1wiKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuICAgIHJldHVybiBwYXRoO1xyXG59XHJcblxyXG5leHBvcnQgZGVmYXVsdCB7XHJcbiAgICBfX2V4dGVuZHM6IF9fZXh0ZW5kcyxcclxuICAgIF9fYXNzaWduOiBfX2Fzc2lnbixcclxuICAgIF9fcmVzdDogX19yZXN0LFxyXG4gICAgX19kZWNvcmF0ZTogX19kZWNvcmF0ZSxcclxuICAgIF9fcGFyYW06IF9fcGFyYW0sXHJcbiAgICBfX2VzRGVjb3JhdGU6IF9fZXNEZWNvcmF0ZSxcclxuICAgIF9fcnVuSW5pdGlhbGl6ZXJzOiBfX3J1bkluaXRpYWxpemVycyxcclxuICAgIF9fcHJvcEtleTogX19wcm9wS2V5LFxyXG4gICAgX19zZXRGdW5jdGlvbk5hbWU6IF9fc2V0RnVuY3Rpb25OYW1lLFxyXG4gICAgX19tZXRhZGF0YTogX19tZXRhZGF0YSxcclxuICAgIF9fYXdhaXRlcjogX19hd2FpdGVyLFxyXG4gICAgX19nZW5lcmF0b3I6IF9fZ2VuZXJhdG9yLFxyXG4gICAgX19jcmVhdGVCaW5kaW5nOiBfX2NyZWF0ZUJpbmRpbmcsXHJcbiAgICBfX2V4cG9ydFN0YXI6IF9fZXhwb3J0U3RhcixcclxuICAgIF9fdmFsdWVzOiBfX3ZhbHVlcyxcclxuICAgIF9fcmVhZDogX19yZWFkLFxyXG4gICAgX19zcHJlYWQ6IF9fc3ByZWFkLFxyXG4gICAgX19zcHJlYWRBcnJheXM6IF9fc3ByZWFkQXJyYXlzLFxyXG4gICAgX19zcHJlYWRBcnJheTogX19zcHJlYWRBcnJheSxcclxuICAgIF9fYXdhaXQ6IF9fYXdhaXQsXHJcbiAgICBfX2FzeW5jR2VuZXJhdG9yOiBfX2FzeW5jR2VuZXJhdG9yLFxyXG4gICAgX19hc3luY0RlbGVnYXRvcjogX19hc3luY0RlbGVnYXRvcixcclxuICAgIF9fYXN5bmNWYWx1ZXM6IF9fYXN5bmNWYWx1ZXMsXHJcbiAgICBfX21ha2VUZW1wbGF0ZU9iamVjdDogX19tYWtlVGVtcGxhdGVPYmplY3QsXHJcbiAgICBfX2ltcG9ydFN0YXI6IF9faW1wb3J0U3RhcixcclxuICAgIF9faW1wb3J0RGVmYXVsdDogX19pbXBvcnREZWZhdWx0LFxyXG4gICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldDogX19jbGFzc1ByaXZhdGVGaWVsZEdldCxcclxuICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQ6IF9fY2xhc3NQcml2YXRlRmllbGRTZXQsXHJcbiAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkSW46IF9fY2xhc3NQcml2YXRlRmllbGRJbixcclxuICAgIF9fYWRkRGlzcG9zYWJsZVJlc291cmNlOiBfX2FkZERpc3Bvc2FibGVSZXNvdXJjZSxcclxuICAgIF9fZGlzcG9zZVJlc291cmNlczogX19kaXNwb3NlUmVzb3VyY2VzLFxyXG4gICAgX19yZXdyaXRlUmVsYXRpdmVJbXBvcnRFeHRlbnNpb246IF9fcmV3cml0ZVJlbGF0aXZlSW1wb3J0RXh0ZW5zaW9uLFxyXG59O1xyXG4iLG51bGwsbnVsbCxudWxsLG51bGxdLCJuYW1lcyI6WyJkZXNjcmliZSIsInRlc3QiLCJJc1N0cmluZyIsIkxlbmd0aCIsIk1hdGNoZXMiLCJJc051bWJlciIsIklzUG9zaXRpdmUiLCJJc0VtYWlsIiwiTWluIiwiTWF4IiwiSXNFbnVtIiwiSXNCb29sZWFuIiwiSXNPcHRpb25hbCIsIklzQXJyYXkiLCJWYWxpZGF0ZU5lc3RlZCIsIklzRGF0ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFXQSxNQUFNLHNCQUFzQixHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLGVBQWUsQ0FBQztBQUUzRSxNQUFNLFlBQVksR0FBRztJQUNuQixNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUU7SUFDM0MsR0FBRyxFQUFFLEVBQUUsSUFBSSxFQUFFLEtBQXNCLENBQUU7SUFDckMsT0FBTyxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQTBCLENBQUU7QUFDN0MsSUFBQSxNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRTtJQUM3RCxPQUFPLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUU7SUFDOUMsTUFBTSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFO0FBQzNDLElBQUEsTUFBTSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7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QUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7QUFFbkQsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUM7QUFDdkQsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUM7UUFFeEQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQztBQUVuQyxRQUFBLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQztBQUN4RCxRQUFBLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFFL0QsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFFNUQsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDOUQsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUM7QUFFbkUsUUFBQSxNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsUUFBUSxJQUFJLEVBQUU7UUFDNUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDL0MsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUM7QUFDbEQsSUFBQSxDQUFDLENBQUM7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LEVBQUUsRUFBRSxDQUFDO0FBQy9ELFFBQUEsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDO1FBRWpFLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUM7QUFFckMsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxTQUFTLENBQUM7QUFFL0QsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLElBQUksRUFBRSxRQUFRLENBQUM7QUFFaEUsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDNUQsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUM7QUFFakUsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDOUQsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUM7QUFFbkUsUUFBQSxNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsUUFBUSxJQUFJLEVBQUU7UUFDNUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDakQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDM0MsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUM7QUFDcEQsSUFBQSxDQUFDLENBQUM7O0FBR0osQ0FBQyxDQUFDOztBQ3JJRjs7QUFFRztNQUVVLE9BQU8sQ0FBQTtBQUNsQixJQUFBLE1BQU07QUFDTixJQUFBLElBQUk7QUFDSixJQUFBLEtBQUs7QUFDTCxJQUFBLE9BQU87QUFDUCxJQUFBLE9BQU87QUFDUjtNQUVZLElBQUksQ0FBQTtBQUNmLElBQUEsRUFBRTtBQUNGLElBQUEsSUFBSTtBQUNKLElBQUEsV0FBVztBQUNYLElBQUEsS0FBSztBQUNOO01BRVksT0FBTyxDQUFBO0FBQ2xCLElBQUEsSUFBSTtBQUNKLElBQUEsUUFBUTtBQUNSLElBQUEsV0FBVztBQUNYLElBQUEsU0FBUztBQUNWO01BUVksVUFBVSxDQUFBO0FBQ3JCLElBQUEsRUFBRTtBQUNGLElBQUEsSUFBSTtBQUNKLElBQUEsS0FBSztBQUNMLElBQUEsT0FBTztBQUNQLElBQUEsS0FBSztBQUNMLElBQUEsT0FBTztBQUNQLElBQUEsb0JBQW9CO0FBQ3BCLElBQUEsZ0JBQWdCO0FBQ2pCO0FBRUQ7O0FBRUc7TUFDVSxVQUFVLENBQUE7QUFDckIsSUFBQSxFQUFFO0FBQ0YsSUFBQSxJQUFJO0FBQ0osSUFBQSxNQUFNO0FBQ1A7TUFFWSxJQUFJLENBQUE7QUFDZixJQUFBLEVBQUU7QUFDRixJQUFBLElBQUk7QUFDSixJQUFBLFVBQVU7QUFDVixJQUFBLE9BQU87QUFDUjtNQUVZLFVBQVUsQ0FBQTtBQUNyQixJQUFBLEVBQUU7QUFDRixJQUFBLElBQUk7QUFDSixJQUFBLEtBQUs7QUFDTCxJQUFBLElBQUk7QUFDSixJQUFBLFNBQVM7QUFDVjtNQVFZLFlBQVksQ0FBQTtBQUN2QixJQUFBLEVBQUU7QUFDRixJQUFBLElBQUk7QUFDSixJQUFBLEtBQUs7QUFDTCxJQUFBLFlBQVk7QUFDWixJQUFBLFlBQVk7QUFDYjs7QUMvRUQ7O0FBRUc7QUFlSEQsa0JBQVEsQ0FBQywyQkFBMkIsRUFBRSxNQUFLO0FBQ3pDLElBQUFDLGNBQUksQ0FBQywwQ0FBMEMsRUFBRSxNQUFLO0FBQ3BELFFBQUEsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQztBQUNqQyxRQUFBLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNO1FBRTVCLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDekMsUUFBQSxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUM7QUFFNUIsUUFBQSxNQUFNLGtCQUFrQixHQUFHLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBQztBQUM1RSxRQUFBLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUc7WUFDaEMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ2xDLFlBQUEsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDNUQsUUFBQSxDQUFDLENBQUM7QUFFRixRQUFBLE1BQU0sQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxrQkFBa0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQztBQUM1RSxJQUFBLENBQUMsQ0FBQztBQUVGLElBQUFBLGNBQUksQ0FBQyx1Q0FBdUMsRUFBRSxNQUFLO0FBQ2pELFFBQUEsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQztBQUM5QixRQUFBLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNO1FBRTVCLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDekMsUUFBQSxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUM7QUFFNUIsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDdkQsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDekQsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUM7QUFDL0QsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDO0FBQ3RFLFFBQUEsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDO0FBQzVELElBQUEsQ0FBQyxDQUFDO0FBRUYsSUFBQUEsY0FBSSxDQUFDLDBDQUEwQyxFQUFFLE1BQUs7QUFDcEQsUUFBQSxNQUFNLE1BQU0sR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDO0FBQ2pDLFFBQUEsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU07UUFFNUIsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQztBQUN6QyxRQUFBLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQztBQUU1QixRQUFBLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQztBQUN6RCxRQUFBLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQztBQUM3RCxRQUFBLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQztBQUNoRSxRQUFBLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQztBQUNoRSxJQUFBLENBQUMsQ0FBQztBQUVGLElBQUFBLGNBQUksQ0FBQyw2Q0FBNkMsRUFBRSxNQUFLO0FBQ3ZELFFBQUEsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQztBQUNwQyxRQUFBLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNO1FBRTVCLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDekMsUUFBQSxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUM7O0FBRzVCLFFBQUEsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDO1FBQzVELE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDOztBQUcvQyxRQUFBLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQztBQUN6RCxRQUFBLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7O0FBR2hFLFFBQUEsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDO1FBQzVELE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDOztBQUcvQyxRQUFBLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDO0FBQ3hFLFFBQUEsTUFBTSxDQUFDLFdBQVcsQ0FDaEIsTUFBTSxDQUFDLFVBQVUsQ0FBQyxvQkFBb0IsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUNqRCxRQUFRLENBQ1Q7O0FBR0QsUUFBQSxNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsUUFBUSxJQUFJLEVBQUU7UUFDNUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUN6RCxJQUFBLENBQUMsQ0FBQztBQUVGLElBQUFBLGNBQUksQ0FBQyxpRUFBaUUsRUFBRSxNQUFLO0FBQzNFLFFBQUEsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLFlBQVksQ0FBQztBQUN0QyxRQUFBLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNO1FBRTVCLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDekMsUUFBQSxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUM7O0FBRzVCLFFBQUEsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDO0FBQ3pELFFBQUEsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQzs7QUFHaEUsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7O0FBR2pFLFFBQUEsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDO0FBQ2hFLFFBQUEsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQztBQUN6RSxJQUFBLENBQUMsQ0FBQztBQUVGLElBQUFBLGNBQUksQ0FBQyx5REFBeUQsRUFBRSxNQUFLO0FBQ25FLFFBQUEsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQztBQUM5QixRQUFBLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNO1FBRTVCLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDekMsUUFBQSxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUM7O0FBRzVCLFFBQUEsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDOztBQUcvRCxRQUFBLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQztBQUMzRCxRQUFBLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDcEUsSUFBQSxDQUFDLENBQUM7QUFFRixJQUFBQSxjQUFJLENBQUMsNkNBQTZDLEVBQUUsTUFBSztBQUN2RCxRQUFBLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxVQUFVLENBQUM7QUFDcEMsUUFBQSxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTTtRQUU1QixNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDO0FBQ3pDLFFBQUEsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDOztBQUc1QixRQUFBLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQztBQUM5RCxRQUFBLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQztBQUNyRSxJQUFBLENBQUMsQ0FBQztBQUVGLElBQUFBLGNBQUksQ0FBQyw2Q0FBNkMsRUFBRSxNQUFLO0FBQ3ZELFFBQUEsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQztBQUNwQyxRQUFBLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNO1FBRTVCLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDekMsUUFBQSxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUM7QUFFNUIsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDdkQsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDekQsUUFBQSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUM7QUFDN0QsSUFBQSxDQUFDLENBQUM7QUFDSixDQUFDLENBQUM7OyIsInhfZ29vZ2xlX2lnbm9yZUxpc3QiOls1XX0=
|