@buildvision/nest-sdk-generator 2.3.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/.eslintrc.js +1 -1
  2. package/.github/workflows/test.yml +35 -0
  3. package/README.md +402 -239
  4. package/build/analyzer/classdeps.js +36 -4
  5. package/build/analyzer/controller.d.ts +2 -14
  6. package/build/analyzer/controller.js +38 -18
  7. package/build/analyzer/controllers.d.ts +2 -2
  8. package/build/analyzer/controllers.js +37 -5
  9. package/build/analyzer/extractor.d.ts +2 -41
  10. package/build/analyzer/extractor.js +63 -66
  11. package/build/analyzer/index.d.ts +2 -6
  12. package/build/analyzer/index.js +107 -86
  13. package/build/analyzer/methods.d.ts +2 -30
  14. package/build/analyzer/methods.js +7 -16
  15. package/build/analyzer/module.js +36 -4
  16. package/build/analyzer/params.d.ts +3 -39
  17. package/build/analyzer/params.js +17 -37
  18. package/build/analyzer/route.js +8 -9
  19. package/build/analyzer/sdk.d.ts +146 -0
  20. package/build/analyzer/sdk.js +120 -0
  21. package/build/analyzer/typedeps.d.ts +15 -0
  22. package/build/analyzer/typedeps.js +62 -10
  23. package/build/bin.js +72 -26
  24. package/build/config.d.ts +13 -0
  25. package/build/config.js +36 -3
  26. package/build/engine/analyze.d.ts +16 -0
  27. package/build/engine/analyze.js +786 -0
  28. package/build/engine/ast.d.ts +24 -0
  29. package/build/engine/ast.js +100 -0
  30. package/build/engine/file-order.d.ts +17 -0
  31. package/build/engine/file-order.js +97 -0
  32. package/build/engine/host.d.ts +63 -0
  33. package/build/engine/host.js +16 -0
  34. package/build/engine/index.d.ts +15 -0
  35. package/build/engine/index.js +93 -0
  36. package/build/engine/ts-morph-compat-host.d.ts +8 -0
  37. package/build/engine/ts-morph-compat-host.js +18 -0
  38. package/build/engine/tsgo-host.d.ts +9 -0
  39. package/build/engine/tsgo-host.js +136 -0
  40. package/build/engine/typescript-host.d.ts +26 -0
  41. package/build/engine/typescript-host.js +142 -0
  42. package/build/generator/genmodules.d.ts +1 -4
  43. package/build/generator/genmodules.js +23 -27
  44. package/build/generator/gentypes.d.ts +1 -1
  45. package/build/generator/gentypes.js +36 -4
  46. package/build/generator/index.d.ts +1 -1
  47. package/build/generator/index.js +91 -69
  48. package/build/generator/prettier.js +43 -9
  49. package/build/generator/sdk-interface.d.ts +1 -1
  50. package/build/generator/sdk-interface.js +5 -5
  51. package/build/logging.d.ts +2 -0
  52. package/build/logging.js +14 -11
  53. package/build/rtk-query-generator/genmodules.d.ts +1 -4
  54. package/build/rtk-query-generator/genmodules.js +27 -31
  55. package/build/rtk-query-generator/index.d.ts +1 -1
  56. package/build/rtk-query-generator/index.js +87 -65
  57. package/build/rtk-query-generator/prettier.js +43 -9
  58. package/build/rtk-query-generator/sdk-interface.js +3 -4
  59. package/build/utils.js +38 -6
  60. package/package.json +29 -11
  61. package/src/analyzer/controller.ts +3 -31
  62. package/src/analyzer/controllers.ts +3 -2
  63. package/src/analyzer/extractor.ts +17 -86
  64. package/src/analyzer/index.ts +5 -11
  65. package/src/analyzer/methods.ts +5 -36
  66. package/src/analyzer/params.ts +13 -55
  67. package/src/analyzer/sdk.ts +247 -0
  68. package/src/analyzer/typedeps.ts +22 -4
  69. package/src/bin.ts +29 -5
  70. package/src/config.ts +15 -0
  71. package/src/engine/analyze.ts +1110 -0
  72. package/src/engine/ast.ts +105 -0
  73. package/src/engine/file-order.ts +104 -0
  74. package/src/engine/host.ts +79 -0
  75. package/src/engine/index.ts +79 -0
  76. package/src/engine/ts-morph-compat-host.ts +20 -0
  77. package/src/engine/tsgo-host.ts +119 -0
  78. package/src/engine/typescript-host.ts +159 -0
  79. package/src/generator/genmodules.ts +9 -4
  80. package/src/generator/gentypes.ts +1 -1
  81. package/src/generator/index.ts +1 -1
  82. package/src/logging.ts +6 -1
  83. package/src/rtk-query-generator/genmodules.ts +9 -4
  84. package/src/rtk-query-generator/index.ts +1 -2
  85. package/src/rtk-query-generator/sdk-interface.ts +2 -3
  86. package/tsconfig.json +7 -6
  87. package/build/analyzer/decorator.d.ts +0 -10
  88. package/build/analyzer/decorator.js +0 -29
  89. package/build/rtk-query-generator/gentypes.d.ts +0 -10
  90. package/build/rtk-query-generator/gentypes.js +0 -62
  91. package/build/tsconfig.tsbuildinfo +0 -1
  92. package/bun.lockb +0 -0
  93. package/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,786 @@
