@twin.org/ts-to-openapi 0.0.2-next.8 → 0.0.3-next.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.
Files changed (36) hide show
  1. package/bin/index.js +1 -1
  2. package/dist/es/cli.js +37 -0
  3. package/dist/es/cli.js.map +1 -0
  4. package/dist/es/commands/httpStatusCodeMap.js +115 -0
  5. package/dist/es/commands/httpStatusCodeMap.js.map +1 -0
  6. package/dist/{esm/index.mjs → es/commands/tsToOpenApi.js} +27 -168
  7. package/dist/es/commands/tsToOpenApi.js.map +1 -0
  8. package/dist/es/index.js +7 -0
  9. package/dist/es/index.js.map +1 -0
  10. package/dist/es/models/IInputPath.js +2 -0
  11. package/dist/es/models/IInputPath.js.map +1 -0
  12. package/dist/es/models/IInputResult.js +2 -0
  13. package/dist/es/models/IInputResult.js.map +1 -0
  14. package/dist/es/models/IRestRoute.js +2 -0
  15. package/dist/es/models/IRestRoute.js.map +1 -0
  16. package/dist/es/models/IRestRouteEntryPoints.js +2 -0
  17. package/dist/es/models/IRestRouteEntryPoints.js.map +1 -0
  18. package/dist/es/models/ITag.js +4 -0
  19. package/dist/es/models/ITag.js.map +1 -0
  20. package/dist/es/models/ITsToOpenApiConfig.js +2 -0
  21. package/dist/es/models/ITsToOpenApiConfig.js.map +1 -0
  22. package/dist/es/models/ITsToOpenApiConfigEntryPoint.js +4 -0
  23. package/dist/es/models/ITsToOpenApiConfigEntryPoint.js.map +1 -0
  24. package/dist/locales/en.json +46 -73
  25. package/dist/types/commands/tsToOpenApi.d.ts +1 -1
  26. package/dist/types/index.d.ts +4 -4
  27. package/dist/types/models/IInputResult.d.ts +11 -3
  28. package/dist/types/models/IRestRoute.d.ts +98 -0
  29. package/dist/types/models/IRestRouteEntryPoints.d.ts +23 -0
  30. package/dist/types/models/ITag.d.ts +13 -0
  31. package/dist/types/models/ITsToOpenApiConfig.d.ts +1 -1
  32. package/docs/changelog.md +64 -0
  33. package/docs/examples.md +1 -1
  34. package/locales/.validate-ignore +1 -0
  35. package/package.json +20 -11
  36. package/dist/cjs/index.cjs +0 -1083
package/bin/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  // Copyright 2024 IOTA Stiftung.
3
3
  // SPDX-License-Identifier: Apache-2.0.
4
- import { CLI } from '../dist/esm/index.mjs';
4
+ import { CLI } from '../dist/es/index.js';
5
5
 
6
6
  const cli = new CLI();
7
7
  const result = await cli.run(process.argv);
