ts-class-to-openapi 1.0.4 → 1.0.6

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