1
+ "use strict";
2
+ /**
3
+ * @file Source API analyzer running on top of an `AnalysisHost` (tsgo or in-process TypeScript)
4
+ *
5
+ * This is a port of the legacy ts-morph analyzer (`src/analyzer`). It performs the same operations, in the same
6
+ * order, with the same messages, so that given the same type checker it produces the same SDK content.
7
+ * The parity tests enforce this by running it against the TypeScript program ts-morph builds.
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.analyzeWithHost = analyzeWithHost;
44
+ const fs = __importStar(require("fs"));
45
+ const os = __importStar(require("os"));
46
+ const path = __importStar(require("path"));
47
+ const chalk = require("chalk");
48
+ const builtin_1 = require("../analyzer/builtin");
49
+ const route_1 = require("../analyzer/route");
50
+ const sdk_1 = require("../analyzer/sdk");
51
+ const typedeps_1 = require("../analyzer/typedeps");
52
+ const logging_1 = require("../logging");
53
+ const utils_1 = require("../utils");
54
+ const ast_1 = require("./ast");
55
+ /**
56
+ * Analyze the source API
57
+ * @param config Generator configuration
58
+ * @param createHost Creates the engine for a given tsconfig file
59
+ */
60
+ async function analyzeWithHost(config, createHost) {
61
+ const started = Date.now();
62
+ const sourcePath = path.resolve(process.cwd(), config.apiInputPath);
63
+ if (!sourcePath)
64
+ (0, logging_1.panic)('Please provide a source directory');
65
+ if (!fs.existsSync(sourcePath))
66
+ (0, logging_1.panic)('Provided source path {magentaBright} does not exist', sourcePath);
67
+ if (!fs.lstatSync(sourcePath).isDirectory())
68
+ (0, logging_1.panic)('Provided source path is not a directory');
69
+ (0, logging_1.debug)(`Analyzing from source directory {yellow}`, sourcePath);
70
+ if (config.jsonOutput) {
71
+ const jsonOutputParentDir = path.dirname(path.resolve(process.cwd(), config.jsonOutput));
72
+ if (!fs.existsSync(jsonOutputParentDir)) {
73
+ (0, logging_1.panic)("Output file's parent directory {magentaBright} does not exist.", jsonOutputParentDir);
74
+ }
75
+ (0, logging_1.debug)('Writing output to {yellow}', config.jsonOutput, config.jsonPrettyOutput ? 'beautified' : 'minified');
76
+ }
77
+ // ====== Find & parse 'tsconfig.json' ====== //
78
+ if (config.tsconfigFile && config.tsconfigFile.includes('/')) {
79
+ (0, logging_1.panic)('Provided tsconfig file name contains slashes');
80
+ }
81
+ const tsConfigFileName = config.tsconfigFile ?? 'tsconfig.json';
82
+ const tsConfigFilePath = path.join(sourcePath, tsConfigFileName);
83
+ if (!fs.existsSync(tsConfigFilePath)) {
84
+ (0, logging_1.panic)('No {yellow} file found in provided source path {yellow}', tsConfigFileName, sourcePath);
85
+ }
86
+ const host = createHost(tsConfigFilePath);
87
+ try {
88
+ // Get the list of all TypeScript files in the source directory
89
+ const sourceTSFiles = host.getProjectFilePaths().map((file) => path.relative(sourcePath, file));
90
+ (0, logging_1.debug)(`Found {magentaBright} source files.`, sourceTSFiles.length);
91
+ // Add them
92
+ (0, logging_1.debug)('\nAdding them to the source project...');
93
+ let progressByTenth = 0;
94
+ const strLen = sourceTSFiles.length.toString().length;
95
+ const hasProgress = (filesTreated) => filesTreated / sourceTSFiles.length >= (progressByTenth + 1) / 10;
96
+ const controllers = [];
97
+ for (let i = 0; i < sourceTSFiles.length; i++) {
98
+ const file = sourceTSFiles[i];
99
+ if (file.endsWith('.controller.ts')) {
100
+ controllers.push(file);
101
+ }
102
+ if (hasProgress(i + 1)) {
103
+ while (hasProgress(i + 1))
104
+ progressByTenth++;
105
+ (0, logging_1.debug)('| Progress: {yellow} ({magentaBright} files) - {green} controller{} found', (progressByTenth * 10).toString().padStart(3, ' ') + '%', `${(i + 1).toString().padStart(strLen, ' ')} / ${sourceTSFiles.length}`, controllers.length.toString().padStart(strLen, ''), controllers.length > 1 ? 's' : '');
106
+ }
107
+ }
108
+ (0, logging_1.debug)('All files were added successfully.\n');
109
+ const modules = analyzeControllers(host, controllers, sourcePath);
110
+ // Builtin magic types are concatenated **after** the configuration's ones, as this allows users to
111
+ // override the builtin ones if they want. Do **not** change the concatenation order!
112
+ const magicTypes = (config.magicTypes ?? []).concat(builtin_1.builtinMagicTypes);
113
+ const typesCache = new TypesExtractor(host, sourcePath, magicTypes);
114
+ const typesToExtract = (0, sdk_1.locateTypesFile)((0, sdk_1.flattenSdkResolvedTypes)(modules));
115
+ (0, logging_1.debug)('\n==== Extracting {} type' + (typesToExtract.length > 1 ? 's' : '') + ' ====\n', typesToExtract.length);
116
+ for (const loc of typesToExtract) {
117
+ const result = typesCache.extractType(loc);
118
+ if (result instanceof Error) {
119
+ (0, logging_1.panic)(result.message);
120
+ }
121
+ }
122
+ const content = {
123
+ modules,
124
+ types: typesCache.extracted,
125
+ };
126
+ if (config.jsonOutput) {
127
+ fs.writeFileSync(config.jsonOutput, (0, sdk_1.serializeSdkContent)(content, !!config.jsonPrettyOutput), 'utf8');
128
+ }
129
+ (0, logging_1.debug)('\n===== Done in {green}! ====', ((Date.now() - started) / 1000).toFixed(2) + 's');
130
+ return content;
131
+ }
132
+ finally {
133
+ host.dispose();
134
+ }
135
+ }
136
+ /**
137
+ * Get a source file from the program, throwing like ts-morph's `project.getSourceFileOrThrow()`
138
+ */
139
+ function getSourceFileOrThrow(host, absolutePath) {
140
+ const file = host.getSourceFile(absolutePath);
141
+ if (!file) {
142
+ throw new Error(`Could not find source file in project at the provided path: ${absolutePath}`);
143
+ }
144
+ return file;
145
+ }
146
+ // =============================================================================================================== //
147
+ // Controllers & modules (see src/analyzer/controllers.ts, src/analyzer/controller.ts, src/analyzer/module.ts) //
148
+ // =============================================================================================================== //
149
+ function analyzeControllers(host, controllers, absoluteSrcPath) {
150
+ /** Hierarchised SDK informations */
151
+ const collected = new Map();
152
+ const usedControllerNames = new Set();
153
+ /**
154
+ * Modules cache: contains for a given directory the nearest module file's path and name
155
+ * This allows to avoid having to analyze the whole directory structure for each controller
156
+ */
157
+ const modulesCache = new Map();
158
+ /**
159
+ * Path of the declared modules
160
+ * When a module is detected and put in the cache, its name is registered here along with its path
161
+ * This allows to ensure there is no name clash between two different modules
162
+ */
163
+ const declaredModulesPath = new Map();
164
+ (0, logging_1.debug)(`Analyzing {yellow} controllers...`, controllers.length);
165
+ controllers.forEach((relativeControllerPath, i) => {
166
+ const absoluteControllerPath = path.resolve(absoluteSrcPath, relativeControllerPath);
167
+ (0, logging_1.debug)('\n{cyan} {yellow}: {magentaBright} {cyan}\n', '===== Analyzing controller', `${i + 1}/${controllers.length}`, relativeControllerPath, '=====');
168
+ const basePath = path.dirname(absoluteControllerPath);
169
+ let moduleName = modulesCache.get(basePath);
170
+ // Check if the module's name is in cache
171
+ if (!moduleName) {
172
+ // Else, find the nearest module file
173
+ const absoluteModulePath = (0, utils_1.findFileAbove)(/^.*\.module\.ts$/, path.resolve(absoluteSrcPath, basePath));
174
+ if (absoluteModulePath === null) {
175
+ (0, logging_1.panic)('No module file was found for controller at path: {yellow}', absoluteControllerPath);
176
+ }
177
+ const relativeModulePath = path.relative(absoluteSrcPath, absoluteModulePath);
178
+ // Get the module's name
179
+ moduleName = getModuleName(host, relativeModulePath, absoluteSrcPath);
180
+ (0, logging_1.debug)('Discovered module: {yellow}', moduleName);
181
+ // Ensure this module is unique
182
+ const cachedModulePath = declaredModulesPath.get(moduleName);
183
+ if (cachedModulePath) {
184
+ (0, logging_1.panic)(`Two modules were declared with the same name {yellow}:\n` + `- One in {yellow}\n` + `- One in {yellow}`, moduleName, cachedModulePath, relativeModulePath);
185
+ }
186
+ modulesCache.set(basePath, moduleName);
187
+ }
188
+ if (moduleName in {}) {
189
+ (0, logging_1.panic)(`Detected module whose name {yellow} collides with a JavaScript's native object property`, moduleName);
190
+ }
191
+ let moduleSdkInfos = collected.get(moduleName);
192
+ if (!moduleSdkInfos) {
193
+ moduleSdkInfos = new Map();
194
+ collected.set(moduleName, moduleSdkInfos);
195
+ }
196
+ if (i === 0) {
197
+ if (process.platform === 'linux' && os.release().toLocaleLowerCase().includes('microsoft') && absoluteSrcPath.startsWith('/mnt/')) {
198
+ (0, logging_1.warn)("NOTE: On WSL, the first type analysis on a project located in Windows's filesystem may take a long time to complete.");
199
+ (0, logging_1.warn)('Please consider moving your project to WSL, or running this tool directly from Windows');
200
+ }
201
+ }
202
+ const metadata = analyzeController(host, relativeControllerPath, absoluteSrcPath);
203
+ if (metadata instanceof Error) {
204
+ throw new Error((0, logging_1.format)('Failed to analyze controller at path {magenta}:\n{}', relativeControllerPath, metadata.message));
205
+ }
206
+ if (metadata) {
207
+ if (metadata.registrationName in {}) {
208
+ (0, logging_1.panic)(`Detected controller whose registration name {yellow} collides with a JavaScript's native object property`, metadata.registrationName);
209
+ }
210
+ // Ensure the each controller has a unique name across modules
211
+ if (usedControllerNames.has(metadata.className)) {
212
+ (0, logging_1.panic)(`Detected two controllers with the same name {yellow}. Second occurrence found in {yellow}`, metadata.registrationName, metadata.path);
213
+ }
214
+ else {
215
+ usedControllerNames.add(metadata.className);
216
+ }
217
+ moduleSdkInfos.set(metadata.className, metadata);
218
+ }
219
+ });
220
+ return collected;
221
+ }
222
+ function getModuleName(host, modulePath, sourcePath) {
223
+ const SK = host.SyntaxKind;
224
+ // Prepare the source file to analyze
225
+ const file = getSourceFileOrThrow(host, path.resolve(sourcePath, modulePath));
226
+ // Find the module class declaration
227
+ const classDecl = file.statements.find((node) => node.kind === SK.ClassDeclaration && (0, ast_1.getDecorators)(host, node).length > 0);
228
+ if (!classDecl) {
229
+ (0, logging_1.panic)('No class declaration found in module at {yellow}', modulePath);
230
+ }
231
+ const moduleName = (0, ast_1.nodeName)(classDecl, file);
232
+ if (moduleName === undefined) {
233
+ (0, logging_1.panic)('Internal error: failed to retrieve name of declared class');
234
+ }
235
+ const decorators = (0, ast_1.getDecorators)(host, classDecl);
236
+ const moduleDecorator = decorators.find((dec) => (0, ast_1.decoratorName)(host, dec, file) === 'Module');
237
+ if (!moduleDecorator) {
238
+ (0, logging_1.panic)((0, logging_1.format)(`Module class {yellow} is missing {yellow} decorator\nModule path is: {yellow}`, moduleName, '@Module', modulePath));
239
+ }
240
+ return moduleName;
241
+ }
242
+ function analyzeController(host, controllerPath, absoluteSrcPath) {
243
+ const SK = host.SyntaxKind;
244
+ (0, logging_1.debug)('Analyzing: {yellow}', controllerPath);
245
+ // Prepare the source file to analyze
246
+ const file = getSourceFileOrThrow(host, path.resolve(absoluteSrcPath, controllerPath));
247
+ // Find the controller class declaration
248
+ const classDecl = file.statements.find((node) => node.kind === SK.ClassDeclaration);
249
+ if (!classDecl) {
250
+ (0, logging_1.warn)('No controller found in this file.');
251
+ return null;
252
+ }
253
+ const className = (0, ast_1.nodeName)(classDecl, file);
254
+ if (className === undefined) {
255
+ return new Error('Internal error: failed to retrieve name of declared class');
256
+ }
257
+ // By default, a controller is registered under its class name
258
+ // This is unless it provides an argument to its @Controller() decorator
259
+ let registrationName = (0, sdk_1.camelcase)(className);
260
+ let controllerUriPrefix = null;
261
+ (0, logging_1.debug)('Found class declaration: {yellow}', className);
262
+ // Get the @Controller() decorator
263
+ const decorator = (0, ast_1.getDecorators)(host, classDecl).find((dec) => (0, ast_1.decoratorName)(host, dec, file) === 'Controller');
264
+ if (!decorator) {
265
+ (0, logging_1.warn)('Skipping this controller as it does not have a @Controller() decorator');
266
+ return null;
267
+ }
268
+ // Get the decorator's call expression
269
+ const decCallExpr = (0, ast_1.decoratorCallExpression)(host, decorator);
270
+ if (!decCallExpr) {
271
+ (0, logging_1.warn)('Skipping this controller as its @Controller() decorator is not called');
272
+ return null;
273
+ }
274
+ // Get the decorator's arguments
275
+ const decExpr = decCallExpr.arguments;
276
+ if (decExpr.length > 1) {
277
+ (0, logging_1.warn)('Skipping this controller as its @Controller() decorator is called with more than 1 argument');
278
+ return null;
279
+ }
280
+ // Get the first argument, which is expected to be the controller's registration name
281
+ // Example: `@Controller("SuperName")` will register the controller under the name "SuperName"
282
+ if (decExpr[0]) {
283
+ const nameArg = decExpr[0];
284
+ // Variables are not supported
285
+ if (!(0, ast_1.isStringLiteral)(host, nameArg)) {
286
+ (0, logging_1.warn)("Skipping this controller as its @Controller() decorator's argument is not a string literal");
287
+ return null;
288
+ }
289
+ // Update the registration name
290
+ registrationName = nameArg.text;
291
+ controllerUriPrefix = registrationName;
292
+ (0, logging_1.debug)('Registering controller {yellow} as {yellow} (as specified in @Controller())', className, registrationName);
293
+ }
294
+ else {
295
+ // No argument was provided to the @Controller() decorator, so we stick with the original controller's name
296
+ (0, logging_1.debug)('@Controller() was called without argument, registering controller under name {yellow}', registrationName);
297
+ }
298
+ // Generate a SDK interface for the controller's methods
299
+ const methods = analyzeMethods(host, file, classDecl, controllerUriPrefix, controllerPath, absoluteSrcPath);
300
+ if (methods instanceof Error) {
301
+ return methods;
302
+ }
303
+ // Success!
304
+ (0, logging_1.debug)(`└─ Done for controller {yellow}`, controllerPath);
305
+ return {
306
+ path: controllerPath,
307
+ className,
308
+ registrationName,
309
+ methods,
310
+ };
311
+ }
312
+ // =============================================================================================================== //
313
+ // Methods & parameters (see src/analyzer/methods.ts, src/analyzer/params.ts) //
314
+ // =============================================================================================================== //
315
+ function analyzeMethods(host, sourceFile, controllerClass, controllerUriPrefix, filePath, absoluteSrcPath) {
316
+ // Output variable
317
+ const collected = new Array();
318
+ // Get the list of all methods
319
+ const methods = controllerClass.members.filter((node) => node.kind === host.SyntaxKind.MethodDeclaration);
320
+ for (const method of methods) {
321
+ const methodName = (0, ast_1.nodeName)(method, sourceFile);
322
+ (0, logging_1.debug)('├─ Found method: {yellow}', methodName);
323
+ // Get the HTTP decorator(s) of the method
324
+ const decorators = (0, ast_1.getDecorators)(host, method).filter((dec) => Object.keys(sdk_1.SdkHttpMethod).includes((0, ast_1.decoratorName)(host, dec, sourceFile)));
325
+ // We expect to have exactly one HTTP decorator
326
+ if (decorators.length > 1) {
327
+ // If there is more than one decorator, that's invalid, so we can't analyze the method
328
+ return new Error((0, logging_1.format)('├─── Detected multiple HTTP decorators on method: {yellow}' +
329
+ decorators.map((dec) => (0, ast_1.decoratorName)(host, dec, sourceFile)).join(',')));
330
+ }
331
+ else if (decorators.length === 0) {
332
+ // If there isn't any HTTP decorator, this is simply not a method available from the outside and so we won't generate an interface for it
333
+ (0, logging_1.debug)('├─── Skipping this method as it does not have an HTTP decorator');
334
+ continue;
335
+ }
336
+ // Get the HTTP decorator
337
+ const dec = decorators[0];
338
+ const httpMethod = sdk_1.SdkHttpMethod[(0, ast_1.decoratorName)(host, dec, sourceFile)];
339
+ (0, logging_1.debug)('├─── Detected HTTP method: {magentaBright}', httpMethod.toLocaleUpperCase());
340
+ // Get the arguments provided to the HTTP decorator (we expect one, the URI path)
341
+ const decArgs = (0, ast_1.decoratorArguments)(host, dec);
342
+ // The method's URI path
343
+ let uriPath;
344
+ // We expect the decorator to have exactly one argument
345
+ if (decArgs.length > 1) {
346
+ // If we have more than one argument, that's invalid (or at least not supported here), so we can't analyze the method
347
+ return new Error(`Multiple (${decArgs.length}) arguments were provided to the HTTP decorator`);
348
+ }
349
+ else if (decArgs.length === 0) {
350
+ // If there is no argument, we take the method's name as the URI path
351
+ (0, logging_1.debug)('├─── No argument found for decorator, using base URI path.');
352
+ uriPath = '';
353
+ }
354
+ else {
355
+ // If we have exactly one argument, hurray! That's our URI path.
356
+ const uriNameDec = decArgs[0];
357
+ // Variables are not supported
358
+ if (!(0, ast_1.isStringLiteral)(host, uriNameDec)) {
359
+ return new Error((0, logging_1.format)('├─── The argument provided to the HTTP decorator is not a string literal:\n>> {cyan}', (0, ast_1.nodeText)(uriNameDec, sourceFile)));
360
+ }
361
+ // Update the method's URI path
362
+ uriPath = uriNameDec.text;
363
+ (0, logging_1.debug)('├─── Detected argument in HTTP decorator, mapping this method to custom URI name');
364
+ }
365
+ (0, logging_1.debug)('├─── Detected URI name: {yellow}', uriPath);
366
+ // Analyze the method's URI
367
+ const route = (0, route_1.analyzeUri)(controllerUriPrefix ? (uriPath ? `/${controllerUriPrefix}/${uriPath}` : `/` + controllerUriPrefix) : uriPath);
368
+ if (route instanceof Error) {
369
+ return new Error('├─── Detected unsupported URI format:\n' +
370
+ route.message
371
+ .split('\n')
372
+ .map((line) => '├───── ' + line)
373
+ .join('\n'));
374
+ }
375
+ (0, logging_1.debug)('├─── Parsed URI name to route: {yellow}', (0, route_1.debugUri)(route, chalk.blue));
376
+ // Analyze the method's arguments
377
+ (0, logging_1.debug)('├─── Analyzing arguments...');
378
+ const params = extractParams({ host, sourceFile, controllerClass, httpMethod, route, method, filePath, absoluteSrcPath });
379
+ // Get the method's return type
380
+ (0, logging_1.debug)('├─── Resolving return type...');
381
+ const returnType = (0, typedeps_1.resolveTypeTextDependencies)(host.typeToString(host.getReturnTypeOfDeclaration(method)), filePath, absoluteSrcPath);
382
+ (0, logging_1.debug)('├─── Detected return type: {cyan}', returnType.resolvedType);
383
+ // Success!
384
+ collected.push({
385
+ name: methodName,
386
+ httpMethod,
387
+ returnType,
388
+ route,
389
+ uriPath,
390
+ params,
391
+ });
392
+ }
393
+ return collected;
394
+ }
395
+ function extractParams(context) {
396
+ const { httpMethod, route } = context;
397
+ const { Body, Param, Query } = extractDecoratedArgs(context);
398
+ const resolvedParams = {
399
+ routeParams: mergeDecoratedArgs(Param),
400
+ queryParams: mergeDecoratedArgs(Query),
401
+ bodyParams: mergeDecoratedArgs(Body),
402
+ context,
403
+ };
404
+ /**
405
+ * Validate Body Params are not used in GET requests
406
+ */
407
+ if (httpMethod === sdk_1.SdkHttpMethod.Get && resolvedParams.bodyParams) {
408
+ panicWithContext(`${httpMethod} request should not have @Body params, use @Query params instead`, context);
409
+ }
410
+ /**
411
+ * Validate Query Params are not used in non-GET requests
412
+ */
413
+ if (httpMethod !== sdk_1.SdkHttpMethod.Get && resolvedParams.queryParams) {
414
+ panicWithContext(`${httpMethod} request should not have @Query params, use @Body params instead`, context);
415
+ }
416
+ /**
417
+ * Validate Route Params exist in route URL
418
+ */
419
+ const { routeParams } = resolvedParams;
420
+ if (routeParams) {
421
+ const allowedRouteParams = new Set((0, route_1.paramsFromRoute)(route));
422
+ // Like the legacy analyzer, this checks the keys of the resolved params object. For a generic `@Param()` argument,
423
+ // these are the keys of the resolved type's description (rawType, resolvedType...), which are rejected.
424
+ const usedRouteParams = Object.keys(routeParams);
425
+ for (const usedParam of usedRouteParams) {
426
+ if (!allowedRouteParams.has(usedParam)) {
427
+ panicWithContext(`Route param ${usedParam} does not appear in route URL`, context);
428
+ }
429
+ }
430
+ }
431
+ return resolvedParams;
432
+ }
433
+ function extractDecoratedArgs(context) {
434
+ const decoratedArgs = {
435
+ [sdk_1.ArgDecorator.Param]: [],
436
+ [sdk_1.ArgDecorator.Query]: [],
437
+ [sdk_1.ArgDecorator.Body]: [],
438
+ };
439
+ const { controllerClass, host, method, sourceFile } = context;
440
+ const args = method.parameters;
441
+ for (const arg of args) {
442
+ const argName = (0, ast_1.nodeName)(arg, sourceFile);
443
+ (0, logging_1.debug)('├───── Detected argument: {yellow}', argName);
444
+ // Arguments are collected as soon as they have a decorator like @Query() or @Body()
445
+ const argDecorators = (0, ast_1.getDecorators)(host, arg).filter((dec) => Object.values(sdk_1.ArgDecorator).includes((0, ast_1.decoratorName)(host, dec, sourceFile)));
446
+ if (argDecorators.length === 0) {
447
+ // If we have no argument, this is not an argument we are interested in, so we just skip it
448
+ (0, logging_1.debug)('├───── Skipping this argument as it does not have a decorator');
449
+ continue;
450
+ }
451
+ else if (argDecorators.length > 1) {
452
+ (0, logging_1.panic)(`${(0, ast_1.nodeName)(controllerClass, sourceFile)} ${(0, ast_1.nodeName)(method, sourceFile)} has multiple decorators on argument ${argName} ${argDecorators
453
+ .map((dec) => (0, ast_1.decoratorName)(host, dec, sourceFile))
454
+ .join(', ')}`);
455
+ }
456
+ // Get the only decrator
457
+ const decorator = argDecorators[0];
458
+ const decoratorType = (0, ast_1.decoratorName)(host, decorator, sourceFile);
459
+ const argParamKey = extractArgParamKey({ ...context, arg, decorator });
460
+ const argType = host.getTypeAtLocation(arg);
461
+ if (!argParamKey && !host.isObjectType(argType)) {
462
+ (0, logging_1.panic)(`${(0, ast_1.nodeName)(controllerClass, sourceFile)} ${(0, ast_1.nodeName)(method, sourceFile)} generic controller argument ${decoratorType}() ${argName} must be an object type`);
463
+ }
464
+ decoratedArgs[decoratorType].push({
465
+ arg,
466
+ argParamKey,
467
+ decorator,
468
+ decoratorType,
469
+ context,
470
+ });
471
+ }
472
+ return decoratedArgs;
473
+ }
474
+ function extractArgParamKey(context) {
475
+ const { arg, controllerClass, decorator, host, method, sourceFile } = context;
476
+ const decoratorArgs = (0, ast_1.decoratorArguments)(host, decorator);
477
+ if (decoratorArgs.length > 1) {
478
+ (0, logging_1.panic)(`${(0, ast_1.nodeName)(controllerClass, sourceFile)} ${(0, ast_1.nodeName)(method, sourceFile)} ${(0, ast_1.decoratorName)(host, decorator, sourceFile)}() ${(0, ast_1.nodeName)(arg, sourceFile)} argument decorator has multiple parameters`);
479
+ }
480
+ else if (decoratorArgs.length === 0) {
481
+ return null;
482
+ }
483
+ const decoratorArg = decoratorArgs[0];
484
+ if (!(0, ast_1.isStringLiteral)(host, decoratorArg)) {
485
+ (0, logging_1.panic)('The argument provided to the decorator is not a string literal:\n>>> {cyan}', (0, ast_1.nodeText)(arg, sourceFile));
486
+ }
487
+ const paramKey = decoratorArg.text;
488
+ if (paramKey in {}) {
489
+ panicWithContext(`${(0, ast_1.decoratorName)(host, decorator, sourceFile)}('${paramKey}') param name collides with JavaScript native object property`, context);
490
+ }
491
+ return paramKey;
492
+ }
493
+ function mergeDecoratedArgs(decoratedArgs) {
494
+ let genericParam = null;
495
+ const paramMap = {};
496
+ for (const decoratedArg of decoratedArgs) {
497
+ const { arg, argParamKey, context, decoratorType } = decoratedArg;
498
+ const resolvedType = (0, typedeps_1.resolveTypeTextDependencies)(context.host.typeToString(context.host.getTypeAtLocation(arg)), context.filePath, context.absoluteSrcPath);
499
+ if (argParamKey) {
500
+ if (paramMap[argParamKey]) {
501
+ panicWithContext(`${decoratorType}('${argParamKey}') used twice in controller method`, decoratedArg.context);
502
+ }
503
+ paramMap[argParamKey] = resolvedType;
504
+ }
505
+ else {
506
+ if (genericParam) {
507
+ panicWithContext(`${decoratorType}() used twice in controller method`, decoratedArg.context);
508
+ }
509
+ genericParam = resolvedType;
510
+ }
511
+ }
512
+ const hasArgsByKey = Object.keys(paramMap).length > 0;
513
+ if (genericParam && hasArgsByKey) {
514
+ panicWithContext(`Cannot mix generic and specific ${decoratedArgs[0].decoratorType}()`, decoratedArgs[0].context);
515
+ }
516
+ return hasArgsByKey ? paramMap : genericParam;
517
+ }
518
+ const panicWithContext = (message, context) => {
519
+ const { controllerClass, filePath, httpMethod, method, sourceFile } = context;
520
+ const ctx = {
521
+ controller: (0, ast_1.nodeName)(controllerClass, sourceFile),
522
+ method: (0, ast_1.nodeName)(method, sourceFile),
523
+ httpMethod,
524
+ filePath,
525
+ };
526
+ (0, logging_1.panic)(`${message}\n${JSON.stringify(ctx, null, 2)}`);
527
+ };
528
+ // =============================================================================================================== //
529
+ // Types extraction (see src/analyzer/extractor.ts, src/analyzer/classdeps.ts) //
530
+ // =============================================================================================================== //
531
+ function analyzeClassDeps(host, decl, sourceFile, relativeFilePath, absoluteSrcPath) {
532
+ if (path.isAbsolute(relativeFilePath)) {
533
+ (0, logging_1.unreachable)('Internal error: got absolute file path in class dependencies analyzer, when expecting a relative one (got {magentaBright})', relativeFilePath);
534
+ }
535
+ const toLookup = new Array();
536
+ for (const sup of (0, ast_1.getExtendsTypeNodes)(host, decl)) {
537
+ toLookup.push(host.getTypeAtLocation(sup));
538
+ }
539
+ for (const prop of (0, ast_1.getDeclarationProperties)(host, decl, sourceFile)) {
540
+ toLookup.push(host.getTypeAtLocation(prop));
541
+ }
542
+ return toLookup.map((type) => (0, typedeps_1.resolveTypeTextDependencies)(host.typeToString(type), relativeFilePath, absoluteSrcPath));
543
+ }
544
+ /**
545
+ * Types extractor
546
+ */
547
+ class TypesExtractor {
548
+ host;
549
+ absoluteSrcPath;
550
+ magicTypes;
551
+ extracted;
552
+ constructor(
553
+ /** Analysis engine */
554
+ host,
555
+ /** Absolute source path */
556
+ absoluteSrcPath,
557
+ /** Magic types to replace non-portable types */
558
+ magicTypes,
559
+ /** Extracted types */
560
+ extracted = new Map()) {
561
+ this.host = host;
562
+ this.absoluteSrcPath = absoluteSrcPath;
563
+ this.magicTypes = magicTypes;
564
+ this.extracted = extracted;
565
+ }
566
+ /**
567
+ * Find if a type has previously been extracted, without providing its extension
568
+ * @param loc
569
+ * @returns
570
+ */
571
+ findExtractedTypeWithoutExt(loc) {
572
+ for (const ext of sdk_1.MODULE_EXTENSIONS) {
573
+ const typ = this.extracted.get(loc.relativePathNoExt + ext)?.get(loc.typename);
574
+ if (typ) {
575
+ return typ;
576
+ }
577
+ }
578
+ return null;
579
+ }
580
+ /**
581
+ * Find the relative file location of a type
582
+ * @param loc
583
+ * @returns
584
+ */
585
+ findTypeRelativeFilePath(loc) {
586
+ if (path.isAbsolute(loc.relativePathNoExt)) {
587
+ (0, logging_1.unreachable)('Internal error: got absolute file path in types extractor, when expecting a relative one (got {magentaBright})', loc.relativePathNoExt);
588
+ }
589
+ const absolutePathNoExt = path.resolve(this.absoluteSrcPath, loc.relativePathNoExt);
590
+ const cached = this.findExtractedTypeWithoutExt(loc);
591
+ if (cached) {
592
+ return cached.relativePath;
593
+ }
594
+ let relativeFilePath = null;
595
+ for (const ext of sdk_1.MODULE_EXTENSIONS) {
596
+ if (this.host.getSourceFile(absolutePathNoExt + ext)) {
597
+ relativeFilePath = loc.relativePathNoExt + ext;
598
+ }
599
+ }
600
+ return (relativeFilePath ??
601
+ new Error((0, logging_1.format)('File {magenta} was not found (was expected to contain dependency type {yellow})', loc.relativePathNoExt, loc.typename)));
602
+ }
603
+ /**
604
+ * Extract a type
605
+ * @param loc
606
+ * @param typesPath
607
+ * @returns
608
+ */
609
+ extractType(loc, typesPath = []) {
610
+ const { host } = this;
611
+ const SK = host.SyntaxKind;
612
+ if (path.isAbsolute(loc.relativePathNoExt)) {
613
+ (0, logging_1.unreachable)('Internal error: got absolute file path in types extractor, when expecting a relative one (got {magentaBright})', loc.relativePathNoExt);
614
+ }
615
+ // Get the absolute path of the type's parent file
616
+ // We don't know its extension yet as imported file names in import statements don't have an extension
617
+ const absolutePathNoExt = path.resolve(this.absoluteSrcPath, loc.relativePathNoExt);
618
+ // If the type is already in cache, return it directly
619
+ const cached = this.findExtractedTypeWithoutExt(loc);
620
+ if (cached) {
621
+ return cached;
622
+ }
623
+ // Try to find the path with extension of the file and get it as a source file
624
+ // (like the legacy analyzer, the last matching extension wins)
625
+ let fileAndPath = null;
626
+ for (const ext of sdk_1.MODULE_EXTENSIONS) {
627
+ const sourceFile = host.getSourceFile(absolutePathNoExt + ext);
628
+ if (sourceFile) {
629
+ fileAndPath = [sourceFile, loc.relativePathNoExt + ext];
630
+ }
631
+ }
632
+ if (!fileAndPath) {
633
+ return new Error((0, logging_1.format)('File {magenta} was not found (was expected to contain dependency type {yellow})', loc.relativePathNoExt, loc.typename));
634
+ }
635
+ const [file, relativeFilePath] = fileAndPath;
636
+ // Use magic types to replace non-portable types
637
+ for (const magicType of this.magicTypes) {
638
+ if (relativeFilePath.endsWith(`node_modules/${magicType.nodeModuleFilePath}`) && loc.typename === magicType.typeName) {
639
+ (0, logging_1.debug)('-> '.repeat(typesPath.length + 1) +
640
+ 'Found magic type {yellow} from external module file {magentaBright}, using provided placeholder.', loc.typename, relativeFilePath);
641
+ const extracted = {
642
+ content: '/** @file Magic placeholder from configuration file */\n\n' + magicType.placeholderContent,
643
+ relativePath: relativeFilePath,
644
+ relativePathNoExt: loc.relativePathNoExt,
645
+ typename: loc.typename,
646
+ typeParams: [],
647
+ dependencies: [],
648
+ };
649
+ typesPath.pop();
650
+ let types = this.extracted.get(relativeFilePath);
651
+ if (!types) {
652
+ types = new Map();
653
+ this.extracted.set(relativeFilePath, types);
654
+ }
655
+ types.set(loc.typename, extracted);
656
+ return extracted;
657
+ }
658
+ }
659
+ (0, logging_1.debug)('-> '.repeat(typesPath.length + 1) + 'Extracting type {yellow} from file {magentaBright}...', loc.typename, relativeFilePath);
660
+ // Analyze the type's declaration
661
+ const decl = file.statements.find((node) => {
662
+ return ((node.kind === SK.EnumDeclaration ||
663
+ node.kind === SK.TypeAliasDeclaration ||
664
+ node.kind === SK.InterfaceDeclaration ||
665
+ node.kind === SK.ClassDeclaration ||
666
+ node.kind === SK.FunctionDeclaration) &&
667
+ (0, ast_1.nodeName)(node, file) === loc.typename);
668
+ });
669
+ if (!decl) {
670
+ return new Error((0, logging_1.format)(`Type {yellow} was not found in file {magenta}`, loc.typename, relativeFilePath));
671
+ }
672
+ // Handle a limitation of the tool: you can't import two types from two files at the same path with just two different extensions
673
+ // Example: importing a type named "User" from two files in the same directory called "user.entity.ts" and "user.entity.js"
674
+ const typ = this.findExtractedTypeWithoutExt(loc);
675
+ if (typ && typ.relativePath !== relativeFilePath) {
676
+ (0, logging_1.panic)('Found two conflicting files at same path but with different extensions:\n> {magentaBright}\n> {magentaBright}', typ.relativePath, relativeFilePath);
677
+ }
678
+ /** Resolved type's dependencies */
679
+ let resolvedDeps;
680
+ /** Type's parameters (e.g. <T>) */
681
+ let typeParams;
682
+ /** Type declaration */
683
+ let extractedDecl = (0, ast_1.nodeText)(decl, file);
684
+ // Handle enumerations
685
+ if (decl.kind === SK.EnumDeclaration) {
686
+ resolvedDeps = [];
687
+ typeParams = [];
688
+ }
689
+ // Handle type aliases
690
+ else if (decl.kind === SK.TypeAliasDeclaration) {
691
+ resolvedDeps = [(0, typedeps_1.resolveTypeTextDependencies)(host.typeToString(host.getTypeAtLocation(decl)), relativeFilePath, this.absoluteSrcPath)];
692
+ typeParams = [];
693
+ }
694
+ // Handle interfaces
695
+ else if (decl.kind === SK.InterfaceDeclaration) {
696
+ resolvedDeps = analyzeClassDeps(host, decl, file, relativeFilePath, this.absoluteSrcPath);
697
+ typeParams = (decl.typeParameters ?? []).map((tp) => (0, ast_1.nodeText)(tp, file));
698
+ }
699
+ // Handle classes
700
+ // Methods are not handled because they shouldn't be used as DTOs and won't be decodable from JSON in all cases
701
+ // This part is tricky as we remake the class from scratch using the informations we have on it, given we have to get rid
702
+ // of methods as well as removing decorators
703
+ else if (decl.kind === SK.ClassDeclaration) {
704
+ const classHead = (0, ast_1.nodeText)(decl, file).match(/\b(export[^{]+class[^{]+{)/);
705
+ if (!classHead) {
706
+ (0, logging_1.unreachable)('Internal error: failed to match class head in declaration: {yellow}', (0, ast_1.nodeText)(decl, file));
707
+ }
708
+ extractedDecl = classHead[1];
709
+ const index = host.getIndexType(host.getTypeAtLocation(decl), 'string') ?? host.getIndexType(host.getTypeAtLocation(decl), 'number');
710
+ if (index) {
711
+ extractedDecl += '\npublic [input: string | number]: ' + (0, typedeps_1.getImportResolvedTypeText)(host.typeToString(index));
712
+ }
713
+ // Export all members
714
+ for (const member of (0, ast_1.getClassMembers)(host, decl, file)) {
715
+ if (member.kind !== SK.PropertyDeclaration) {
716
+ (0, logging_1.warn)('Found non-property member in class {cyan}: {magenta}', (0, ast_1.nodeName)(decl, file) ?? '<anonymous>', (0, ast_1.nodeText)(member, file));
717
+ continue;
718
+ }
719
+ const memberType = host.getTypeAtLocation(member);
720
+ const memberText = (0, ast_1.nodeText)(member, file);
721
+ extractedDecl += `\npublic ${(0, ast_1.nodeName)(member, file)}${memberText.includes('?') ? '?' : memberText.includes('!:') ? '!' : ''}: ${(0, typedeps_1.getImportResolvedTypeText)(host.typeToString(memberType))};`;
722
+ }
723
+ extractedDecl += '\n}';
724
+ resolvedDeps = analyzeClassDeps(host, decl, file, relativeFilePath, this.absoluteSrcPath);
725
+ typeParams = (decl.typeParameters ?? []).map((tp) => (0, ast_1.nodeText)(tp, file));
726
+ }
727
+ // Handle functions
728
+ else if (decl.kind === SK.FunctionDeclaration) {
729
+ resolvedDeps = [];
730
+ typeParams = [];
731
+ }
732
+ // Handle unknown types
733
+ else {
734
+ (0, logging_1.panic)('Unknown node type when extracting types: ' + decl.kind);
735
+ }
736
+ /** Normalized dependencies */
737
+ const dependencies = [];
738
+ // Ensure we're not stuck in an infinite loop where we analyze a type A, then its dependency B, which itself depends on A, and so on
739
+ if (typesPath.includes(loc.typename)) {
740
+ (0, logging_1.unreachable)(`Internal error: infinite loop detected in types extracted: {yellow}`, typesPath.join(' -> '));
741
+ }
742
+ typesPath.push(loc.typename);
743
+ // Analyze all dependencies
744
+ for (const dependencyLoc of (0, sdk_1.locateTypesFile)(resolvedDeps)) {
745
+ // If the "dependency" is one of the type's parameters (e.g. "T"), ignore this part
746
+ if (typeParams.includes(dependencyLoc.typename)) {
747
+ continue;
748
+ }
749
+ // Find the dependency's relative path
750
+ let relativePath;
751
+ const cached = this.findExtractedTypeWithoutExt(dependencyLoc);
752
+ if (cached) {
753
+ relativePath = cached.relativePath;
754
+ }
755
+ else if (typesPath.includes(dependencyLoc.typename)) {
756
+ relativePath = this.findTypeRelativeFilePath(dependencyLoc);
757
+ }
758
+ else {
759
+ const extracted = this.extractType(dependencyLoc, typesPath);
760
+ relativePath = extracted instanceof Error ? extracted : extracted.relativePath;
761
+ }
762
+ if (relativePath instanceof Error) {
763
+ return new Error((0, logging_1.format)('├─ Failed to extract type {yellow} due to an error in dependency type {yellow}\nfrom file {magenta} :\n{}', loc.typename, dependencyLoc.typename, relativeFilePath, relativePath.message.replace(/^/gm, ' ')));
764
+ }
765
+ // Update dependencies
766
+ dependencies.push({ ...dependencyLoc, relativePath });
767
+ }
768
+ const extracted = {
769
+ ...loc,
770
+ relativePath: relativeFilePath,
771
+ typeParams,
772
+ content: extractedDecl,
773
+ dependencies,
774
+ };
775
+ typesPath.pop();
776
+ let types = this.extracted.get(relativeFilePath);
777
+ if (!types) {
778
+ types = new Map();
779
+ this.extracted.set(relativeFilePath, types);
780
+ }
781
+ // Save the dependency
782
+ types.set(loc.typename, extracted);
783
+ return extracted;
784
+ }
785
+ }
786
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5hbHl6ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9lbmdpbmUvYW5hbHl6ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFSCxNQUFZLEVBQUUsK0JBQVU7QUFDeEIsTUFBWSxFQUFFLCtCQUFVO0FBQ3hCLE1BQVksSUFBSSxpQ0FBWTtBQUU1QixNQUFPLEtBQUssb0JBQW1CO0FBRS9CLGlEQUF1RDtBQUN2RCw2Q0FBZ0Y7QUFDaEYseUNBbUJ3QjtBQUN4QixtREFBK0c7QUFFL0csd0NBQW9FO0FBQ3BFLG9DQUF3QztBQUV4QywrQkFXYztBQUdkOzs7O0dBSUc7QUFDSSxLQUFLLDBCQUEwQixNQUFjLEVBQUUsVUFBc0Q7SUFDMUcsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFBO0lBRTFCLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUVuRSxJQUFJLENBQUMsVUFBVTtRQUFFLElBQUEsZUFBSyxFQUFDLG1DQUFtQyxDQUFDLENBQUE7SUFFM0QsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDO1FBQUUsSUFBQSxlQUFLLEVBQUMscURBQXFELEVBQUUsVUFBVSxDQUFDLENBQUE7SUFDeEcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLENBQUMsV0FBVyxFQUFFO1FBQUUsSUFBQSxlQUFLLEVBQUMseUNBQXlDLENBQUMsQ0FBQTtJQUU3RixJQUFBLGVBQUssRUFBQywwQ0FBMEMsRUFBRSxVQUFVLENBQUMsQ0FBQTtJQUU3RCxJQUFJLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUN0QixNQUFNLG1CQUFtQixHQUFHLElBQUksQ0FBQyxPQUFPLENB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