package/dist/es/cli.js ADDED
@@ -0,0 +1,37 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { CLIBase } from "@twin.org/cli-core";
6
+ import { buildCommandTsToOpenApi } from "./commands/tsToOpenApi.js";
7
+ /**
8
+ * The main entry point for the CLI.
9
+ */
10
+ export class CLI extends CLIBase {
11
+ /**
12
+ * Run the app.
13
+ * @param argv The process arguments.
14
+ * @param localesDirectory The directory for the locales, default to relative to the script.
15
+ * @param options Additional options.
16
+ * @param options.overrideOutputWidth Override the output width.
17
+ * @returns The exit code.
18
+ */
19
+ async run(argv, localesDirectory, options) {
20
+ return this.execute({
21
+ title: "TWIN TypeScript To OpenAPI",
22
+ appName: "ts-to-openapi",
23
+ version: "0.0.3-next.1", // x-release-please-version
24
+ icon: "⚙️ ",
25
+ supportsEnvFiles: false,
26
+ overrideOutputWidth: options?.overrideOutputWidth
27
+ }, localesDirectory ?? path.join(path.dirname(fileURLToPath(import.meta.url)), "../locales"), argv);
28
+ }
29
+ /**
30
+ * Configure any options or actions at the root program level.
31
+ * @param program The root program command.
32
+ */
33
+ configureRoot(program) {
34
+ buildCommandTsToOpenApi(program);
35
+ }
36
+ }
37
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEpE;;GAEG;AACH,MAAM,OAAO,GAAI,SAAQ,OAAO;IAC/B;;;;;;;OAOG;IACI,KAAK,CAAC,GAAG,CACf,IAAc,EACd,gBAAyB,EACzB,OAA0C;QAE1C,OAAO,IAAI,CAAC,OAAO,CAClB;YACC,KAAK,EAAE,4BAA4B;YACnC,OAAO,EAAE,eAAe;YACxB,OAAO,EAAE,cAAc,EAAE,2BAA2B;YACpD,IAAI,EAAE,KAAK;YACX,gBAAgB,EAAE,KAAK;YACvB,mBAAmB,EAAE,OAAO,EAAE,mBAAmB;SACjD,EACD,gBAAgB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,EACzF,IAAI,CACJ,CAAC;IACH,CAAC;IAED;;;OAGG;IACO,aAAa,CAAC,OAAgB;QACvC,uBAAuB,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;CACD","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { CLIBase } from \"@twin.org/cli-core\";\nimport type { Command } from \"commander\";\nimport { buildCommandTsToOpenApi } from \"./commands/tsToOpenApi.js\";\n\n/**\n * The main entry point for the CLI.\n */\nexport class CLI extends CLIBase {\n\t/**\n\t * Run the app.\n\t * @param argv The process arguments.\n\t * @param localesDirectory The directory for the locales, default to relative to the script.\n\t * @param options Additional options.\n\t * @param options.overrideOutputWidth Override the output width.\n\t * @returns The exit code.\n\t */\n\tpublic async run(\n\t\targv: string[],\n\t\tlocalesDirectory?: string,\n\t\toptions?: { overrideOutputWidth?: number }\n\t): Promise<number> {\n\t\treturn this.execute(\n\t\t\t{\n\t\t\t\ttitle: \"TWIN TypeScript To OpenAPI\",\n\t\t\t\tappName: \"ts-to-openapi\",\n\t\t\t\tversion: \"0.0.3-next.1\", // x-release-please-version\n\t\t\t\ticon: \"⚙️ \",\n\t\t\t\tsupportsEnvFiles: false,\n\t\t\t\toverrideOutputWidth: options?.overrideOutputWidth\n\t\t\t},\n\t\t\tlocalesDirectory ?? path.join(path.dirname(fileURLToPath(import.meta.url)), \"../locales\"),\n\t\t\targv\n\t\t);\n\t}\n\n\t/**\n\t * Configure any options or actions at the root program level.\n\t * @param program The root program command.\n\t */\n\tprotected configureRoot(program: Command): void {\n\t\tbuildCommandTsToOpenApi(program);\n\t}\n}\n"]}
@@ -0,0 +1,115 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ import { HttpStatusCode } from "@twin.org/web";
4
+ export const HTTP_STATUS_CODE_MAP = {
5
+ ok: {
6
+ code: HttpStatusCode.ok,
7
+ responseType: "OkResponse"
8
+ },
9
+ created: {
10
+ code: HttpStatusCode.created,
11
+ responseType: "CreatedResponse"
12
+ },
13
+ accepted: {
14
+ code: HttpStatusCode.accepted,
15
+ responseType: "AcceptedResponse"
16
+ },
17
+ noContent: {
18
+ code: HttpStatusCode.noContent,
19
+ responseType: "NoContentResponse"
20
+ },
21
+ badRequest: {
22
+ code: HttpStatusCode.badRequest,
23
+ responseType: "BadRequestResponse",
24
+ example: {
25
+ name: "GeneralError",
26
+ message: "errorMessage",
27
+ properties: {
28
+ foo: "bar"
29
+ }
30
+ }
31
+ },
32
+ unauthorized: {
33
+ code: HttpStatusCode.unauthorized,
34
+ responseType: "UnauthorizedResponse",
35
+ example: {
36
+ name: "UnauthorizedError",
37
+ message: "errorMessage"
38
+ }
39
+ },
40
+ forbidden: {
41
+ code: HttpStatusCode.forbidden,
42
+ responseType: "ForbiddenResponse",
43
+ example: {
44
+ name: "NotImplementedError",
45
+ message: "errorMessage",
46
+ properties: {
47
+ method: "aMethod"
48
+ }
49
+ }
50
+ },
51
+ notFound: {
52
+ code: HttpStatusCode.notFound,
53
+ responseType: "NotFoundResponse",
54
+ example: {
55
+ name: "NotFoundError",
56
+ message: "errorMessage",
57
+ properties: {
58
+ notFoundId: "1"
59
+ }
60
+ }
61
+ },
62
+ conflict: {
63
+ code: HttpStatusCode.conflict,
64
+ responseType: "ConflictResponse",
65
+ example: {
66
+ name: "ConflictError",
67
+ message: "errorMessage",
68
+ properties: {
69
+ conflicts: ["1"]
70
+ }
71
+ }
72
+ },
73
+ internalServerError: {
74
+ code: HttpStatusCode.internalServerError,
75
+ responseType: "InternalServerErrorResponse",
76
+ example: {
77
+ name: "InternalServerError",
78
+ message: "errorMessage"
79
+ }
80
+ },
81
+ unprocessableEntity: {
82
+ code: HttpStatusCode.unprocessableEntity,
83
+ responseType: "UnprocessableEntityResponse",
84
+ example: {
85
+ name: "UnprocessableError",
86
+ message: "errorMessage"
87
+ }
88
+ }
89
+ };
90
+ /**
91
+ * Get the HTTP status code from the error code type.
92
+ * @param errorCodeType The error code type.
93
+ * @returns The HTTP status code.
94
+ */
95
+ export function getHttpStatusCodeFromType(errorCodeType) {
96
+ for (const httpStatusCodeType of Object.values(HTTP_STATUS_CODE_MAP)) {
97
+ if (httpStatusCodeType.responseType === errorCodeType) {
98
+ return httpStatusCodeType.code;
99
+ }
100
+ }
101
+ return HttpStatusCode.ok;
102
+ }
103
+ /**
104
+ * Get the HTTP example from the error code type.
105
+ * @param errorCodeType The error code type.
106
+ * @returns The example.
107
+ */
108
+ export function getHttpExampleFromType(errorCodeType) {
109
+ for (const httpStatusCodeType of Object.values(HTTP_STATUS_CODE_MAP)) {
110
+ if (httpStatusCodeType.responseType === errorCodeType) {
111
+ return httpStatusCodeType.example;
112
+ }
113
+ }
114
+ }
115
+ //# sourceMappingURL=httpStatusCodeMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"httpStatusCodeMap.js","sourceRoot":"","sources":["../../../src/commands/httpStatusCodeMap.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { HttpStatusCode } from \"@twin.org/web\";\n\nexport const HTTP_STATUS_CODE_MAP: {\n\t[id: string]: {\n\t\tcode: HttpStatusCode;\n\t\tresponseType: string;\n\t\texample?: unknown;\n\t};\n} = {\n\tok: {\n\t\tcode: HttpStatusCode.ok,\n\t\tresponseType: \"OkResponse\"\n\t},\n\tcreated: {\n\t\tcode: HttpStatusCode.created,\n\t\tresponseType: \"CreatedResponse\"\n\t},\n\taccepted: {\n\t\tcode: HttpStatusCode.accepted,\n\t\tresponseType: \"AcceptedResponse\"\n\t},\n\tnoContent: {\n\t\tcode: HttpStatusCode.noContent,\n\t\tresponseType: \"NoContentResponse\"\n\t},\n\tbadRequest: {\n\t\tcode: HttpStatusCode.badRequest,\n\t\tresponseType: \"BadRequestResponse\",\n\t\texample: {\n\t\t\tname: \"GeneralError\",\n\t\t\tmessage: \"errorMessage\",\n\t\t\tproperties: {\n\t\t\t\tfoo: \"bar\"\n\t\t\t}\n\t\t}\n\t},\n\tunauthorized: {\n\t\tcode: HttpStatusCode.unauthorized,\n\t\tresponseType: \"UnauthorizedResponse\",\n\t\texample: {\n\t\t\tname: \"UnauthorizedError\",\n\t\t\tmessage: \"errorMessage\"\n\t\t}\n\t},\n\tforbidden: {\n\t\tcode: HttpStatusCode.forbidden,\n\t\tresponseType: \"ForbiddenResponse\",\n\t\texample: {\n\t\t\tname: \"NotImplementedError\",\n\t\t\tmessage: \"errorMessage\",\n\t\t\tproperties: {\n\t\t\t\tmethod: \"aMethod\"\n\t\t\t}\n\t\t}\n\t},\n\tnotFound: {\n\t\tcode: HttpStatusCode.notFound,\n\t\tresponseType: \"NotFoundResponse\",\n\t\texample: {\n\t\t\tname: \"NotFoundError\",\n\t\t\tmessage: \"errorMessage\",\n\t\t\tproperties: {\n\t\t\t\tnotFoundId: \"1\"\n\t\t\t}\n\t\t}\n\t},\n\tconflict: {\n\t\tcode: HttpStatusCode.conflict,\n\t\tresponseType: \"ConflictResponse\",\n\t\texample: {\n\t\t\tname: \"ConflictError\",\n\t\t\tmessage: \"errorMessage\",\n\t\t\tproperties: {\n\t\t\t\tconflicts: [\"1\"]\n\t\t\t}\n\t\t}\n\t},\n\tinternalServerError: {\n\t\tcode: HttpStatusCode.internalServerError,\n\t\tresponseType: \"InternalServerErrorResponse\",\n\t\texample: {\n\t\t\tname: \"InternalServerError\",\n\t\t\tmessage: \"errorMessage\"\n\t\t}\n\t},\n\tunprocessableEntity: {\n\t\tcode: HttpStatusCode.unprocessableEntity,\n\t\tresponseType: \"UnprocessableEntityResponse\",\n\t\texample: {\n\t\t\tname: \"UnprocessableError\",\n\t\t\tmessage: \"errorMessage\"\n\t\t}\n\t}\n};\n\n/**\n * Get the HTTP status code from the error code type.\n * @param errorCodeType The error code type.\n * @returns The HTTP status code.\n */\nexport function getHttpStatusCodeFromType(errorCodeType: string): HttpStatusCode {\n\tfor (const httpStatusCodeType of Object.values(HTTP_STATUS_CODE_MAP)) {\n\t\tif (httpStatusCodeType.responseType === errorCodeType) {\n\t\t\treturn httpStatusCodeType.code;\n\t\t}\n\t}\n\treturn HttpStatusCode.ok;\n}\n\n/**\n * Get the HTTP example from the error code type.\n * @param errorCodeType The error code type.\n * @returns The example.\n */\nexport function getHttpExampleFromType(errorCodeType: string): unknown {\n\tfor (const httpStatusCodeType of Object.values(HTTP_STATUS_CODE_MAP)) {\n\t\tif (httpStatusCodeType.responseType === errorCodeType) {\n\t\t\treturn httpStatusCodeType.example;\n\t\t}\n\t}\n}\n"]}
@@ -1,136 +1,23 @@
1
- import path from 'node:path';
2
- import { fileURLToPath } from 'node:url';
3
- import { CLIDisplay, CLIUtils, CLIBase } from '@twin.org/cli-core';
4
- import { mkdir, rm, writeFile } from 'node:fs/promises';
5
- import { I18n, GeneralError, Is, StringHelper, ObjectHelper } from '@twin.org/core';
6
- import { OpenApiHelper, JsonSchemaHelper } from '@twin.org/tools-core';
7
- import { HttpStatusCode, MimeTypes } from '@twin.org/web';
8
- import { createGenerator } from 'ts-json-schema-generator';
9
-
10
- const HTTP_STATUS_CODE_MAP = {
11
- ok: {
12
- code: HttpStatusCode.ok,
13
- responseType: "IOkResponse"
14
- },
15
- created: {
16
- code: HttpStatusCode.created,
17
- responseType: "ICreatedResponse"
18
- },
19
- accepted: {
20
- code: HttpStatusCode.accepted,
21
- responseType: "IAcceptedResponse"
22
- },
23
- noContent: {
24
- code: HttpStatusCode.noContent,
25
- responseType: "INoContentResponse"
26
- },
27
- badRequest: {
28
- code: HttpStatusCode.badRequest,
29
- responseType: "IBadRequestResponse",
30
- example: {
31
- name: "GeneralError",
32
- message: "component.error",
33
- properties: {
34
- foo: "bar"
35
- }
36
- }
37
- },
38
- unauthorized: {
39
- code: HttpStatusCode.unauthorized,
40
- responseType: "IUnauthorizedResponse",
41
- example: {
42
- name: "UnauthorizedError",
43
- message: "component.error"
44
- }
45
- },
46
- forbidden: {
47
- code: HttpStatusCode.forbidden,
48
- responseType: "IForbiddenResponse",
49
- example: {
50
- name: "NotImplementedError",
51
- message: "component.error",
52
- properties: {
53
- method: "aMethod"
54
- }
55
- }
56
- },
57
- notFound: {
58
- code: HttpStatusCode.notFound,
59
- responseType: "INotFoundResponse",
60
- example: {
61
- name: "NotFoundError",
62
- message: "component.error",
63
- properties: {
64
- notFoundId: "1"
65
- }
66
- }
67
- },
68
- conflict: {
69
- code: HttpStatusCode.conflict,
70
- responseType: "IConflictResponse",
71
- example: {
72
- name: "ConflictError",
73
- message: "component.error",
74
- properties: {
75
- conflicts: ["1"]
76
- }
77
- }
78
- },
79
- internalServerError: {
80
- code: HttpStatusCode.internalServerError,
81
- responseType: "IInternalServerErrorResponse",
82
- example: {
83
- name: "InternalServerError",
84
- message: "component.error"
85
- }
86
- },
87
- unprocessableEntity: {
88
- code: HttpStatusCode.unprocessableEntity,
89
- responseType: "IUnprocessableEntityResponse",
90
- example: {
91
- name: "UnprocessableError",
92
- message: "component.error"
93
- }
94
- }
95
- };
96
- /**
97
- * Get the HTTP status code from the error code type.
98
- * @param errorCodeType The error code type.
99
- * @returns The HTTP status code.
100
- */
101
- function getHttpStatusCodeFromType(errorCodeType) {
102
- for (const httpStatusCodeType of Object.values(HTTP_STATUS_CODE_MAP)) {
103
- if (httpStatusCodeType.responseType === errorCodeType) {
104
- return httpStatusCodeType.code;
105
- }
106
- }
107
- return HttpStatusCode.ok;
108
- }
109
- /**
110
- * Get the HTTP example from the error code type.
111
- * @param errorCodeType The error code type.
112
- * @returns The example.
113
- */
114
- function getHttpExampleFromType(errorCodeType) {
115
- for (const httpStatusCodeType of Object.values(HTTP_STATUS_CODE_MAP)) {
116
- if (httpStatusCodeType.responseType === errorCodeType) {
117
- return httpStatusCodeType.example;
118
- }
119
- }
120
- }
121
-
122
1
  // Copyright 2024 IOTA Stiftung.
123
2
  // SPDX-License-Identifier: Apache-2.0.
3
+ import { mkdir, rm, writeFile } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { CLIDisplay, CLIUtils } from "@twin.org/cli-core";
6
+ import { GeneralError, I18n, Is, ObjectHelper, StringHelper } from "@twin.org/core";
7
+ import { JsonSchemaHelper, OpenApiHelper } from "@twin.org/tools-core";
8
+ import { HttpStatusCode, MimeTypes } from "@twin.org/web";
9
+ import { createGenerator } from "ts-json-schema-generator";
10
+ import { HTTP_STATUS_CODE_MAP, getHttpExampleFromType, getHttpStatusCodeFromType } from "./httpStatusCodeMap.js";
124
11
  /**
125
12
  * Build the root command to be consumed by the CLI.
126
13
  * @param program The command to build on.
127
14
  */
