@twin.org/ts-to-openapi 0.0.2-next.9 → 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.
- package/bin/index.js +1 -1
- package/dist/es/cli.js +37 -0
- package/dist/es/cli.js.map +1 -0
- package/dist/es/commands/httpStatusCodeMap.js +115 -0
- package/dist/es/commands/httpStatusCodeMap.js.map +1 -0
- package/dist/{esm/index.mjs → es/commands/tsToOpenApi.js} +28 -170
- package/dist/es/commands/tsToOpenApi.js.map +1 -0
- package/dist/es/index.js +7 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/models/IInputPath.js +2 -0
- package/dist/es/models/IInputPath.js.map +1 -0
- package/dist/es/models/IInputResult.js +2 -0
- package/dist/es/models/IInputResult.js.map +1 -0
- package/dist/es/models/IRestRoute.js +2 -0
- package/dist/es/models/IRestRoute.js.map +1 -0
- package/dist/es/models/IRestRouteEntryPoints.js +2 -0
- package/dist/es/models/IRestRouteEntryPoints.js.map +1 -0
- package/dist/es/models/ITag.js +4 -0
- package/dist/es/models/ITag.js.map +1 -0
- package/dist/es/models/ITsToOpenApiConfig.js +2 -0
- package/dist/es/models/ITsToOpenApiConfig.js.map +1 -0
- package/dist/es/models/ITsToOpenApiConfigEntryPoint.js +4 -0
- package/dist/es/models/ITsToOpenApiConfigEntryPoint.js.map +1 -0
- package/dist/locales/en.json +46 -73
- package/dist/types/commands/tsToOpenApi.d.ts +1 -1
- package/dist/types/index.d.ts +4 -4
- package/dist/types/models/IInputResult.d.ts +11 -3
- package/dist/types/models/IRestRoute.d.ts +98 -0
- package/dist/types/models/IRestRouteEntryPoints.d.ts +23 -0
- package/dist/types/models/ITag.d.ts +13 -0
- package/dist/types/models/ITsToOpenApiConfig.d.ts +1 -1
- package/docs/changelog.md +50 -0
- package/docs/examples.md +1 -1
- package/locales/.validate-ignore +1 -0
- package/package.json +20 -11
- package/dist/cjs/index.cjs +0 -1084
package/bin/index.js
CHANGED
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: "
|
|
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 === "
|
|
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]) {
|
|
@@ -435,13 +328,12 @@ async function tsToOpenApi(config, outputFile, workingDirectory) {
|
|
|
435
328
|
if (requestObject?.properties) {
|
|
436
329
|
// If there are any properties other than body, query, pathParams and headers
|
|
437
330
|
// we should throw an error as we don't know what to do with them
|
|
438
|
-
const otherKeys = Object.keys(requestObject.properties).filter(k => !["body", "query", "pathParams", "headers"
|
|
331
|
+
const otherKeys = Object.keys(requestObject.properties).filter(k => !["body", "query", "pathParams", "headers"].includes(k));
|
|
439
332
|
if (otherKeys.length > 0) {
|
|
440
333
|
throw new GeneralError("commands", "commands.ts-to-openapi.unsupportedProperties", {
|
|
441
334
|
keys: otherKeys.join(", ")
|
|
442
335
|
});
|
|
443
336
|
}
|
|
444
|
-
delete requestObject.properties.authentication;
|
|
445
337
|
// If there is a path params object convert these to params
|
|
446
338
|
if (Is.object(requestObject.properties.pathParams)) {
|
|
447
339
|
for (const pathParam of pathQueryHeaderParams) {
|
|
@@ -799,7 +691,7 @@ async function processPackageRestDetails(restRoutes) {
|
|
|
799
691
|
// But only if we haven't got a response already for different content type
|
|
800
692
|
if (responseType.length === 0) {
|
|
801
693
|
responseType.push({
|
|
802
|
-
type: "
|
|
694
|
+
type: "OkResponse",
|
|
803
695
|
statusCode: HttpStatusCode.ok
|
|
804
696
|
});
|
|
805
697
|
}
|
|
@@ -1004,7 +896,7 @@ async function loadPackages(tsToOpenApiConfig, outputWorkingDir, typeRoots) {
|
|
|
1004
896
|
}
|
|
1005
897
|
}
|
|
1006
898
|
CLIDisplay.task(I18n.formatMessage("commands.ts-to-openapi.progress.importingModule"), pkgJson.name);
|
|
1007
|
-
const pkg = await import(`file://${path.join(rootFolder, "dist/
|
|
899
|
+
const pkg = await import(`file://${path.join(rootFolder, "dist/es/index.js")}`);
|
|
1008
900
|
if (!Is.array(pkg.restEntryPoints)) {
|
|
1009
901
|
throw new GeneralError("commands", "commands.ts-to-openapi.missingRestRoutesEntryPoints", {
|
|
1010
902
|
method: "restEntryPoints",
|
|
@@ -1041,38 +933,4 @@ async function loadPackages(tsToOpenApiConfig, outputWorkingDir, typeRoots) {
|
|
|
1041
933
|
}
|
|
1042
934
|
return restRoutes;
|
|
1043
935
|
}
|
|
1044
|
-
|
|
1045
|
-
// Copyright 2024 IOTA Stiftung.
|
|
1046
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
1047
|
-
/**
|
|
1048
|
-
* The main entry point for the CLI.
|
|
1049
|
-
*/
|
|
1050
|
-
class CLI extends CLIBase {
|
|
1051
|
-
/**
|
|
1052
|
-
* Run the app.
|
|
1053
|
-
* @param argv The process arguments.
|
|
1054
|
-
* @param localesDirectory The directory for the locales, default to relative to the script.
|
|
1055
|
-
* @param options Additional options.
|
|
1056
|
-
* @param options.overrideOutputWidth Override the output width.
|
|
1057
|
-
* @returns The exit code.
|
|
1058
|
-
*/
|
|
1059
|
-
async run(argv, localesDirectory, options) {
|
|
1060
|
-
return this.execute({
|
|
1061
|
-
title: "TWIN TypeScript To OpenAPI",
|
|
1062
|
-
appName: "ts-to-openapi",
|
|
1063
|
-
version: "0.0.2-next.9", // x-release-please-version
|
|
1064
|
-
icon: "⚙️ ",
|
|
1065
|
-
supportsEnvFiles: false,
|
|
1066
|
-
overrideOutputWidth: options?.overrideOutputWidth
|
|
1067
|
-
}, localesDirectory ?? path.join(path.dirname(fileURLToPath(import.meta.url)), "../locales"), argv);
|
|
1068
|
-
}
|
|
1069
|
-
/**
|
|
1070
|
-
* Configure any options or actions at the root program level.
|
|
1071
|
-
* @param program The root program command.
|
|
1072
|
-
*/
|
|
1073
|
-
configureRoot(program) {
|
|
1074
|
-
buildCommandTsToOpenApi(program);
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
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"]}
|