vls-openapi-generator 1.12.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generate-openapi.js +13 -83
- package/package.json +1 -2
- package/src/generate-openapi.ts +11 -107
package/dist/generate-openapi.js
CHANGED
|
@@ -35,44 +35,26 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.generateOpenAPI = void 0;
|
|
37
37
|
const zod_openapi_1 = require("@anatine/zod-openapi");
|
|
38
|
-
const
|
|
39
|
-
const
|
|
38
|
+
const node_child_process_1 = require("node:child_process");
|
|
39
|
+
const node_fs_1 = require("node:fs");
|
|
40
40
|
require("module-alias/register.js");
|
|
41
|
-
const path = __importStar(require("path"));
|
|
42
|
-
const
|
|
41
|
+
const path = __importStar(require("node:path"));
|
|
42
|
+
const node_util_1 = require("node:util");
|
|
43
43
|
const zod_1 = require("zod");
|
|
44
|
-
const client_cloudformation_1 = require("@aws-sdk/client-cloudformation");
|
|
45
44
|
const OPENAPI_FILE = path.join(process.cwd(), 'openapi.json');
|
|
46
45
|
const HANDLERS_DIR = path.join(process.cwd(), 'dist', 'src', 'handlers');
|
|
47
46
|
const SCHEMAS_DIR = path.join(process.cwd(), 'dist', 'src', 'schemas');
|
|
48
47
|
const OUTPUT_FILE = path.join(process.cwd(), 'openapi.json');
|
|
49
48
|
const generateOpenAPI = async () => {
|
|
50
|
-
await (0,
|
|
51
|
-
await (0,
|
|
52
|
-
const handlerFiles = await
|
|
49
|
+
await (0, node_util_1.promisify)(node_child_process_1.exec)('rm -rf ./dist');
|
|
50
|
+
await (0, node_util_1.promisify)(node_child_process_1.exec)('npx tsc');
|
|
51
|
+
const handlerFiles = await node_fs_1.promises.readdir(HANDLERS_DIR).catch(() => []);
|
|
53
52
|
if (handlerFiles.length === 0) {
|
|
54
53
|
console.log('No handler found in handlers folder.');
|
|
55
54
|
return;
|
|
56
55
|
}
|
|
57
56
|
console.info('Generating Open API documentation...');
|
|
58
|
-
const
|
|
59
|
-
const params = {};
|
|
60
|
-
for (let i = 2; i < args.length;) {
|
|
61
|
-
const key = args[i].replace('--', '');
|
|
62
|
-
params[key] = args[i + 1];
|
|
63
|
-
if (!params[key]) {
|
|
64
|
-
i++;
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
if (params[key].startsWith('--')) {
|
|
68
|
-
i++;
|
|
69
|
-
delete params[key];
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
i += 2;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const existingOpenAPIFile = JSON.parse(await fs_1.promises.readFile(OPENAPI_FILE, 'utf-8'));
|
|
57
|
+
const existingOpenAPIFile = JSON.parse(await node_fs_1.promises.readFile(OPENAPI_FILE, 'utf-8'));
|
|
76
58
|
existingOpenAPIFile.paths = {};
|
|
77
59
|
for (const handler of handlerFiles) {
|
|
78
60
|
const fileName = path.parse(handler).name;
|
|
@@ -80,6 +62,9 @@ const generateOpenAPI = async () => {
|
|
|
80
62
|
continue;
|
|
81
63
|
}
|
|
82
64
|
const { bodySchema, queryParametersSchema, eventResponseParametersSchema, eventResponseModulesSchema, OPENAPI_CONFIG: openAPIConfig } = (await Promise.resolve(`${path.join(SCHEMAS_DIR, fileName + '.js')}`).then(s => __importStar(require(s))).catch(() => ({})));
|
|
65
|
+
if (!openAPIConfig) {
|
|
66
|
+
throw new Error(`${fileName} handler schema not found.`);
|
|
67
|
+
}
|
|
83
68
|
if (openAPIConfig.isDocumentationNeeded === false) {
|
|
84
69
|
continue;
|
|
85
70
|
}
|
|
@@ -91,7 +76,7 @@ const generateOpenAPI = async () => {
|
|
|
91
76
|
if (queryParametersSchema) {
|
|
92
77
|
for (const key in queryParametersComponent.properties) {
|
|
93
78
|
const properties = queryParametersComponent?.properties;
|
|
94
|
-
if (!properties
|
|
79
|
+
if (!properties?.[key]) {
|
|
95
80
|
continue;
|
|
96
81
|
}
|
|
97
82
|
queryParameters.push({
|
|
@@ -128,65 +113,10 @@ const generateOpenAPI = async () => {
|
|
|
128
113
|
}
|
|
129
114
|
};
|
|
130
115
|
}
|
|
131
|
-
|
|
132
|
-
if (partnerName) {
|
|
133
|
-
const developmentURLIndex = existingOpenAPIFile.servers.findIndex((x) => x.url.includes('development'));
|
|
134
|
-
const fetchedDevelopmentURL = await getStackURL(partnerName, 'development');
|
|
135
|
-
if (fetchedDevelopmentURL) {
|
|
136
|
-
existingOpenAPIFile.servers[developmentURLIndex].url =
|
|
137
|
-
fetchedDevelopmentURL[fetchedDevelopmentURL.length - 1] === '/'
|
|
138
|
-
? fetchedDevelopmentURL.slice(0, -1)
|
|
139
|
-
: fetchedDevelopmentURL;
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
existingOpenAPIFile.servers[developmentURLIndex].url = 'development url';
|
|
143
|
-
}
|
|
144
|
-
const productionURLIndex = existingOpenAPIFile.servers.findIndex((x) => x.url.includes('production'));
|
|
145
|
-
const fetchedProductionURL = await getStackURL(partnerName, 'production');
|
|
146
|
-
if (fetchedProductionURL) {
|
|
147
|
-
existingOpenAPIFile.servers[productionURLIndex].url =
|
|
148
|
-
fetchedProductionURL[fetchedProductionURL.length - 1] === '/'
|
|
149
|
-
? fetchedProductionURL.slice(0, -1)
|
|
150
|
-
: fetchedProductionURL;
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
existingOpenAPIFile.servers[productionURLIndex].url = 'production url';
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
await fs_1.promises.writeFile(OUTPUT_FILE, JSON.stringify(existingOpenAPIFile, undefined, 4));
|
|
116
|
+
await node_fs_1.promises.writeFile(OUTPUT_FILE, JSON.stringify(existingOpenAPIFile, undefined, 4));
|
|
157
117
|
console.info('Open API documentation generated successfully');
|
|
158
118
|
};
|
|
159
119
|
exports.generateOpenAPI = generateOpenAPI;
|
|
160
|
-
async function getStackURL(partnerName, environment) {
|
|
161
|
-
const stackName = `${partnerName}-${environment}`;
|
|
162
|
-
const cloudFormationClient = new client_cloudformation_1.CloudFormationClient();
|
|
163
|
-
const describeStacksCommand = new client_cloudformation_1.DescribeStacksCommand({
|
|
164
|
-
StackName: stackName
|
|
165
|
-
});
|
|
166
|
-
const result = await cloudFormationClient.send(describeStacksCommand).catch((err) => {
|
|
167
|
-
if (err instanceof client_cloudformation_1.CloudFormationServiceException &&
|
|
168
|
-
err.message.includes(`Stack with id ${stackName} does not exist`)) {
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
throw err;
|
|
172
|
-
});
|
|
173
|
-
if (!result || !result.Stacks) {
|
|
174
|
-
console.warn(`Base URL was not found with the given environment. Environment will not be updated. Given environment: ${environment}`);
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
for (const cloudFormationStack of result.Stacks) {
|
|
178
|
-
if (!cloudFormationStack.Outputs) {
|
|
179
|
-
console.warn(`Output was not found within the given stack. Environment will not be updated. Given environment: ${environment}`);
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
for (const output of cloudFormationStack.Outputs) {
|
|
183
|
-
if (output.OutputKey !== 'WebEndpoint' || !output.OutputValue) {
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
186
|
-
return output.OutputValue;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
120
|
function generateEventResponseComponent(responseType = 'mindbehind-chat-bot-response', eventResponseParametersSchema, eventResponseModulesSchema) {
|
|
191
121
|
if (responseType === 'mindbehind-chat-bot-response') {
|
|
192
122
|
return (0, zod_openapi_1.generateSchema)(zod_1.z.object({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vls-openapi-generator",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"scripts": {
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
"description": "VLS Open API Generator",
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@anatine/zod-openapi": "^2.2.7",
|
|
19
|
-
"@aws-sdk/client-cloudformation": "^3.817.0",
|
|
20
19
|
"axios": "^1.12.0",
|
|
21
20
|
"module-alias": "^2.2.3",
|
|
22
21
|
"openapi-to-postmanv2": "^4.25.0"
|
package/src/generate-openapi.ts
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { extendApi, generateSchema, OpenApiZodAny } from '@anatine/zod-openapi';
|
|
2
|
-
import { exec } from 'child_process';
|
|
3
|
-
import { promises as fs } from 'fs';
|
|
2
|
+
import { exec } from 'node:child_process';
|
|
3
|
+
import { promises as fs } from 'node:fs';
|
|
4
4
|
import 'module-alias/register.js';
|
|
5
|
-
import * as path from 'path';
|
|
6
|
-
import { promisify } from 'util';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
import { promisify } from 'node:util';
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
import { LambdaConfig, OpenAPIConfig } from './lambda-type';
|
|
9
9
|
import { OpenAPI } from './openapi-type';
|
|
10
|
-
import {
|
|
11
|
-
CloudFormationClient,
|
|
12
|
-
CloudFormationServiceException,
|
|
13
|
-
DescribeStacksCommand
|
|
14
|
-
} from '@aws-sdk/client-cloudformation';
|
|
15
10
|
|
|
16
11
|
const OPENAPI_FILE = path.join(process.cwd(), 'openapi.json');
|
|
17
12
|
const HANDLERS_DIR = path.join(process.cwd(), 'dist', 'src', 'handlers');
|
|
@@ -32,26 +27,6 @@ export const generateOpenAPI = async (): Promise<void> => {
|
|
|
32
27
|
|
|
33
28
|
console.info('Generating Open API documentation...');
|
|
34
29
|
|
|
35
|
-
const args = process.argv;
|
|
36
|
-
const params: Record<string, string> = {};
|
|
37
|
-
|
|
38
|
-
for (let i = 2; i < args.length; ) {
|
|
39
|
-
const key = args[i].replace('--', '');
|
|
40
|
-
params[key] = args[i + 1];
|
|
41
|
-
|
|
42
|
-
if (!params[key]) {
|
|
43
|
-
i++;
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (params[key].startsWith('--')) {
|
|
48
|
-
i++;
|
|
49
|
-
delete params[key];
|
|
50
|
-
} else {
|
|
51
|
-
i += 2;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
30
|
const existingOpenAPIFile = JSON.parse(await fs.readFile(OPENAPI_FILE, 'utf-8')) as OpenAPI;
|
|
56
31
|
|
|
57
32
|
existingOpenAPIFile.paths = {};
|
|
@@ -77,6 +52,10 @@ export const generateOpenAPI = async (): Promise<void> => {
|
|
|
77
52
|
OPENAPI_CONFIG: OpenAPIConfig;
|
|
78
53
|
};
|
|
79
54
|
|
|
55
|
+
if (!openAPIConfig) {
|
|
56
|
+
throw new Error(`${fileName} handler schema not found.`);
|
|
57
|
+
}
|
|
58
|
+
|
|
80
59
|
if (openAPIConfig.isDocumentationNeeded === false) {
|
|
81
60
|
continue;
|
|
82
61
|
}
|
|
@@ -99,14 +78,14 @@ export const generateOpenAPI = async (): Promise<void> => {
|
|
|
99
78
|
for (const key in queryParametersComponent.properties) {
|
|
100
79
|
const properties = queryParametersComponent?.properties;
|
|
101
80
|
|
|
102
|
-
if (!properties
|
|
81
|
+
if (!properties?.[key]) {
|
|
103
82
|
continue;
|
|
104
83
|
}
|
|
105
84
|
|
|
106
85
|
queryParameters.push({
|
|
107
86
|
name: key,
|
|
108
87
|
in: 'query',
|
|
109
|
-
schema: properties[key]
|
|
88
|
+
schema: properties[key]
|
|
110
89
|
} as const);
|
|
111
90
|
}
|
|
112
91
|
}
|
|
@@ -139,86 +118,11 @@ export const generateOpenAPI = async (): Promise<void> => {
|
|
|
139
118
|
};
|
|
140
119
|
}
|
|
141
120
|
|
|
142
|
-
const partnerName = params['partner-name'];
|
|
143
|
-
|
|
144
|
-
if (partnerName) {
|
|
145
|
-
const developmentURLIndex = existingOpenAPIFile.servers.findIndex((x) => x.url.includes('development'));
|
|
146
|
-
|
|
147
|
-
const fetchedDevelopmentURL = await getStackURL(partnerName, 'development');
|
|
148
|
-
|
|
149
|
-
if (fetchedDevelopmentURL) {
|
|
150
|
-
existingOpenAPIFile.servers[developmentURLIndex].url =
|
|
151
|
-
fetchedDevelopmentURL[fetchedDevelopmentURL.length - 1] === '/'
|
|
152
|
-
? fetchedDevelopmentURL.slice(0, -1)
|
|
153
|
-
: fetchedDevelopmentURL;
|
|
154
|
-
} else {
|
|
155
|
-
existingOpenAPIFile.servers[developmentURLIndex].url = 'development url';
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const productionURLIndex = existingOpenAPIFile.servers.findIndex((x) => x.url.includes('production'));
|
|
159
|
-
|
|
160
|
-
const fetchedProductionURL = await getStackURL(partnerName, 'production');
|
|
161
|
-
|
|
162
|
-
if (fetchedProductionURL) {
|
|
163
|
-
existingOpenAPIFile.servers[productionURLIndex].url =
|
|
164
|
-
fetchedProductionURL[fetchedProductionURL.length - 1] === '/'
|
|
165
|
-
? fetchedProductionURL.slice(0, -1)
|
|
166
|
-
: fetchedProductionURL;
|
|
167
|
-
} else {
|
|
168
|
-
existingOpenAPIFile.servers[productionURLIndex].url = 'production url';
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
121
|
await fs.writeFile(OUTPUT_FILE, JSON.stringify(existingOpenAPIFile, undefined, 4));
|
|
122
|
+
|
|
173
123
|
console.info('Open API documentation generated successfully');
|
|
174
124
|
};
|
|
175
125
|
|
|
176
|
-
async function getStackURL(partnerName: string, environment: 'development' | 'production') {
|
|
177
|
-
const stackName = `${partnerName}-${environment}`;
|
|
178
|
-
const cloudFormationClient = new CloudFormationClient();
|
|
179
|
-
|
|
180
|
-
const describeStacksCommand = new DescribeStacksCommand({
|
|
181
|
-
StackName: stackName
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
const result = await cloudFormationClient.send(describeStacksCommand).catch((err) => {
|
|
185
|
-
if (
|
|
186
|
-
err instanceof CloudFormationServiceException &&
|
|
187
|
-
err.message.includes(`Stack with id ${stackName} does not exist`)
|
|
188
|
-
) {
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
throw err;
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
if (!result || !result.Stacks) {
|
|
196
|
-
console.warn(
|
|
197
|
-
`Base URL was not found with the given environment. Environment will not be updated. Given environment: ${environment}`
|
|
198
|
-
);
|
|
199
|
-
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
for (const cloudFormationStack of result.Stacks) {
|
|
204
|
-
if (!cloudFormationStack.Outputs) {
|
|
205
|
-
console.warn(
|
|
206
|
-
`Output was not found within the given stack. Environment will not be updated. Given environment: ${environment}`
|
|
207
|
-
);
|
|
208
|
-
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
for (const output of cloudFormationStack.Outputs) {
|
|
213
|
-
if (output.OutputKey !== 'WebEndpoint' || !output.OutputValue) {
|
|
214
|
-
continue;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
return output.OutputValue;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
126
|
function generateEventResponseComponent(
|
|
223
127
|
responseType: OpenAPIConfig['responseType'] = 'mindbehind-chat-bot-response',
|
|
224
128
|
eventResponseParametersSchema?: OpenApiZodAny,
|