128
- function buildCommandTsToOpenApi(program) {
15
+ export function buildCommandTsToOpenApi(program) {
129
16
  program
130
17
  .argument(I18n.formatMessage("commands.ts-to-openapi.options.config.param"), I18n.formatMessage("commands.ts-to-openapi.options.config.description"))
131
18
  .argument(I18n.formatMessage("commands.ts-to-openapi.options.output-file.param"), I18n.formatMessage("commands.ts-to-openapi.options.output-file.description"))
132
19
  .action(async (config, outputFile, opts) => {
133
- await actionCommandTsToOpenApi(config, outputFile);
20
+ await actionCommandTsToOpenApi(config, outputFile, opts);
134
21
  });
135
22
  }
136
23
  /**
@@ -139,7 +26,7 @@ function buildCommandTsToOpenApi(program) {
139
26
  * @param outputFile The output file for the generation OpenApi spec.
140
27
  * @param opts The options for the command.
141
28
  */
142
- async function actionCommandTsToOpenApi(configFile, outputFile, opts) {
29
+ export async function actionCommandTsToOpenApi(configFile, outputFile, opts) {
143
30
  let outputWorkingDir;
144
31
  try {
145
32
  let config;
@@ -183,14 +70,18 @@ async function actionCommandTsToOpenApi(configFile, outputFile, opts) {
183
70
  * @param outputFile The location of the file to output the OpenAPI spec.
184
71
  * @param workingDirectory The folder the app was run from.
185
72
  */
186
- async function tsToOpenApi(config, outputFile, workingDirectory) {
73
+ export async function tsToOpenApi(config, outputFile, workingDirectory) {
187
74
  await writeFile(path.join(workingDirectory, "package.json"), JSON.stringify({
188
75
  version: "1.0.0",
189
76
  name: "ts-to-openapi-working",
190
77
  dependencies: {}
191
78
  }, undefined, "\t"));
192
79
  await writeFile(path.join(workingDirectory, "tsconfig.json"), JSON.stringify({
193
- compilerOptions: {}
80
+ compilerOptions: {
81
+ module: "nodenext",
82
+ moduleResolution: "nodenext",
83
+ target: "ES2022"
84
+ }
194
85
  }, undefined, "\t"));
195
86
  const openApi = {
196
87
  openapi: OpenApiHelper.API_VERSION,
@@ -213,6 +104,7 @@ async function tsToOpenApi(config, outputFile, workingDirectory) {
213
104
  const securitySchemes = {};
214
105
  buildSecurity(config, securitySchemes, authSecurity);
215
106
  const types = Object.values(HTTP_STATUS_CODE_MAP).map(h => h.responseType);
107
+ const responseCodes = [];
216
108
  const inputResults = [];
217
109
  const typeRoots = [];
218
110
  const restRoutesAndTags = await loadPackages(config, workingDirectory, typeRoots);
@@ -270,7 +162,7 @@ async function tsToOpenApi(config, outputFile, workingDirectory) {
270
162
  if (pathSpecificAuthSecurity.length > 0) {
271
163
  responseTypes.push({
272
164
  statusCode: HttpStatusCode.unauthorized,
273
- type: "IUnauthorizedResponse"
165
+ type: "UnauthorizedResponse"
274
166
  });
275
167
  }
276
168
  for (const responseType of responseTypes) {
@@ -356,8 +248,7 @@ async function tsToOpenApi(config, outputFile, workingDirectory) {
356
248
  responses.push({
357
249
  code: responseType.statusCode,
358
250
  description,
359
- content: responseType.type === "ICreatedResponse" ||
360
- responseType.type === "INoContentResponse"
251
+ content: responseType.type === "CreatedResponse" || responseType.type === "NoContentResponse"
361
252
  ? undefined
362
253
  : {
363
254
  [mimeType]: {
@@ -382,6 +273,9 @@ async function tsToOpenApi(config, outputFile, workingDirectory) {
382
273
  // Only include the response code if it hasn't already been
383
274
  // included with a specific response
384
275
  if (!responseTypes.some(r => r.statusCode === responseCodeDetails.code)) {
276
+ if (!responseCodes.includes(responseCode)) {
277
+ responseCodes.push(responseCode);
278
+ }
385
279
  let examples;
386
280
  if (responseCodeDetails.example) {
387
281
  examples = {
@@ -420,8 +314,7 @@ async function tsToOpenApi(config, outputFile, workingDirectory) {
420
314
  in: "path",
421
315
  style: "simple"
422
316
  }));
423
- const requestExample = inputPath.requestExamples?.[0]
424
- ?.request;
317
+ const requestExample = inputPath.requestExamples?.[0]?.request;
425
318
  if (Is.object(requestExample?.pathParams)) {
426
319
  for (const pathOrQueryParam of pathQueryHeaderParams) {
427
320
  if (requestExample.pathParams[pathOrQueryParam.name]) {
@@ -798,7 +691,7 @@ async function processPackageRestDetails(restRoutes) {
798
691
  // But only if we haven't got a response already for different content type
799
692
  if (responseType.length === 0) {
800
693
  responseType.push({
801
- type: "IOkResponse",
694
+ type: "OkResponse",
802
695
  statusCode: HttpStatusCode.ok
803
696
  });
804
697
  }
@@ -1003,7 +896,7 @@ async function loadPackages(tsToOpenApiConfig, outputWorkingDir, typeRoots) {
1003
896
  }
1004
897
  }
1005
898
  CLIDisplay.task(I18n.formatMessage("commands.ts-to-openapi.progress.importingModule"), pkgJson.name);
1006
- const pkg = await import(`file://${path.join(rootFolder, "dist/esm/index.mjs")}`);
899
+ const pkg = await import(`file://${path.join(rootFolder, "dist/es/index.js")}`);
1007
900
  if (!Is.array(pkg.restEntryPoints)) {
1008
901
  throw new GeneralError("commands", "commands.ts-to-openapi.missingRestRoutesEntryPoints", {
1009
902
  method: "restEntryPoints",
@@ -1040,38 +933,4 @@ async function loadPackages(tsToOpenApiConfig, outputWorkingDir, typeRoots) {
1040
933
  }
1041
934
  return restRoutes;
1042
935
  }
1043
-
1044
- // Copyright 2024 IOTA Stiftung.
1045
- // SPDX-License-Identifier: Apache-2.0.
1046
- /**
1047
- * The main entry point for the CLI.
1048
- */
1049
- class CLI extends CLIBase {
1050
- /**
1051
- * Run the app.
1052
- * @param argv The process arguments.
1053
- * @param localesDirectory The directory for the locales, default to relative to the script.
1054
- * @param options Additional options.
1055
- * @param options.overrideOutputWidth Override the output width.
1056
- * @returns The exit code.
1057
- */
1058
- async run(argv, localesDirectory, options) {
1059
- return this.execute({
1060
- title: "TWIN TypeScript To OpenAPI",
1061
- appName: "ts-to-openapi",
1062
- version: "0.0.2-next.8", // x-release-please-version
1063
- icon: "⚙️ ",
1064
- supportsEnvFiles: false,
1065
- overrideOutputWidth: options?.overrideOutputWidth
1066
- }, localesDirectory ?? path.join(path.dirname(fileURLToPath(import.meta.url)), "../locales"), argv);
1067
- }
1068
- /**
1069
- * Configure any options or actions at the root program level.
1070
- * @param program The root program command.
1071
- */
1072
- configureRoot(program) {
1073
- buildCommandTsToOpenApi(program);
1074
- }
1075
- }
1076
-
1077
- export { CLI, actionCommandTsToOpenApi, buildCommandTsToOpenApi, tsToOpenApi };
936
+ //# sourceMappingURL=tsToOpenApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tsToOpenApi.js","sourceRoot":"","sources":["../../../src/commands/tsToOpenApi.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { mkdir, rm, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { CLIDisplay, CLIUtils } from \"@twin.org/cli-core\";\nimport { GeneralError, I18n, Is, ObjectHelper, StringHelper } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport {\n\tJsonSchemaHelper,\n\tOpenApiHelper,\n\ttype IJsonSchema,\n\ttype IOpenApi,\n\ttype IOpenApiExample,\n\ttype IOpenApiHeader,\n\ttype IOpenApiResponse,\n\ttype IOpenApiSecurityScheme,\n\ttype IPackageJson,\n\ttype JsonTypeName\n} from \"@twin.org/tools-core\";\nimport { HttpStatusCode, MimeTypes } from \"@twin.org/web\";\nimport type { Command } from \"commander\";\nimport { createGenerator } from \"ts-json-schema-generator\";\nimport {\n\tHTTP_STATUS_CODE_MAP,\n\tgetHttpExampleFromType,\n\tgetHttpStatusCodeFromType\n} from \"./httpStatusCodeMap.js\";\nimport type { IInputPath } from \"../models/IInputPath.js\";\nimport type { IInputResult } from \"../models/IInputResult.js\";\nimport type { IRestRoute } from \"../models/IRestRoute.js\";\nimport type { IRestRouteEntryPoint } from \"../models/IRestRouteEntryPoints.js\";\nimport type { ITag } from \"../models/ITag.js\";\nimport type { ITsToOpenApiConfig } from \"../models/ITsToOpenApiConfig.js\";\nimport type { ITsToOpenApiConfigEntryPoint } from \"../models/ITsToOpenApiConfigEntryPoint.js\";\n\n/**\n * Build the root command to be consumed by the CLI.\n * @param program The command to build on.\n */\nexport function buildCommandTsToOpenApi(program: Command): void {\n\tprogram\n\t\t.argument(\n\t\t\tI18n.formatMessage(\"commands.ts-to-openapi.options.config.param\"),\n\t\t\tI18n.formatMessage(\"commands.ts-to-openapi.options.config.description\")\n\t\t)\n\t\t.argument(\n\t\t\tI18n.formatMessage(\"commands.ts-to-openapi.options.output-file.param\"),\n\t\t\tI18n.formatMessage(\"commands.ts-to-openapi.options.output-file.description\")\n\t\t)\n\t\t.action(async (config, outputFile, opts) => {\n\t\t\tawait actionCommandTsToOpenApi(config, outputFile, opts);\n\t\t});\n}\n\n/**\n * Action the root command.\n * @param configFile The optional configuration file.\n * @param outputFile The output file for the generation OpenApi spec.\n * @param opts The options for the command.\n */\nexport async function actionCommandTsToOpenApi(\n\tconfigFile: string,\n\toutputFile: string,\n\topts: unknown\n): Promise<void> {\n\tlet outputWorkingDir: string | undefined;\n\ttry {\n\t\tlet config: ITsToOpenApiConfig | undefined;\n\n\t\tconst fullConfigFile = path.resolve(configFile);\n\t\tconst fullOutputFile = path.resolve(outputFile);\n\t\toutputWorkingDir = path.join(path.dirname(fullOutputFile), \"working\");\n\n\t\tCLIDisplay.value(\n\t\t\tI18n.formatMessage(\"commands.ts-to-openapi.labels.configJson\"),\n\t\t\tfullConfigFile\n\t\t);\n\t\tCLIDisplay.value(\n\t\t\tI18n.formatMessage(\"commands.ts-to-openapi.labels.outputFile\"),\n\t\t\tfullOutputFile\n\t\t);\n\t\tCLIDisplay.value(\n\t\t\tI18n.formatMessage(\"commands.ts-to-openapi.labels.outputWorkingDir\"),\n\t\t\toutputWorkingDir\n\t\t);\n\t\tCLIDisplay.break();\n\n\t\ttry {\n\t\t\tCLIDisplay.task(I18n.formatMessage(\"commands.ts-to-openapi.progress.loadingConfigJson\"));\n\t\t\tCLIDisplay.break();\n\n\t\t\tconfig = await CLIUtils.readJsonFile<ITsToOpenApiConfig>(fullConfigFile);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\"commands\", \"commands.ts-to-openapi.configFailed\", undefined, err);\n\t\t}\n\n\t\tif (Is.empty(config)) {\n\t\t\tthrow new GeneralError(\"commands\", \"commands.ts-to-openapi.configFailed\");\n\t\t}\n\n\t\tCLIDisplay.task(I18n.formatMessage(\"commands.ts-to-openapi.progress.creatingWorkingDir\"));\n\t\tawait mkdir(outputWorkingDir, { recursive: true });\n\t\tCLIDisplay.break();\n\n\t\tawait tsToOpenApi(config ?? {}, fullOutputFile, outputWorkingDir);\n\n\t\tCLIDisplay.break();\n\t\tCLIDisplay.done();\n\t} finally {\n\t\ttry {\n\t\t\tif (outputWorkingDir) {\n\t\t\t\tawait rm(outputWorkingDir, { recursive: true });\n\t\t\t}\n\t\t} catch {}\n\t}\n}\n\n/**\n * Convert the TypeScript definitions to OpenAPI spec.\n * @param config The configuration for the app.\n * @param outputFile The location of the file to output the OpenAPI spec.\n * @param workingDirectory The folder the app was run from.\n */\nexport async function tsToOpenApi(\n\tconfig: ITsToOpenApiConfig,\n\toutputFile: string,\n\tworkingDirectory: string\n): Promise<void> {\n\tawait writeFile(\n\t\tpath.join(workingDirectory, \"package.json\"),\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\tversion: \"1.0.0\",\n\t\t\t\tname: \"ts-to-openapi-working\",\n\t\t\t\tdependencies: {}\n\t\t\t},\n\t\t\tundefined,\n\t\t\t\"\\t\"\n\t\t)\n\t);\n\n\tawait writeFile(\n\t\tpath.join(workingDirectory, \"tsconfig.json\"),\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\tcompilerOptions: {\n\t\t\t\t\tmodule: \"nodenext\",\n\t\t\t\t\tmoduleResolution: \"nodenext\",\n\t\t\t\t\ttarget: \"ES2022\"\n\t\t\t\t}\n\t\t\t},\n\t\t\tundefined,\n\t\t\t\"\\t\"\n\t\t)\n\t);\n\n\tconst openApi: IOpenApi = {\n\t\topenapi: OpenApiHelper.API_VERSION,\n\t\tinfo: {\n\t\t\ttitle: config.title,\n\t\t\tdescription: config.description,\n\t\t\tversion: config.version,\n\t\t\tlicense: {\n\t\t\t\tname: config.licenseName,\n\t\t\t\turl: config.licenseUrl\n\t\t\t}\n\t\t},\n\t\tservers: Is.arrayValue(config.servers) ? config.servers.map(s => ({ url: s })) : undefined,\n\t\ttags: [],\n\t\tpaths: {}\n\t};\n\n\tCLIDisplay.task(I18n.formatMessage(\"commands.ts-to-openapi.progress.creatingSecuritySchemas\"));\n\tCLIDisplay.break();\n\n\tconst authSecurity: { [name: string]: string[] }[] = [];\n\tconst securitySchemes: { [name: string]: IOpenApiSecurityScheme } = {};\n\n\tbuildSecurity(config, securitySchemes, authSecurity);\n\n\tconst types: string[] = Object.values(HTTP_STATUS_CODE_MAP).map(h => h.responseType);\n\tconst responseCodes: string[] = [];\n\tconst inputResults: IInputResult[] = [];\n\tconst typeRoots: string[] = [];\n\tconst restRoutesAndTags = await loadPackages(config, workingDirectory, typeRoots);\n\n\tfor (const restRouteAndTag of restRoutesAndTags) {\n\t\tconst paths = await processPackageRestDetails(restRouteAndTag.restRoutes);\n\t\tinputResults.push({\n\t\t\tpaths,\n\t\t\ttags: restRouteAndTag.tags\n\t\t});\n\n\t\tfor (const inputPath of paths) {\n\t\t\tif (inputPath.requestType && !types.includes(inputPath.requestType)) {\n\t\t\t\ttypes.push(inputPath.requestType);\n\t\t\t}\n\n\t\t\tif (inputPath.responseType) {\n\t\t\t\tconst rt = inputPath.responseType.map(i => i.type);\n\t\t\t\tfor (const r of rt) {\n\t\t\t\t\tif (r && inputPath.responseType && !types.includes(r)) {\n\t\t\t\t\t\ttypes.push(r);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tCLIDisplay.task(I18n.formatMessage(\"commands.ts-to-openapi.progress.generatingSchemas\"));\n\n\tconst autoExpandTypes = config.autoExpandTypes ?? [];\n\tconst defaultExpandTypes = [\"/ObjectOrArray<.*>/\"];\n\tfor (const defaultType of defaultExpandTypes) {\n\t\tif (!autoExpandTypes.includes(defaultType)) {\n\t\t\tautoExpandTypes.push(defaultType);\n\t\t}\n\t}\n\n\tconst schemas = await generateSchemas(typeRoots, types, autoExpandTypes, workingDirectory);\n\n\tfor (const type in schemas) {\n\t\tif (Is.object<IJsonSchema>(config.overrides?.[type])) {\n\t\t\tCLIDisplay.task(I18n.formatMessage(\"commands.ts-to-openapi.progress.overridingSchema\"));\n\t\t\tschemas[type] = config.overrides?.[type];\n\t\t}\n\t}\n\n\tconst usedCommonResponseTypes: string[] = [];\n\n\tfor (let i = 0; i < inputResults.length; i++) {\n\t\tconst result = inputResults[i];\n\t\tfor (const tag of result.tags) {\n\t\t\tconst exists = openApi.tags?.find(t => t.name === tag.name);\n\t\t\tif (!exists) {\n\t\t\t\topenApi.tags?.push(tag);\n\t\t\t}\n\t\t}\n\n\t\tfor (const inputPath of result.paths) {\n\t\t\tconst responses: ({ code?: HttpStatusCode } & IOpenApiResponse)[] = [];\n\t\t\tconst responseTypes = inputPath.responseType;\n\n\t\t\tconst pathSpecificAuthSecurity: { [name: string]: string[] }[] = [];\n\n\t\t\tif (authSecurity.length > 0 && !inputPath.skipAuth) {\n\t\t\t\tpathSpecificAuthSecurity.push(...authSecurity);\n\t\t\t}\n\n\t\t\tif (pathSpecificAuthSecurity.length > 0) {\n\t\t\t\tresponseTypes.push({\n\t\t\t\t\tstatusCode: HttpStatusCode.unauthorized,\n\t\t\t\t\ttype: \"UnauthorizedResponse\"\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tfor (const responseType of responseTypes) {\n\t\t\t\tif (schemas[responseType.type]) {\n\t\t\t\t\tlet headers: { [id: string]: IOpenApiHeader } | undefined;\n\t\t\t\t\tlet examples: { [id: string]: IOpenApiExample } | undefined;\n\n\t\t\t\t\tif (Is.arrayValue(responseType.examples)) {\n\t\t\t\t\t\tfor (const example of responseType.examples) {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tIs.object<{ headers: { [id: string]: string | string[] }; body: unknown }>(\n\t\t\t\t\t\t\t\t\texample.response\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tif (Is.objectValue(example.response.headers)) {\n\t\t\t\t\t\t\t\t\theaders ??= {};\n\t\t\t\t\t\t\t\t\tconst headersSchema = schemas[responseType.type].properties\n\t\t\t\t\t\t\t\t\t\t?.headers as IJsonSchema;\n\t\t\t\t\t\t\t\t\tfor (const header in example.response.headers) {\n\t\t\t\t\t\t\t\t\t\tconst headerValue = example.response.headers[header];\n\t\t\t\t\t\t\t\t\t\tconst propertySchema = headersSchema.properties?.[header];\n\t\t\t\t\t\t\t\t\t\tconst schemaType = Is.object<IJsonSchema>(propertySchema)\n\t\t\t\t\t\t\t\t\t\t\t? propertySchema?.type\n\t\t\t\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\t\t\t\t\theaders[header] = {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: Is.string(schemaType) ? schemaType : \"string\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tdescription: `e.g. ${\n\t\t\t\t\t\t\t\t\t\t\t\tIs.array(headerValue) ? headerValue.join(\",\") : headerValue\n\t\t\t\t\t\t\t\t\t\t\t}`\n\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (!Is.undefined(example.response.body)) {\n\t\t\t\t\t\t\t\t\texamples ??= {};\n\t\t\t\t\t\t\t\t\texamples[example.id] = {\n\t\t\t\t\t\t\t\t\t\tsummary: example.description,\n\t\t\t\t\t\t\t\t\t\tvalue: example.response.body\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst statusExample = getHttpExampleFromType(responseType.type);\n\t\t\t\t\t\tif (statusExample) {\n\t\t\t\t\t\t\texamples = {};\n\t\t\t\t\t\t\texamples.exampleResponse = {\n\t\t\t\t\t\t\t\tvalue: statusExample\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tlet mimeType: string;\n\t\t\t\t\tlet schemaType: string | undefined;\n\t\t\t\t\tlet schemaFormat: string | undefined;\n\t\t\t\t\tlet schemaRef: string | undefined;\n\t\t\t\t\tlet description: string | undefined = schemas[responseType.type]?.description;\n\n\t\t\t\t\tif (Is.stringValue(responseType.mimeType)) {\n\t\t\t\t\t\tmimeType = responseType.mimeType;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst hasBody = Is.notEmpty(schemas[responseType.type]?.properties?.body);\n\t\t\t\t\t\tif (hasBody) {\n\t\t\t\t\t\t\tmimeType = MimeTypes.Json;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmimeType = MimeTypes.PlainText;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Perform some special handling for binary octet-streams to produce a nicer spec output\n\t\t\t\t\tif (responseType.type === nameof<Uint8Array>()) {\n\t\t\t\t\t\tschemaType = \"string\";\n\t\t\t\t\t\tschemaFormat = \"binary\";\n\t\t\t\t\t\tschemaRef = undefined;\n\t\t\t\t\t\tdescription = \"Binary data\";\n\t\t\t\t\t\tif (Is.objectValue<IOpenApiExample>(examples)) {\n\t\t\t\t\t\t\tconst exampleKeys = Object.keys(examples);\n\n\t\t\t\t\t\t\tconst firstExample = examples[exampleKeys[0]];\n\t\t\t\t\t\t\tdescription = firstExample.summary;\n\t\t\t\t\t\t\tfirstExample.summary = \"Binary Data\";\n\n\t\t\t\t\t\t\tfor (const exampleKey in examples) {\n\t\t\t\t\t\t\t\texamples[exampleKey].value = \"\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tschemaRef = `#/definitions/${responseType.type}`;\n\t\t\t\t\t}\n\n\t\t\t\t\tresponses.push({\n\t\t\t\t\t\tcode: responseType.statusCode,\n\t\t\t\t\t\tdescription,\n\t\t\t\t\t\tcontent:\n\t\t\t\t\t\t\tresponseType.type === \"CreatedResponse\" || responseType.type === \"NoContentResponse\"\n\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t\t[mimeType]: {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: schemaRef,\n\t\t\t\t\t\t\t\t\t\t\t\ttype: schemaType,\n\t\t\t\t\t\t\t\t\t\t\t\tformat: schemaFormat\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\texamples\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\theaders\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (!usedCommonResponseTypes.includes(responseType.type)) {\n\t\t\t\t\tusedCommonResponseTypes.push(responseType.type);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (inputPath.responseCodes.length > 0) {\n\t\t\t\tfor (const responseCode of inputPath.responseCodes) {\n\t\t\t\t\tconst responseCodeDetails = HTTP_STATUS_CODE_MAP[responseCode];\n\t\t\t\t\t// Only include the response code if it hasn't already been\n\t\t\t\t\t// included with a specific response\n\t\t\t\t\tif (!responseTypes.some(r => r.statusCode === responseCodeDetails.code)) {\n\t\t\t\t\t\tif (!responseCodes.includes(responseCode)) {\n\t\t\t\t\t\t\tresponseCodes.push(responseCode);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet examples: { [id: string]: IOpenApiExample } | undefined;\n\n\t\t\t\t\t\tif (responseCodeDetails.example) {\n\t\t\t\t\t\t\texamples = {\n\t\t\t\t\t\t\t\texampleResponse: {\n\t\t\t\t\t\t\t\t\tvalue: responseCodeDetails.example\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (schemas[responseCodeDetails.responseType]) {\n\t\t\t\t\t\t\tresponses.push({\n\t\t\t\t\t\t\t\tcode: responseCodeDetails.code,\n\t\t\t\t\t\t\t\tdescription: schemas[responseCodeDetails.responseType].description,\n\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t[MimeTypes.Json]: {\n\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t$ref: `#/definitions/${responseCodeDetails.responseType}`\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\texamples\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!usedCommonResponseTypes.includes(responseCodeDetails.responseType)) {\n\t\t\t\t\t\t\tusedCommonResponseTypes.push(responseCodeDetails.responseType);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst pathQueryHeaderParams: {\n\t\t\t\tname: string;\n\t\t\t\tdescription?: string;\n\t\t\t\trequired: boolean;\n\t\t\t\tin: \"path\" | \"query\" | \"header\";\n\t\t\t\tschema: {\n\t\t\t\t\ttype?: JsonTypeName | JsonTypeName[];\n\t\t\t\t\tenum?: IJsonSchema[];\n\t\t\t\t\t$ref?: string;\n\t\t\t\t};\n\t\t\t\tstyle?: string;\n\t\t\t\texample?: unknown;\n\t\t\t}[] = inputPath.pathParameters.map(p => ({\n\t\t\t\tname: p,\n\t\t\t\tdescription: \"\",\n\t\t\t\trequired: true,\n\t\t\t\tschema: {\n\t\t\t\t\ttype: \"string\"\n\t\t\t\t},\n\t\t\t\tin: \"path\",\n\t\t\t\tstyle: \"simple\"\n\t\t\t}));\n\n\t\t\tconst requestExample = inputPath.requestExamples?.[0]?.request as {\n\t\t\t\tpathParams: { [id: string]: string };\n\t\t\t\theaders: { [id: string]: string };\n\t\t\t\tquery: { [id: string]: string };\n\t\t\t};\n\n\t\t\tif (Is.object(requestExample?.pathParams)) {\n\t\t\t\tfor (const pathOrQueryParam of pathQueryHeaderParams) {\n\t\t\t\t\tif (requestExample.pathParams[pathOrQueryParam.name]) {\n\t\t\t\t\t\tpathOrQueryParam.example = requestExample.pathParams[pathOrQueryParam.name];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet requestObject: IJsonSchema | undefined = inputPath.requestType\n\t\t\t\t? schemas[inputPath.requestType]\n\t\t\t\t: undefined;\n\n\t\t\tif (requestObject?.properties) {\n\t\t\t\t// If there are any properties other than body, query, pathParams and headers\n\t\t\t\t// we should throw an error as we don't know what to do with them\n\t\t\t\tconst otherKeys = Object.keys(requestObject.properties).filter(\n\t\t\t\t\tk => ![\"body\", \"query\", \"pathParams\", \"headers\"].includes(k)\n\t\t\t\t);\n\t\t\t\tif (otherKeys.length > 0) {\n\t\t\t\t\tthrow new GeneralError(\"commands\", \"commands.ts-to-openapi.unsupportedProperties\", {\n\t\t\t\t\t\tkeys: otherKeys.join(\", \")\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// If there is a path params object convert these to params\n\t\t\t\tif (Is.object<IJsonSchema>(requestObject.properties.pathParams)) {\n\t\t\t\t\tfor (const pathParam of pathQueryHeaderParams) {\n\t\t\t\t\t\tconst prop = requestObject.properties.pathParams.properties?.[pathParam.name];\n\t\t\t\t\t\tif (Is.object<IJsonSchema>(prop)) {\n\t\t\t\t\t\t\tpathParam.description = prop.description ?? pathParam.description;\n\t\t\t\t\t\t\tpathParam.schema = {\n\t\t\t\t\t\t\t\ttype: prop.type,\n\t\t\t\t\t\t\t\tenum: prop.enum,\n\t\t\t\t\t\t\t\t$ref: prop.$ref\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tpathParam.required = true;\n\t\t\t\t\t\t\tdelete requestObject.properties.pathParams.properties?.[pathParam.name];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdelete requestObject.properties.pathParams;\n\t\t\t\t}\n\n\t\t\t\t// If there is a query object convert these to params as well\n\t\t\t\tif (Is.object<IJsonSchema>(requestObject.properties.query)) {\n\t\t\t\t\tfor (const prop in requestObject.properties.query.properties) {\n\t\t\t\t\t\tconst queryProp = requestObject.properties.query.properties[prop];\n\t\t\t\t\t\tif (Is.object<IJsonSchema>(queryProp)) {\n\t\t\t\t\t\t\tlet example: unknown;\n\t\t\t\t\t\t\tif (Is.object(requestExample.query) && requestExample.query[prop]) {\n\t\t\t\t\t\t\t\texample = requestExample.query[prop];\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tpathQueryHeaderParams.push({\n\t\t\t\t\t\t\t\tname: prop,\n\t\t\t\t\t\t\t\tdescription: queryProp.description,\n\t\t\t\t\t\t\t\trequired: Boolean(requestObject.required?.includes(prop)),\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: queryProp.type,\n\t\t\t\t\t\t\t\t\tenum: queryProp.enum,\n\t\t\t\t\t\t\t\t\t$ref: queryProp.$ref\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\t\t\texample\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tdelete requestObject.properties.query.properties[prop];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdelete requestObject.properties.query;\n\t\t\t\t}\n\n\t\t\t\t// If there are headers in the object convert these to spec params\n\t\t\t\tif (Is.object<IJsonSchema>(requestObject.properties.headers)) {\n\t\t\t\t\tconst headerProperties = requestObject.properties.headers.properties;\n\n\t\t\t\t\tfor (const prop in headerProperties) {\n\t\t\t\t\t\tconst headerSchema = headerProperties[prop];\n\t\t\t\t\t\tif (Is.object<IJsonSchema>(headerSchema)) {\n\t\t\t\t\t\t\tlet example: unknown;\n\t\t\t\t\t\t\tif (Is.object(requestExample.headers) && requestExample.headers[prop]) {\n\t\t\t\t\t\t\t\texample = requestExample.headers[prop];\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tpathQueryHeaderParams.push({\n\t\t\t\t\t\t\t\tname: prop,\n\t\t\t\t\t\t\t\tdescription: headerSchema.description,\n\t\t\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"string\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tin: \"header\",\n\t\t\t\t\t\t\t\tstyle: \"simple\",\n\t\t\t\t\t\t\t\texample\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdelete requestObject.properties.headers;\n\t\t\t\t}\n\n\t\t\t\t// If we have used all the properties from the object in the\n\t\t\t\t// path we should remove it.\n\t\t\t\tif (Object.keys(requestObject.properties).length === 0 && inputPath.requestType) {\n\t\t\t\t\tdelete schemas[inputPath.requestType];\n\t\t\t\t\trequestObject = undefined;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (config.restRoutes) {\n\t\t\t\tlet fullPath = StringHelper.trimTrailingSlashes(inputPath.path);\n\t\t\t\tif (fullPath.length === 0) {\n\t\t\t\t\tfullPath = \"/\";\n\t\t\t\t}\n\t\t\t\topenApi.paths[fullPath] ??= {};\n\n\t\t\t\tconst method = inputPath.method.toLowerCase();\n\t\t\t\topenApi.paths[fullPath][method] = {\n\t\t\t\t\toperationId: inputPath.operationId,\n\t\t\t\t\tsummary: inputPath.summary,\n\t\t\t\t\ttags: [inputPath.tag],\n\t\t\t\t\tparameters:\n\t\t\t\t\t\tpathQueryHeaderParams.length > 0\n\t\t\t\t\t\t\t? pathQueryHeaderParams.map(p => ({\n\t\t\t\t\t\t\t\t\tname: p.name,\n\t\t\t\t\t\t\t\t\tdescription: p.description,\n\t\t\t\t\t\t\t\t\tin: p.in,\n\t\t\t\t\t\t\t\t\trequired: p.required,\n\t\t\t\t\t\t\t\t\tschema: p.schema,\n\t\t\t\t\t\t\t\t\tstyle: p.style,\n\t\t\t\t\t\t\t\t\texample: p.example\n\t\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t};\n\n\t\t\t\tif (pathSpecificAuthSecurity.length > 0) {\n\t\t\t\t\topenApi.paths[fullPath][method].security = pathSpecificAuthSecurity;\n\t\t\t\t}\n\n\t\t\t\tif (requestObject && inputPath.requestType) {\n\t\t\t\t\tlet examples: { [id: string]: IOpenApiExample } | undefined;\n\t\t\t\t\tif (Is.arrayValue(inputPath.requestExamples)) {\n\t\t\t\t\t\tfor (const example of inputPath.requestExamples) {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tIs.object<{ body: unknown }>(example.request) &&\n\t\t\t\t\t\t\t\t!Is.undefined(example.request.body)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\texamples ??= {};\n\t\t\t\t\t\t\t\texamples[example.id] = {\n\t\t\t\t\t\t\t\t\tsummary: example.description,\n\t\t\t\t\t\t\t\t\tvalue: example.request.body\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tlet requestMimeType: string;\n\t\t\t\t\tif (Is.stringValue(inputPath.requestMimeType)) {\n\t\t\t\t\t\trequestMimeType = inputPath.requestMimeType;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst hasBody = Is.notEmpty(schemas[inputPath.requestType]?.properties?.body);\n\t\t\t\t\t\tif (hasBody) {\n\t\t\t\t\t\t\trequestMimeType = MimeTypes.Json;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\trequestMimeType = MimeTypes.PlainText;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\topenApi.paths[fullPath][method].requestBody = {\n\t\t\t\t\t\tdescription: requestObject.description,\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t[requestMimeType]: {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t$ref: `#/definitions/${inputPath.requestType}`\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\texamples\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (responses.length > 0) {\n\t\t\t\t\tconst openApiResponses: { [code: string]: IOpenApiResponse } = {};\n\t\t\t\t\tfor (const response of responses) {\n\t\t\t\t\t\tconst code = response.code;\n\t\t\t\t\t\tif (code) {\n\t\t\t\t\t\t\tdelete response.code;\n\t\t\t\t\t\t\topenApiResponses[code] ??= {};\n\t\t\t\t\t\t\topenApiResponses[code] = ObjectHelper.merge(openApiResponses[code], response);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\topenApi.paths[fullPath][method].responses = openApiResponses;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tawait finaliseOutput(\n\t\tusedCommonResponseTypes,\n\t\tschemas,\n\t\topenApi,\n\t\tsecuritySchemes,\n\t\tconfig.externalReferences,\n\t\tautoExpandTypes,\n\t\toutputFile\n\t);\n}\n\n/**\n * Finalise the schemas and output the spec.\n * @param usedCommonResponseTypes The common response types used.\n * @param schemas The schemas.\n * @param openApi The OpenAPI spec.\n * @param securitySchemes The security schemes.\n * @param externalReferences The external references.\n * @param autoExpandTypes The auto expand types.\n * @param outputFile The output file.\n */\nasync function finaliseOutput(\n\tusedCommonResponseTypes: string[],\n\tschemas: { [id: string]: IJsonSchema },\n\topenApi: IOpenApi,\n\tsecuritySchemes: { [name: string]: IOpenApiSecurityScheme },\n\texternalReferences: { [type: string]: string } | undefined,\n\tautoExpandTypes: string[],\n\toutputFile: string\n): Promise<void> {\n\tCLIDisplay.break();\n\tCLIDisplay.task(I18n.formatMessage(\"commands.ts-to-openapi.progress.finalisingSchemas\"));\n\n\t// Remove the response codes that we haven't used\n\tfor (const httpStatusCode in HTTP_STATUS_CODE_MAP) {\n\t\tif (!usedCommonResponseTypes.includes(HTTP_STATUS_CODE_MAP[httpStatusCode].responseType)) {\n\t\t\tdelete schemas[HTTP_STATUS_CODE_MAP[httpStatusCode].responseType];\n\t\t}\n\t}\n\n\tconst substituteSchemas: { from: string; to: string }[] = [];\n\tconst finalExternals: { [id: string]: string } = {};\n\n\t// Remove the I, < and > from names\n\tconst finalSchemas: {\n\t\t[id: string]: IJsonSchema;\n\t} = {};\n\tfor (const schema in schemas) {\n\t\tconst props = schemas[schema].properties;\n\t\tlet skipSchema = false;\n\n\t\tif (Is.object<{ [id: string]: IJsonSchema | boolean }>(props)) {\n\t\t\ttidySchemaProperties(props);\n\n\t\t\t// Any request/response objects should be added to the final schemas\n\t\t\t// but only the body property, if there is no body then we don't\n\t\t\t// need to add it to the schemas\n\t\t\tif (schema.endsWith(\"Response\") || schema.endsWith(\"Request\")) {\n\t\t\t\tif (Is.object<IJsonSchema>(props.body)) {\n\t\t\t\t\tschemas[schema] = props.body;\n\t\t\t\t} else {\n\t\t\t\t\tskipSchema = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If the schema is external then remove it from the final schemas\n\t\tif (Is.object(externalReferences)) {\n\t\t\tfor (const external in externalReferences) {\n\t\t\t\tconst re = new RegExp(`^I?${external}(?<!Request|Response)$`);\n\t\t\t\tif (re.test(schema)) {\n\t\t\t\t\tskipSchema = true;\n\t\t\t\t\tfinalExternals[StringHelper.stripPrefix(schema)] = schema.replace(\n\t\t\t\t\t\tre,\n\t\t\t\t\t\texternalReferences[external]\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// We can remove any auto expand types from the final schema as they\n\t\t// will have been expanded inline so no need to keep them\n\t\tfor (const autoExpandType of autoExpandTypes) {\n\t\t\tconst regExp = JsonSchemaHelper.stringToRegEx(autoExpandType);\n\t\t\tif (regExp.test(schema)) {\n\t\t\t\tskipSchema = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!skipSchema) {\n\t\t\t// If the final schema has no properties and is just a ref to another object type\n\t\t\t// then replace the references with that of the referenced type\n\t\t\tconst ref = schemas[schema].$ref;\n\t\t\tif (!Is.arrayValue(schemas[schema].properties) && Is.stringValue(ref)) {\n\t\t\t\tsubstituteSchemas.push({ from: schema, to: ref });\n\t\t\t} else {\n\t\t\t\tlet finalName = schema;\n\n\t\t\t\t// If the type has an interface name e.g. ISomething then strip the I\n\t\t\t\tif (/I[A-Z]/.test(finalName)) {\n\t\t\t\t\tfinalName = finalName.slice(1);\n\t\t\t\t}\n\n\t\t\t\tif (finalName.endsWith(\"[]\")) {\n\t\t\t\t\tfinalName = `ListOf${finalName.slice(0, -2)}`;\n\t\t\t\t}\n\n\t\t\t\tfinalSchemas[finalName] = schemas[schema];\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove standard types that we don't want in the final output\n\tconst removeTypes = [\"HttpStatusCode\", \"Uint8Array\", \"ArrayBuffer\"];\n\tfor (const type of removeTypes) {\n\t\tdelete finalSchemas[type];\n\t}\n\n\tfor (const type in finalSchemas) {\n\t\tJsonSchemaHelper.processArrays(finalSchemas[type]);\n\t}\n\n\tconst schemaKeys = Object.keys(finalSchemas);\n\tschemaKeys.sort();\n\n\tconst sortedSchemas: { [id: string]: IJsonSchema } = {};\n\tfor (const key of schemaKeys) {\n\t\tsortedSchemas[key] = finalSchemas[key];\n\t}\n\n\topenApi.components = {\n\t\tschemas: sortedSchemas,\n\t\tsecuritySchemes\n\t};\n\n\tlet json = JSON.stringify(openApi, undefined, \"\\t\");\n\n\t// Remove the reference only schemas, repeating until no more substitutions\n\tlet performedSubstitution;\n\tdo {\n\t\tperformedSubstitution = false;\n\t\tfor (const substituteSchema of substituteSchemas) {\n\t\t\tconst schemaParts = substituteSchema.to.split(\"/\");\n\t\t\tconst find = new RegExp(`#/definitions/${substituteSchema.from}`, \"g\");\n\t\t\tif (find.test(json)) {\n\t\t\t\tjson = json.replace(find, `#/definitions/${schemaParts[schemaParts.length - 1]}`);\n\t\t\t\tperformedSubstitution = true;\n\t\t\t}\n\t\t}\n\t} while (performedSubstitution);\n\n\t// Update the location of the components\n\tjson = json.replace(/#\\/definitions\\//g, \"#/components/schemas/\");\n\n\t// Remove the I from the type names as long as they are interfaces\n\tjson = json.replace(/#\\/components\\/schemas\\/I([A-Z].*)/g, \"#/components/schemas/$1\");\n\n\t// Remove the array [] from the type names\n\t// eslint-disable-next-line unicorn/better-regex\n\tjson = json.replace(/#\\/components\\/schemas\\/(.*)\\[\\]/g, \"#/components/schemas/ListOf$1\");\n\n\tjson = JsonSchemaHelper.normaliseTypeName(json);\n\n\t// Remove external references\n\tfor (const finalExternal in finalExternals) {\n\t\tjson = json.replace(\n\t\t\tnew RegExp(`\"#/components/schemas/${StringHelper.stripPrefix(finalExternal)}\"`, \"g\"),\n\t\t\t`\"${finalExternals[finalExternal]}\"`\n\t\t);\n\t}\n\n\tCLIDisplay.task(\n\t\tI18n.formatMessage(\"commands.ts-to-openapi.progress.writingOutputFile\"),\n\t\toutputFile\n\t);\n\n\ttry {\n\t\tawait mkdir(path.dirname(outputFile), { recursive: true });\n\t} catch {}\n\tawait writeFile(outputFile, `${json}\\n`);\n}\n\n/**\n * Build the security schemas from the config.\n * @param config The configuration.\n * @param securitySchemes The security schemes.\n * @param authSecurity The auth security.\n */\nfunction buildSecurity(\n\tconfig: ITsToOpenApiConfig,\n\tsecuritySchemes: { [name: string]: IOpenApiSecurityScheme },\n\tauthSecurity: { [name: string]: string[] }[]\n): void {\n\tif (Is.arrayValue(config.authMethods)) {\n\t\tfor (const authMethod of config.authMethods) {\n\t\t\tconst security: { [name: string]: string[] } = {};\n\t\t\tif (authMethod === \"basic\") {\n\t\t\t\tsecuritySchemes.basicAuthScheme = {\n\t\t\t\t\ttype: \"http\",\n\t\t\t\t\tscheme: \"basic\"\n\t\t\t\t};\n\t\t\t\tsecurity.basicAuthScheme = [];\n\t\t\t} else if (authMethod === \"jwtBearer\") {\n\t\t\t\tsecuritySchemes.jwtBearerAuthScheme = {\n\t\t\t\t\ttype: \"http\",\n\t\t\t\t\tscheme: \"bearer\",\n\t\t\t\t\tbearerFormat: \"JWT\"\n\t\t\t\t};\n\t\t\t\tsecurity.jwtBearerAuthScheme = [];\n\t\t\t} else if (authMethod === \"jwtCookie\") {\n\t\t\t\tsecuritySchemes.jwtCookieAuthScheme = {\n\t\t\t\t\ttype: \"apiKey\",\n\t\t\t\t\tin: \"cookie\",\n\t\t\t\t\tname: \"auth_token\"\n\t\t\t\t};\n\t\t\t\tsecurity.jwtCookieAuthScheme = [];\n\t\t\t}\n\t\t\tauthSecurity.push(security);\n\t\t}\n\t}\n}\n\n/**\n * Process the REST details for a package.\n * @param baseDir The base directory other locations are relative to.\n * @param prefix The prefix.\n * @param restDetails The package details.\n * @returns The paths and schemas for the input.\n * @internal\n */\nasync function processPackageRestDetails(restRoutes: IRestRoute[]): Promise<IInputPath[]> {\n\tconst paths: IInputPath[] = [];\n\n\tCLIDisplay.task(I18n.formatMessage(\"commands.ts-to-openapi.progress.processingRoutes\"));\n\n\tfor (const route of restRoutes) {\n\t\tCLIDisplay.value(\n\t\t\tI18n.formatMessage(\"commands.ts-to-openapi.labels.route\"),\n\t\t\t`${route.operationId} ${route.method} ${route.path}`,\n\t\t\t1\n\t\t);\n\t\tconst pathParameters: string[] = [];\n\n\t\tconst pathPaths = route.path.split(\"/\");\n\t\tconst finalPathParts = [];\n\t\tfor (const part of pathPaths) {\n\t\t\tif (part.startsWith(\":\")) {\n\t\t\t\tfinalPathParts.push(`{${part.slice(1)}}`);\n\t\t\t\tpathParameters.push(part.slice(1));\n\t\t\t} else {\n\t\t\t\tfinalPathParts.push(part);\n\t\t\t}\n\t\t}\n\n\t\tconst responseType: {\n\t\t\tstatusCode: HttpStatusCode;\n\t\t\ttype: string;\n\t\t\tmimeType?: string;\n\t\t\tdescription?: string;\n\t\t\texamples?: {\n\t\t\t\tid: string;\n\t\t\t\tdescription?: string;\n\t\t\t\tresponse: unknown;\n\t\t\t}[];\n\t\t}[] = [];\n\n\t\t// If there is no response type automatically add a success\n\t\tif (Is.empty(route.responseType)) {\n\t\t\t// But only if we haven't got a response already for different content type\n\t\t\tif (responseType.length === 0) {\n\t\t\t\tresponseType.push({\n\t\t\t\t\ttype: \"OkResponse\",\n\t\t\t\t\tstatusCode: HttpStatusCode.ok\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (Is.array(route.responseType)) {\n\t\t\t// Find the response codes for the response types\n\t\t\tfor (const rt of route.responseType) {\n\t\t\t\tconst responseCode = getHttpStatusCodeFromType(rt.type);\n\t\t\t\tresponseType.push({\n\t\t\t\t\t...rt,\n\t\t\t\t\tmimeType: rt.mimeType,\n\t\t\t\t\tstatusCode: responseCode,\n\t\t\t\t\texamples: rt.examples\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst inputPath: IInputPath = {\n\t\t\tpath: finalPathParts.join(\"/\"),\n\t\t\tmethod: route.method,\n\t\t\tpathParameters,\n\t\t\toperationId: route.operationId,\n\t\t\ttag: route.tag,\n\t\t\tsummary: route.summary,\n\t\t\trequestType: route.requestType?.type,\n\t\t\trequestMimeType: route.requestType?.mimeType,\n\t\t\trequestExamples: route.requestType?.examples,\n\t\t\tresponseType,\n\t\t\tresponseCodes: [\"badRequest\", \"internalServerError\"],\n\t\t\tskipAuth: route.skipAuth ?? false\n\t\t};\n\n\t\tconst handlerSource = route.handler.toString();\n\n\t\tlet match;\n\t\tconst re = /httpstatuscode\\.([_a-z]*)/gi;\n\t\twhile ((match = re.exec(handlerSource)) !== null) {\n\t\t\tinputPath.responseCodes.push(match[1]);\n\t\t}\n\n\t\tpaths.push(inputPath);\n\t}\n\n\tCLIDisplay.break();\n\n\treturn paths;\n}\n\n/**\n * Generate schemas for the models.\n * @param modelDirWildcards The filenames for all the models.\n * @param types The types of the schema objects.\n * @param outputWorkingDir The working directory.\n * @returns Nothing.\n * @internal\n */\nasync function generateSchemas(\n\tmodelDirWildcards: string[],\n\ttypes: string[],\n\tautoExpandTypes: string[],\n\toutputWorkingDir: string\n): Promise<{\n\t[id: string]: IJsonSchema;\n}> {\n\tconst allSchemas: { [id: string]: IJsonSchema } = {};\n\n\tconst arraySingularTypes: string[] = [];\n\tfor (const type of types) {\n\t\tif (type.endsWith(\"[]\")) {\n\t\t\tconst singularType = type.slice(0, -2);\n\t\t\tarraySingularTypes.push(singularType);\n\t\t\tif (!types.includes(singularType)) {\n\t\t\t\ttypes.push(singularType);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const files of modelDirWildcards) {\n\t\tCLIDisplay.value(\n\t\t\tI18n.formatMessage(\"commands.ts-to-openapi.progress.models\"),\n\t\t\tfiles.replace(/\\\\/g, \"/\"),\n\t\t\t1\n\t\t);\n\t\tconst generator = createGenerator({\n\t\t\tpath: files.replace(/\\\\/g, \"/\"),\n\t\t\ttype: \"*\",\n\t\t\ttsconfig: path.join(outputWorkingDir, \"tsconfig.json\"),\n\t\t\tskipTypeCheck: true,\n\t\t\texpose: \"all\"\n\t\t});\n\n\t\tconst schema = generator.createSchema(\"*\");\n\n\t\tif (schema.definitions) {\n\t\t\tfor (const def in schema.definitions) {\n\t\t\t\tconst defSub = JsonSchemaHelper.normaliseTypeName(def);\n\n\t\t\t\tallSchemas[defSub] = schema.definitions[def] as IJsonSchema;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst referencedSchemas: { [id: string]: IJsonSchema } = {};\n\n\tJsonSchemaHelper.extractTypes(allSchemas, [...types, ...autoExpandTypes], referencedSchemas);\n\tJsonSchemaHelper.expandTypes(referencedSchemas, autoExpandTypes);\n\n\tfor (const arraySingularType of arraySingularTypes) {\n\t\treferencedSchemas[`${arraySingularType}[]`] = {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\t$ref: `#/components/schemas/${arraySingularType}`\n\t\t\t}\n\t\t};\n\t}\n\n\treturn referencedSchemas;\n}\n\n/**\n * Tidy up the schemas for use in OpenAPI context.\n * @param props The properties to tidy up.\n * @internal\n */\nfunction tidySchemaProperties(props: { [id: string]: IJsonSchema | boolean }): void {\n\tfor (const prop in props) {\n\t\tconst p = props[prop];\n\t\tif (Is.object<IJsonSchema>(p)) {\n\t\t\t// For OpenAPI we don't include a description for\n\t\t\t// items that have refs\n\t\t\tif (p.$ref) {\n\t\t\t\tdelete p.description;\n\t\t\t}\n\n\t\t\tif (p.properties) {\n\t\t\t\ttidySchemaProperties(p.properties);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tp.items &&\n\t\t\t\tIs.object<IJsonSchema>(p.items) &&\n\t\t\t\tIs.object<IJsonSchema>(p.items.properties)\n\t\t\t) {\n\t\t\t\ttidySchemaProperties(p.items.properties);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Load the packages from config and get the routes and tags from them.\n * @param tsToOpenApiConfig The app config.\n * @param outputWorkingDir The working directory.\n * @param typeRoots The model roots.\n * @returns The routes and tags for each package.\n * @internal\n */\nasync function loadPackages(\n\ttsToOpenApiConfig: ITsToOpenApiConfig,\n\toutputWorkingDir: string,\n\ttypeRoots: string[]\n): Promise<\n\t{\n\t\trestRoutes: IRestRoute[];\n\t\ttags: ITag[];\n\t}[]\n> {\n\tconst restRoutes: {\n\t\trestRoutes: IRestRoute[];\n\t\ttags: ITag[];\n\t}[] = [];\n\n\tlet localNpmRoot = await CLIUtils.findNpmRoot(process.cwd());\n\tlocalNpmRoot = localNpmRoot.replace(/[/\\\\]node_modules/, \"\");\n\n\tconst packages: string[] = [];\n\tconst localPackages: string[] = [];\n\n\tfor (const configRestRoutes of tsToOpenApiConfig.restRoutes) {\n\t\tif (Is.stringValue(configRestRoutes.package)) {\n\t\t\tconst existsLocally = await CLIUtils.dirExists(\n\t\t\t\tpath.join(localNpmRoot, \"node_modules\", configRestRoutes.package)\n\t\t\t);\n\t\t\tif (existsLocally) {\n\t\t\t\tif (!localPackages.includes(configRestRoutes.package)) {\n\t\t\t\t\tlocalPackages.push(configRestRoutes.package);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst version = configRestRoutes.version ?? \"latest\";\n\t\t\t\tconst newPackage = `${configRestRoutes.package}@${version}`;\n\t\t\t\tif (!packages.includes(newPackage)) {\n\t\t\t\t\tpackages.push(`${configRestRoutes.package}@${version}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (packages.length > 0) {\n\t\tCLIDisplay.task(\n\t\t\tI18n.formatMessage(\"commands.ts-to-openapi.progress.installingNpmPackages\"),\n\t\t\tpackages.join(\" \")\n\t\t);\n\t\tawait CLIUtils.runShellCmd(\"npm\", [\"install\", ...packages], outputWorkingDir);\n\t\tCLIDisplay.break();\n\t}\n\n\tfor (const configRestRoutes of tsToOpenApiConfig.restRoutes) {\n\t\tconst typeFolders = [\"models\", \"errors\"];\n\t\tconst packageName = configRestRoutes.package;\n\t\tconst packageRoot = configRestRoutes.packageRoot;\n\t\tif (!Is.stringValue(packageName) && !Is.stringValue(packageRoot)) {\n\t\t\t// eslint-disable-next-line no-restricted-syntax\n\t\t\tthrow new Error(\"Package name or root must be specified\");\n\t\t}\n\n\t\tlet rootFolder;\n\t\tlet npmResolveFolder;\n\t\tif (Is.stringValue(packageName)) {\n\t\t\tif (localPackages.includes(packageName)) {\n\t\t\t\tnpmResolveFolder = localNpmRoot;\n\t\t\t\trootFolder = path.join(localNpmRoot, \"node_modules\", packageName);\n\t\t\t} else {\n\t\t\t\tnpmResolveFolder = outputWorkingDir;\n\t\t\t\trootFolder = path.join(outputWorkingDir, \"node_modules\", packageName);\n\t\t\t}\n\t\t} else {\n\t\t\trootFolder = path.resolve(packageRoot ?? \"\");\n\t\t\tnpmResolveFolder = rootFolder;\n\t\t}\n\n\t\tconst pkgJson = (await CLIUtils.readJsonFile<IPackageJson>(\n\t\t\tpath.join(rootFolder, \"package.json\")\n\t\t)) ?? { name: \"\" };\n\t\tCLIDisplay.task(\n\t\t\tI18n.formatMessage(\"commands.ts-to-openapi.progress.processingPackage\"),\n\t\t\tpkgJson.name\n\t\t);\n\n\t\tfor (const typeFolder of typeFolders) {\n\t\t\tconst typesDir = path.join(rootFolder, \"dist\", \"types\", typeFolder);\n\t\t\tif (await CLIUtils.dirExists(typesDir)) {\n\t\t\t\tconst newRoot = path.join(typesDir, \"**/*.ts\");\n\t\t\t\tif (!typeRoots.includes(newRoot)) {\n\t\t\t\t\ttypeRoots.push(newRoot);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (pkgJson.dependencies) {\n\t\t\tconst nodeModulesFolder = await CLIUtils.findNpmRoot(npmResolveFolder);\n\t\t\tfor (const dep in pkgJson.dependencies) {\n\t\t\t\tif (dep.startsWith(\"@twin.org\")) {\n\t\t\t\t\tfor (const typeFolder of typeFolders) {\n\t\t\t\t\t\tconst typesDirDep = path.join(nodeModulesFolder, dep, \"dist\", \"types\", typeFolder);\n\t\t\t\t\t\tif (await CLIUtils.dirExists(typesDirDep)) {\n\t\t\t\t\t\t\tconst newRoot = path.join(typesDirDep, \"**/*.ts\");\n\t\t\t\t\t\t\tif (!typeRoots.includes(newRoot)) {\n\t\t\t\t\t\t\t\ttypeRoots.push(newRoot);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tCLIDisplay.task(\n\t\t\tI18n.formatMessage(\"commands.ts-to-openapi.progress.importingModule\"),\n\t\t\tpkgJson.name\n\t\t);\n\n\t\tconst pkg = await import(`file://${path.join(rootFolder, \"dist/es/index.js\")}`);\n\n\t\tif (!Is.array(pkg.restEntryPoints)) {\n\t\t\tthrow new GeneralError(\"commands\", \"commands.ts-to-openapi.missingRestRoutesEntryPoints\", {\n\t\t\t\tmethod: \"restEntryPoints\",\n\t\t\t\tpackage: pkgJson.name\n\t\t\t});\n\t\t}\n\n\t\tconst packageEntryPoints: IRestRouteEntryPoint[] = pkg.restEntryPoints;\n\n\t\tconst entryPoints: ITsToOpenApiConfigEntryPoint[] =\n\t\t\tconfigRestRoutes.entryPoints ?? packageEntryPoints.map(e => ({ name: e.name }));\n\n\t\tfor (const entryPoint of entryPoints) {\n\t\t\tconst packageEntryPoint = packageEntryPoints.find(e => e.name === entryPoint.name);\n\n\t\t\tif (!Is.object<IRestRouteEntryPoint>(packageEntryPoint)) {\n\t\t\t\tthrow new GeneralError(\"commands\", \"commands.ts-to-openapi.missingRestRoutesEntryPoint\", {\n\t\t\t\t\tentryPoint: entryPoint.name,\n\t\t\t\t\tpackage: pkgJson.name\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tlet baseRouteName = StringHelper.trimTrailingSlashes(\n\t\t\t\tentryPoint.baseRoutePath ?? packageEntryPoint.defaultBaseRoute ?? \"\"\n\t\t\t);\n\n\t\t\tif (baseRouteName.length > 0) {\n\t\t\t\tbaseRouteName = `/${StringHelper.trimLeadingSlashes(baseRouteName)}`;\n\t\t\t}\n\n\t\t\tlet routes: IRestRoute[] = packageEntryPoint.generateRoutes(baseRouteName, \"dummy-service\");\n\n\t\t\troutes = routes.filter(r => !(r.excludeFromSpec ?? false));\n\n\t\t\tif (Is.stringValue(entryPoint.operationIdDistinguisher)) {\n\t\t\t\tfor (const route of routes) {\n\t\t\t\t\troute.operationId = `${route.operationId}${entryPoint.operationIdDistinguisher}`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trestRoutes.push({\n\t\t\t\trestRoutes: routes,\n\t\t\t\ttags: packageEntryPoint.tags\n\t\t\t});\n\t\t}\n\n\t\tCLIDisplay.break();\n\t}\n\n\treturn restRoutes;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export * from "./cli.js";
4
+ export * from "./commands/tsToOpenApi.js";
5
+ export * from "./models/ITsToOpenApiConfig.js";
6
+ export * from "./models/ITsToOpenApiConfigEntryPoint.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,UAAU,CAAC;AACzB,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0CAA0C,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./cli.js\";\nexport * from \"./commands/tsToOpenApi.js\";\nexport * from \"./models/ITsToOpenApiConfig.js\";\nexport * from \"./models/ITsToOpenApiConfigEntryPoint.js\";\n"]}