@necessarylion/adonis-autoswagger 0.0.1

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.
@@ -0,0 +1,777 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.AutoSwagger = void 0;
40
+ const json_to_pretty_yaml_1 = __importDefault(require("json-to-pretty-yaml"));
41
+ const fs_1 = __importDefault(require("fs"));
42
+ const path_1 = __importDefault(require("path"));
43
+ const util_1 = __importDefault(require("util"));
44
+ const http_status_code_1 = __importDefault(require("http-status-code"));
45
+ const lodash_1 = __importDefault(require("lodash"));
46
+ const lodash_2 = require("lodash");
47
+ const fs_2 = require("fs");
48
+ const scalarCustomCss_1 = require("./scalarCustomCss");
49
+ const adonishelpers_1 = require("./adonishelpers");
50
+ const parsers_1 = require("./parsers");
51
+ const helpers_1 = require("./helpers");
52
+ const example_1 = __importStar(require("./example"));
53
+ class AutoSwagger {
54
+ options;
55
+ schemas = {};
56
+ commentParser;
57
+ modelParser;
58
+ interfaceParser;
59
+ enumParser;
60
+ routeParser;
61
+ validatorParser;
62
+ customPaths = {};
63
+ ui(url, options) {
64
+ const persistAuthString = options?.persistAuthorization
65
+ ? "persistAuthorization: true,"
66
+ : "";
67
+ return `<!DOCTYPE html>
68
+ <html lang="en">
69
+ <head>
70
+ <meta charset="UTF-8">
71
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
72
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
73
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.1.3/swagger-ui-standalone-preset.js"></script>
74
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.1.3/swagger-ui-bundle.js"></script>
75
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.1.3/swagger-ui.css" />
76
+ <title>Documentation</title>
77
+ </head>
78
+ <body>
79
+ <div id="swagger-ui"></div>
80
+ <script>
81
+ window.onload = function() {
82
+ SwaggerUIBundle({
83
+ url: "${url}",
84
+ dom_id: '#swagger-ui',
85
+ presets: [
86
+ SwaggerUIBundle.presets.apis,
87
+ SwaggerUIStandalonePreset
88
+ ],
89
+ layout: "BaseLayout",
90
+ ${persistAuthString}
91
+ })
92
+ }
93
+ </script>
94
+ </body>
95
+ </html>`;
96
+ }
97
+ rapidoc(url, style = "view") {
98
+ return (`
99
+ <!doctype html> <!-- Important: must specify -->
100
+ <html>
101
+ <head>
102
+ <meta charset="utf-8"> <!-- Important: rapi-doc uses utf8 characters -->
103
+ <script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"></script>
104
+ <title>Documentation</title>
105
+ </head>
106
+ <body>
107
+ <rapi-doc
108
+ spec-url = "` +
109
+ url +
110
+ `"
111
+ theme = "dark"
112
+ bg-color = "#24283b"
113
+ schema-style="tree"
114
+ schema-expand-level = "10"
115
+ header-color = "#1a1b26"
116
+ allow-try = "true"
117
+ nav-hover-bg-color = "#1a1b26"
118
+ nav-bg-color = "#24283b"
119
+ text-color = "#c0caf5"
120
+ nav-text-color = "#c0caf5"
121
+ primary-color = "#9aa5ce"
122
+ heading-text = "Documentation"
123
+ sort-tags = "true"
124
+ render-style = "` +
125
+ style +
126
+ `"
127
+ default-schema-tab = "example"
128
+ show-components = "true"
129
+ allow-spec-url-load = "false"
130
+ allow-spec-file-load = "false"
131
+ sort-endpoints-by = "path"
132
+
133
+ > </rapi-doc>
134
+ </body>
135
+ </html>
136
+ `);
137
+ }
138
+ scalar(url, proxyUrl = "https://proxy.scalar.com") {
139
+ return `
140
+ <!doctype html>
141
+ <html>
142
+ <head>
143
+ <title>API Reference</title>
144
+ <meta charset="utf-8" />
145
+ <meta
146
+ name="viewport"
147
+ content="width=device-width, initial-scale=1" />
148
+ <style>
149
+ ${scalarCustomCss_1.scalarCustomCss}
150
+ </style>
151
+ </head>
152
+ <body>
153
+ <script
154
+ id="api-reference"
155
+ data-url="${url}"
156
+ data-proxy-url="${proxyUrl}"></script>
157
+ <script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
158
+ </body>
159
+ </html>
160
+ `;
161
+ }
162
+ stoplight(url, theme = "dark") {
163
+ return `
164
+ <!doctype html>
165
+ <html data-theme="${theme}">
166
+ <head>
167
+ <title>API Documentation - Stoplight</title>
168
+ <meta charset="utf-8" />
169
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
170
+ <script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>
171
+ <link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css">
172
+ </head>
173
+ <body style="min-height:100vh">
174
+ <elements-api
175
+ style="display:block;height:100vh;width:100%;"
176
+ apiDescriptionUrl=${url}
177
+ router="hash"
178
+ layout="sidebar"
179
+ />
180
+ </body>
181
+ </html>
182
+ `;
183
+ }
184
+ jsonToYaml(json) {
185
+ return json_to_pretty_yaml_1.default.stringify(json);
186
+ }
187
+ async json(routes, options) {
188
+ if (process.env.NODE_ENV === (options.productionEnv || "production")) {
189
+ const str = await this.readFile(options.path, "json");
190
+ return JSON.parse(str);
191
+ }
192
+ return await this.generate(routes, options);
193
+ }
194
+ async writeFile(routes, options) {
195
+ const json = await this.generate(routes, options);
196
+ const contents = this.jsonToYaml(json);
197
+ const filePath = options.path + "swagger.yml";
198
+ const filePathJson = options.path + "swagger.json";
199
+ fs_1.default.writeFileSync(filePath, contents);
200
+ fs_1.default.writeFileSync(filePathJson, JSON.stringify(json, null, 2));
201
+ }
202
+ async readFile(rootPath, type = "yml") {
203
+ const filePath = rootPath + "swagger." + type;
204
+ const data = fs_1.default.readFileSync(filePath, "utf-8");
205
+ if (!data) {
206
+ console.error("Error reading file");
207
+ return;
208
+ }
209
+ return data;
210
+ }
211
+ async docs(routes, options) {
212
+ if (process.env.NODE_ENV === (options.productionEnv || "production")) {
213
+ return this.readFile(options.path);
214
+ }
215
+ return this.jsonToYaml(await this.generate(routes, options));
216
+ }
217
+ async generate(adonisRoutes, options) {
218
+ this.options = {
219
+ ...{
220
+ snakeCase: true,
221
+ preferredPutPatch: "PUT",
222
+ debug: false,
223
+ },
224
+ ...options,
225
+ };
226
+ const routes = adonisRoutes.root;
227
+ this.options.appPath = this.options.path + "app";
228
+ try {
229
+ const pj = fs_1.default.readFileSync(path_1.default.join(this.options.path, "package.json"));
230
+ const pjson = JSON.parse(pj.toString());
231
+ if (pjson.imports) {
232
+ Object.entries(pjson.imports).forEach(([key, value]) => {
233
+ const k = key.replaceAll("/*", "");
234
+ this.customPaths[k] = value
235
+ .replaceAll("/*.js", "")
236
+ .replaceAll("./", "");
237
+ });
238
+ }
239
+ }
240
+ catch (e) {
241
+ console.error(e);
242
+ }
243
+ this.commentParser = new parsers_1.CommentParser(this.options);
244
+ this.routeParser = new parsers_1.RouteParser(this.options);
245
+ this.modelParser = new parsers_1.ModelParser(this.options.snakeCase);
246
+ this.interfaceParser = new parsers_1.InterfaceParser(this.options.snakeCase);
247
+ this.validatorParser = new parsers_1.ValidatorParser();
248
+ this.enumParser = new parsers_1.EnumParser();
249
+ this.schemas = await this.getSchemas();
250
+ if (this.options.debug) {
251
+ console.log(this.options);
252
+ console.log("Found Schemas", Object.keys(this.schemas));
253
+ console.log("Using custom paths", this.customPaths);
254
+ }
255
+ this.commentParser.exampleGenerator = new example_1.default(this.schemas);
256
+ const docs = {
257
+ openapi: "3.0.0",
258
+ info: options.info || {
259
+ title: options.title,
260
+ version: options.version,
261
+ description: options.description ||
262
+ "Generated by AdonisJS AutoSwagger https://github.com/ad-on-is/adonis-autoswagger",
263
+ },
264
+ components: {
265
+ responses: {
266
+ Forbidden: {
267
+ description: "Access token is missing or invalid",
268
+ },
269
+ Accepted: {
270
+ description: "The request was accepted",
271
+ },
272
+ Created: {
273
+ description: "The resource has been created",
274
+ },
275
+ NotFound: {
276
+ description: "The resource has been created",
277
+ },
278
+ NotAcceptable: {
279
+ description: "The resource has been created",
280
+ },
281
+ },
282
+ securitySchemes: {
283
+ BearerAuth: {
284
+ type: "http",
285
+ scheme: "bearer",
286
+ },
287
+ BasicAuth: {
288
+ type: "http",
289
+ scheme: "basic",
290
+ },
291
+ ApiKeyAuth: {
292
+ type: "apiKey",
293
+ in: "header",
294
+ name: "X-API-Key",
295
+ },
296
+ ...this.options.securitySchemes,
297
+ },
298
+ schemas: this.schemas,
299
+ },
300
+ paths: {},
301
+ tags: [],
302
+ };
303
+ let paths = {};
304
+ let sscheme = "BearerAuth";
305
+ if (this.options.defaultSecurityScheme) {
306
+ sscheme = this.options.defaultSecurityScheme;
307
+ }
308
+ let securities = {
309
+ "auth": { [sscheme]: ["access"] },
310
+ "auth:api": { [sscheme]: ["access"] },
311
+ ...this.options.authMiddlewares
312
+ ?.map((am) => ({
313
+ [am]: { [sscheme]: ["access"] },
314
+ }))
315
+ .reduce((acc, val) => ({ ...acc, ...val }), {}),
316
+ };
317
+ let globalTags = [];
318
+ if (this.options.debug) {
319
+ console.log("Route annotations:");
320
+ console.log("Checking if controllers have propper comment annotations");
321
+ console.log("-----");
322
+ }
323
+ for await (const route of routes) {
324
+ let ignore = false;
325
+ for (const i of options.ignore) {
326
+ if (route.pattern == i ||
327
+ (i.endsWith("*") && route.pattern.startsWith(i.slice(0, -1))) ||
328
+ (i.startsWith("*") && route.pattern.endsWith(i.slice(1)))) {
329
+ ignore = true;
330
+ break;
331
+ }
332
+ }
333
+ if (ignore)
334
+ continue;
335
+ let security = [];
336
+ const responseCodes = {
337
+ GET: "200",
338
+ POST: "201",
339
+ DELETE: "202",
340
+ PUT: "204",
341
+ };
342
+ if (!Array.isArray(route.middleware)) {
343
+ route.middleware = (0, adonishelpers_1.serializeV6Middleware)(route.middleware);
344
+ }
345
+ route.middleware.forEach((m) => {
346
+ if (typeof securities[m] !== "undefined") {
347
+ security.push(securities[m]);
348
+ }
349
+ });
350
+ let { tags, parameters, pattern } = this.routeParser.extractInfos(route.pattern);
351
+ tags.forEach((tag) => {
352
+ if (globalTags.filter((e) => e.name === tag).length > 0)
353
+ return;
354
+ if (tag === "")
355
+ return;
356
+ globalTags.push({
357
+ name: tag,
358
+ description: "Everything related to " + tag,
359
+ });
360
+ });
361
+ const { sourceFile, action, customAnnotations, operationId } = await this.getDataBasedOnAdonisVersion(route);
362
+ route.methods.forEach((method) => {
363
+ let responses = {};
364
+ if (method === "HEAD")
365
+ return;
366
+ if (route.methods.includes("PUT") &&
367
+ route.methods.includes("PATCH") &&
368
+ method !== this.options.preferredPutPatch)
369
+ return;
370
+ let description = "";
371
+ let summary = "";
372
+ let tag = "";
373
+ let operationId;
374
+ if (security.length > 0) {
375
+ responses["401"] = {
376
+ description: `Returns **401** (${http_status_code_1.default.getMessage(401)})`,
377
+ };
378
+ responses["403"] = {
379
+ description: `Returns **403** (${http_status_code_1.default.getMessage(403)})`,
380
+ };
381
+ }
382
+ let requestBody = {
383
+ content: {
384
+ "application/json": {},
385
+ },
386
+ };
387
+ let actionParams = {};
388
+ if (action !== "" && typeof customAnnotations[action] !== "undefined") {
389
+ description = customAnnotations[action].description;
390
+ summary = customAnnotations[action].summary;
391
+ operationId = customAnnotations[action].operationId;
392
+ responses = { ...responses, ...customAnnotations[action].responses };
393
+ requestBody = customAnnotations[action].requestBody;
394
+ actionParams = customAnnotations[action].parameters;
395
+ tag = customAnnotations[action].tag;
396
+ }
397
+ parameters = (0, helpers_1.mergeParams)(parameters, actionParams);
398
+ if (tag != "") {
399
+ globalTags.push({
400
+ name: tag.toUpperCase(),
401
+ description: "Everything related to " + tag.toUpperCase(),
402
+ });
403
+ tags = [tag.toUpperCase()];
404
+ }
405
+ if ((0, lodash_2.isEmpty)(responses)) {
406
+ responses[responseCodes[method]] = {
407
+ description: http_status_code_1.default.getMessage(responseCodes[method]),
408
+ content: {
409
+ "application/json": {},
410
+ },
411
+ };
412
+ }
413
+ else {
414
+ if (typeof responses[responseCodes[method]] !== "undefined" &&
415
+ typeof responses[responseCodes[method]]["summary"] !== "undefined") {
416
+ if (summary === "") {
417
+ summary = responses[responseCodes[method]]["summary"];
418
+ }
419
+ delete responses[responseCodes[method]]["summary"];
420
+ }
421
+ if (typeof responses[responseCodes[method]] !== "undefined" &&
422
+ typeof responses[responseCodes[method]]["description"] !==
423
+ "undefined") {
424
+ description = responses[responseCodes[method]]["description"];
425
+ }
426
+ }
427
+ if (action !== "" && summary === "") {
428
+ // Solve toLowerCase undefined exception
429
+ // https://github.com/ad-on-is/adonis-autoswagger/issues/28
430
+ tags[0] = tags[0] ?? "";
431
+ switch (action) {
432
+ case "index":
433
+ summary = "Get a list of " + tags[0].toLowerCase();
434
+ break;
435
+ case "show":
436
+ summary = "Get a single instance of " + tags[0].toLowerCase();
437
+ break;
438
+ case "update":
439
+ summary = "Update " + tags[0].toLowerCase();
440
+ break;
441
+ case "destroy":
442
+ summary = "Delete " + tags[0].toLowerCase();
443
+ break;
444
+ case "store":
445
+ summary = "Create " + tags[0].toLowerCase();
446
+ break;
447
+ // frontend defaults
448
+ case "create":
449
+ summary = "Create (Frontend) " + tags[0].toLowerCase();
450
+ break;
451
+ case "edit":
452
+ summary = "Update (Frontend) " + tags[0].toLowerCase();
453
+ break;
454
+ }
455
+ }
456
+ const sf = sourceFile.split("/").at(-1).replace(".ts", "");
457
+ let m = {
458
+ summary: `${summary}${action !== "" ? ` (${action})` : "route"}`,
459
+ description: description + "\n\n _" + sourceFile + "_ - **" + action + "**",
460
+ operationId: operationId,
461
+ parameters: parameters,
462
+ tags: tags,
463
+ responses: responses,
464
+ security: security,
465
+ };
466
+ if (method !== "GET" && method !== "DELETE") {
467
+ m["requestBody"] = requestBody;
468
+ }
469
+ pattern = pattern.slice(1);
470
+ if (pattern === "") {
471
+ pattern = "/";
472
+ }
473
+ paths = {
474
+ ...paths,
475
+ [pattern]: { ...paths[pattern], [method.toLowerCase()]: m },
476
+ };
477
+ });
478
+ }
479
+ // filter unused tags
480
+ const usedTags = lodash_1.default.uniq(Object.entries(paths)
481
+ .map(([p, val]) => Object.entries(val)[0][1].tags)
482
+ .flat());
483
+ docs.tags = globalTags.filter((tag) => usedTags.includes(tag.name));
484
+ docs.paths = paths;
485
+ return docs;
486
+ }
487
+ async getDataBasedOnAdonisVersion(route) {
488
+ let sourceFile = "";
489
+ let action = "";
490
+ let customAnnotations;
491
+ let operationId = "";
492
+ if (route.meta.resolvedHandler !== null &&
493
+ route.meta.resolvedHandler !== undefined) {
494
+ if (typeof route.meta.resolvedHandler.namespace !== "undefined" &&
495
+ route.meta.resolvedHandler.method !== "handle") {
496
+ sourceFile = route.meta.resolvedHandler.namespace;
497
+ action = route.meta.resolvedHandler.method;
498
+ // If not defined by an annotation, use the combination of "controllerNameMethodName"
499
+ if (action !== "" && (0, lodash_2.isUndefined)(operationId) && route.handler) {
500
+ operationId = (0, helpers_1.formatOperationId)(route.handler);
501
+ }
502
+ }
503
+ }
504
+ let v6handler = route.handler;
505
+ if (v6handler.reference !== null &&
506
+ v6handler.reference !== undefined &&
507
+ v6handler.reference !== "") {
508
+ if (!Array.isArray(v6handler.reference)) {
509
+ // handles magic strings
510
+ // router.resource('/test', '#controllers/test_controller')
511
+ [sourceFile, action] = v6handler.reference.split(".");
512
+ const split = sourceFile.split("/");
513
+ if (split[0].includes("#")) {
514
+ sourceFile = sourceFile.replaceAll(split[0], this.customPaths[split[0]]);
515
+ }
516
+ else {
517
+ sourceFile = this.options.appPath + "/controllers/" + sourceFile;
518
+ }
519
+ operationId = (0, helpers_1.formatOperationId)(v6handler.reference);
520
+ }
521
+ else {
522
+ // handles lazy import
523
+ // const TestController = () => import('#controllers/test_controller')
524
+ v6handler = await (0, adonishelpers_1.serializeV6Handler)(v6handler);
525
+ action = v6handler.method;
526
+ sourceFile = v6handler.moduleNameOrPath;
527
+ operationId = (0, helpers_1.formatOperationId)(sourceFile + "." + action);
528
+ const split = sourceFile.split("/");
529
+ if (split[0].includes("#")) {
530
+ sourceFile = sourceFile.replaceAll(split[0], this.customPaths[split[0]]);
531
+ }
532
+ else {
533
+ sourceFile = this.options.appPath + "/" + sourceFile;
534
+ }
535
+ }
536
+ }
537
+ if (sourceFile !== "" && action !== "") {
538
+ sourceFile = sourceFile.replace("App/", "app/") + ".ts";
539
+ sourceFile = sourceFile.replace(".js", "");
540
+ customAnnotations = await this.commentParser.getAnnotations(sourceFile, action);
541
+ }
542
+ if (typeof customAnnotations !== "undefined" &&
543
+ typeof customAnnotations.operationId !== "undefined" &&
544
+ customAnnotations.operationId !== "") {
545
+ operationId = customAnnotations.operationId;
546
+ }
547
+ if (this.options.debug) {
548
+ if (sourceFile !== "") {
549
+ console.log(typeof customAnnotations !== "undefined" &&
550
+ !lodash_1.default.isEmpty(customAnnotations)
551
+ ? `\x1b[32m✓ FOUND for ${action}\x1b[0m`
552
+ : `\x1b[33m✗ MISSING for ${action}\x1b[0m`, `${sourceFile} (${route.methods[0].toUpperCase()} ${route.pattern})`);
553
+ }
554
+ }
555
+ return { sourceFile, action, customAnnotations, operationId };
556
+ }
557
+ async getSchemas() {
558
+ let schemas = {
559
+ Any: {
560
+ description: "Any JSON object not defined as schema",
561
+ },
562
+ };
563
+ schemas = {
564
+ ...schemas,
565
+ ...(await this.getInterfaces()),
566
+ ...(await this.getSerializers()),
567
+ ...(await this.getModels()),
568
+ ...(await this.getValidators()),
569
+ ...(await this.getEnums()),
570
+ };
571
+ return schemas;
572
+ }
573
+ async getValidators() {
574
+ const validators = {};
575
+ let p6 = path_1.default.join(this.options.appPath, "validators");
576
+ if (typeof this.customPaths["#validators"] !== "undefined") {
577
+ // it's v6
578
+ p6 = p6.replaceAll("app/validators", this.customPaths["#validators"]);
579
+ p6 = p6.replaceAll("app\\validators", this.customPaths["#validators"]);
580
+ }
581
+ if (!(0, fs_2.existsSync)(p6)) {
582
+ if (this.options.debug) {
583
+ console.log("Validators paths don't exist", p6);
584
+ }
585
+ return validators;
586
+ }
587
+ const files = await this.getFiles(p6, []);
588
+ if (this.options.debug) {
589
+ console.log("Found validator files", files);
590
+ }
591
+ try {
592
+ for (let file of files) {
593
+ if (/^[a-zA-Z]:/.test(file)) {
594
+ file = "file:///" + file;
595
+ }
596
+ const val = await import(file);
597
+ for (const [key, value] of Object.entries(val)) {
598
+ if (value.constructor.name.includes("VineValidator")) {
599
+ validators[key] = await this.validatorParser.validatorToObject(value);
600
+ validators[key].description = key + " (Validator)";
601
+ }
602
+ }
603
+ }
604
+ }
605
+ catch (e) {
606
+ console.log("**You are probably using 'node ace serve --hmr', which is not supported yet. Use 'node ace serve --watch' instead.**");
607
+ console.error(e.message);
608
+ }
609
+ return validators;
610
+ }
611
+ async getSerializers() {
612
+ const serializers = {};
613
+ let p6 = path_1.default.join(this.options.appPath, "serializers");
614
+ if (typeof this.customPaths["#serializers"] !== "undefined") {
615
+ // it's v6
616
+ p6 = p6.replaceAll("app/serializers", this.customPaths["#serializers"]);
617
+ p6 = p6.replaceAll("app\\serializers", this.customPaths["#serializers"]);
618
+ }
619
+ if (!(0, fs_2.existsSync)(p6)) {
620
+ if (this.options.debug) {
621
+ console.log("Serializers paths don't exist", p6);
622
+ }
623
+ return serializers;
624
+ }
625
+ const files = await this.getFiles(p6, []);
626
+ if (this.options.debug) {
627
+ console.log("Found serializer files", files);
628
+ }
629
+ for (let file of files) {
630
+ if (/^[a-zA-Z]:/.test(file)) {
631
+ file = "file:///" + file;
632
+ }
633
+ const val = await import(file);
634
+ for (const [key, value] of Object.entries(val)) {
635
+ if (key.indexOf("Serializer") > -1) {
636
+ serializers[key] = value;
637
+ }
638
+ }
639
+ }
640
+ return serializers;
641
+ }
642
+ async getModels() {
643
+ const models = {};
644
+ let p = path_1.default.join(this.options.appPath, "Models");
645
+ let p6 = path_1.default.join(this.options.appPath, "models");
646
+ if (typeof this.customPaths["#models"] !== "undefined") {
647
+ // it's v6
648
+ p6 = p6.replaceAll("app/models", this.customPaths["#models"]);
649
+ p6 = p6.replaceAll("app\\models", this.customPaths["#models"]);
650
+ }
651
+ if (!(0, fs_2.existsSync)(p) && !(0, fs_2.existsSync)(p6)) {
652
+ if (this.options.debug) {
653
+ console.log("Model paths don't exist", p, p6);
654
+ }
655
+ return models;
656
+ }
657
+ if ((0, fs_2.existsSync)(p6)) {
658
+ p = p6;
659
+ }
660
+ const files = await this.getFiles(p, []);
661
+ const readFile = util_1.default.promisify(fs_1.default.readFile);
662
+ if (this.options.debug) {
663
+ console.log("Found model files", files);
664
+ }
665
+ for (let file of files) {
666
+ file = file.replace(".js", "");
667
+ const data = await readFile(file, "utf8");
668
+ file = file.replace(".ts", "");
669
+ const split = file.split("/");
670
+ let name = split[split.length - 1].replace(".ts", "");
671
+ file = file.replace("app/", "/app/");
672
+ const parsed = this.modelParser.parseModelProperties(data);
673
+ if (parsed.name !== "") {
674
+ name = parsed.name;
675
+ }
676
+ let schema = {
677
+ type: "object",
678
+ required: parsed.required,
679
+ properties: parsed.props,
680
+ description: name + " (Model)",
681
+ };
682
+ models[name] = schema;
683
+ }
684
+ return models;
685
+ }
686
+ async getInterfaces() {
687
+ let interfaces = {
688
+ ...example_1.ExampleInterfaces.paginationInterface(),
689
+ };
690
+ let p = path_1.default.join(this.options.appPath, "Interfaces");
691
+ let p6 = path_1.default.join(this.options.appPath, "interfaces");
692
+ if (typeof this.customPaths["#interfaces"] !== "undefined") {
693
+ // it's v6
694
+ p6 = p6.replaceAll("app/interfaces", this.customPaths["#interfaces"]);
695
+ p6 = p6.replaceAll("app\\interfaces", this.customPaths["#interfaces"]);
696
+ }
697
+ if (!(0, fs_2.existsSync)(p) && !(0, fs_2.existsSync)(p6)) {
698
+ if (this.options.debug) {
699
+ console.log("Interface paths don't exist", p, p6);
700
+ }
701
+ return interfaces;
702
+ }
703
+ if ((0, fs_2.existsSync)(p6)) {
704
+ p = p6;
705
+ }
706
+ const files = await this.getFiles(p, []);
707
+ if (this.options.debug) {
708
+ console.log("Found interfaces files", files);
709
+ }
710
+ const readFile = util_1.default.promisify(fs_1.default.readFile);
711
+ for (let file of files) {
712
+ file = file.replace(".js", "");
713
+ const data = await readFile(file, "utf8");
714
+ file = file.replace(".ts", "");
715
+ interfaces = {
716
+ ...interfaces,
717
+ ...this.interfaceParser.parseInterfaces(data),
718
+ };
719
+ }
720
+ return interfaces;
721
+ }
722
+ async getFiles(dir, files_) {
723
+ const fs = require("fs");
724
+ files_ = files_ || [];
725
+ var files = await fs.readdirSync(dir);
726
+ for (let i in files) {
727
+ var name = dir + "/" + files[i];
728
+ if (fs.statSync(name).isDirectory()) {
729
+ await this.getFiles(name, files_);
730
+ }
731
+ else {
732
+ files_.push(name);
733
+ }
734
+ }
735
+ return files_;
736
+ }
737
+ async getEnums() {
738
+ let enums = {};
739
+ const enumParser = new parsers_1.EnumParser();
740
+ let p = path_1.default.join(this.options.appPath, "Types");
741
+ let p6 = path_1.default.join(this.options.appPath, "types");
742
+ if (typeof this.customPaths["#types"] !== "undefined") {
743
+ // it's v6
744
+ p6 = p6.replaceAll("app/types", this.customPaths["#types"]);
745
+ p6 = p6.replaceAll("app\\types", this.customPaths["#types"]);
746
+ }
747
+ if (!(0, fs_2.existsSync)(p) && !(0, fs_2.existsSync)(p6)) {
748
+ if (this.options.debug) {
749
+ console.log("Enum paths don't exist", p, p6);
750
+ }
751
+ return enums;
752
+ }
753
+ if ((0, fs_2.existsSync)(p6)) {
754
+ p = p6;
755
+ }
756
+ const files = await this.getFiles(p, []);
757
+ if (this.options.debug) {
758
+ console.log("Found enum files", files);
759
+ }
760
+ const readFile = util_1.default.promisify(fs_1.default.readFile);
761
+ for (let file of files) {
762
+ file = file.replace(".js", "");
763
+ const data = await readFile(file, "utf8");
764
+ file = file.replace(".ts", "");
765
+ const split = file.split("/");
766
+ const name = split[split.length - 1].replace(".ts", "");
767
+ file = file.replace("app/", "/app/");
768
+ const parsedEnums = enumParser.parseEnums(data);
769
+ enums = {
770
+ ...enums,
771
+ ...parsedEnums,
772
+ };
773
+ }
774
+ return enums;
775
+ }
776
+ }
777
+ exports.AutoSwagger = AutoSwagger;