serverless-openapi-documenter 0.0.111 → 0.0.113
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/package.json +1 -2
- package/src/definitionGenerator.js +7 -3
- package/src/openAPIGenerator.js +1 -1
- package/src/schemaHandler.js +63 -25
- package/test/unit/definitionGenerator.spec.js +3 -7
- package/test/unit/openAPIGenerator.spec.js +4 -9
- package/test/unit/owasp.spec.js +1 -1
- package/test/unit/schemaHandler.spec.js +856 -633
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "serverless-openapi-documenter",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.113",
|
|
4
4
|
"description": "Generate OpenAPI v3 documentation and Postman Collections from your Serverless Config",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -50,7 +50,6 @@
|
|
|
50
50
|
"chalk": "^4.1.2",
|
|
51
51
|
"js-yaml": "^4.1.0",
|
|
52
52
|
"json-schema-for-openapi": "^0.5.0",
|
|
53
|
-
"lodash.isequal": "^4.5.0",
|
|
54
53
|
"openapi-to-postmanv2": "^5.0.0",
|
|
55
54
|
"uuid": "^11.1.0"
|
|
56
55
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
const isEqual = require("node:util").isDeepStrictEqual;
|
|
3
4
|
const path = require("path");
|
|
4
5
|
|
|
5
6
|
const {
|
|
@@ -8,7 +9,6 @@ const {
|
|
|
8
9
|
stringifyYaml,
|
|
9
10
|
createConfig,
|
|
10
11
|
} = require("@redocly/openapi-core");
|
|
11
|
-
const isEqual = require("lodash.isequal");
|
|
12
12
|
const { v4: uuid } = require("uuid");
|
|
13
13
|
|
|
14
14
|
const SchemaHandler = require("./schemaHandler");
|
|
@@ -39,7 +39,11 @@ class DefinitionGenerator {
|
|
|
39
39
|
},
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
this.schemaHandler = new SchemaHandler(
|
|
42
|
+
this.schemaHandler = new SchemaHandler(
|
|
43
|
+
serverless,
|
|
44
|
+
this.openAPI,
|
|
45
|
+
this.logger
|
|
46
|
+
);
|
|
43
47
|
|
|
44
48
|
this.operationIdMap = {};
|
|
45
49
|
this.functionMap = {};
|
|
@@ -620,7 +624,7 @@ class DefinitionGenerator {
|
|
|
620
624
|
continue;
|
|
621
625
|
}
|
|
622
626
|
|
|
623
|
-
const obj =
|
|
627
|
+
const obj = structuredClone(this.DEFAULT_CORS_HEADERS[key]);
|
|
624
628
|
|
|
625
629
|
if (key === "Access-Control-Allow-Origin") {
|
|
626
630
|
if (
|
package/src/openAPIGenerator.js
CHANGED
package/src/schemaHandler.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
const isEqual = require("node:util").isDeepStrictEqual;
|
|
3
4
|
const path = require("path");
|
|
4
5
|
|
|
5
6
|
const $RefParser = require("@apidevtools/json-schema-ref-parser");
|
|
6
7
|
const SchemaConvertor = require("json-schema-for-openapi");
|
|
7
|
-
const isEqual = require("lodash.isequal");
|
|
8
8
|
const { v4: uuid } = require("uuid");
|
|
9
9
|
|
|
10
10
|
class SchemaHandler {
|
|
11
|
-
constructor(serverless, openAPI) {
|
|
11
|
+
constructor(serverless, openAPI, logger) {
|
|
12
|
+
this.logger = logger;
|
|
13
|
+
|
|
12
14
|
this.apiGatewayModels =
|
|
13
15
|
serverless.service?.provider?.apiGateway?.request?.schemas || {};
|
|
14
16
|
this.documentation = serverless.service.custom.documentation;
|
|
@@ -19,6 +21,12 @@ class SchemaHandler {
|
|
|
19
21
|
this.__standardiseModels();
|
|
20
22
|
|
|
21
23
|
try {
|
|
24
|
+
this.logger.verbose(
|
|
25
|
+
`Trying to resolve Ref-Parser config from: ${path.resolve(
|
|
26
|
+
"options",
|
|
27
|
+
"ref-parser.js"
|
|
28
|
+
)}`
|
|
29
|
+
);
|
|
22
30
|
this.refParserOptions = require(path.resolve("options", "ref-parser.js"));
|
|
23
31
|
} catch (err) {
|
|
24
32
|
this.refParserOptions = {};
|
|
@@ -63,24 +71,15 @@ class SchemaHandler {
|
|
|
63
71
|
const modelName = model.name;
|
|
64
72
|
const modelSchema = model.schema;
|
|
65
73
|
|
|
66
|
-
const
|
|
67
|
-
modelSchema
|
|
74
|
+
const convertedSchemas = await this.__dereferenceAndConvert(
|
|
75
|
+
modelSchema,
|
|
76
|
+
modelName,
|
|
77
|
+
model
|
|
68
78
|
).catch((err) => {
|
|
69
|
-
if (err
|
|
70
|
-
|
|
71
|
-
this.__HTTPError(error, model);
|
|
72
|
-
}
|
|
73
|
-
} else {
|
|
74
|
-
this.__HTTPError(err, model);
|
|
75
|
-
}
|
|
76
|
-
return modelSchema;
|
|
79
|
+
if (err instanceof Error) throw err;
|
|
80
|
+
else return err;
|
|
77
81
|
});
|
|
78
82
|
|
|
79
|
-
const convertedSchemas = SchemaConvertor.convert(
|
|
80
|
-
dereferencedSchema,
|
|
81
|
-
modelName
|
|
82
|
-
);
|
|
83
|
-
|
|
84
83
|
if (
|
|
85
84
|
typeof convertedSchemas.schemas === "object" &&
|
|
86
85
|
!Array.isArray(convertedSchemas.schemas) &&
|
|
@@ -119,13 +118,12 @@ class SchemaHandler {
|
|
|
119
118
|
return this.modelReferences[name];
|
|
120
119
|
}
|
|
121
120
|
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const convertedSchemas = SchemaConvertor.convert(dereferencedSchema, name);
|
|
121
|
+
const convertedSchemas = await this.__dereferenceAndConvert(schema, name, {
|
|
122
|
+
name,
|
|
123
|
+
schema,
|
|
124
|
+
}).catch((err) => {
|
|
125
|
+
throw err;
|
|
126
|
+
});
|
|
129
127
|
|
|
130
128
|
for (const [schemaName, schemaValue] of Object.entries(
|
|
131
129
|
convertedSchemas.schemas
|
|
@@ -147,6 +145,32 @@ class SchemaHandler {
|
|
|
147
145
|
return `#/components/schemas/${finalName}`;
|
|
148
146
|
}
|
|
149
147
|
|
|
148
|
+
async __dereferenceAndConvert(schema, name, model) {
|
|
149
|
+
this.logger.verbose(`dereferencing model: ${name}`);
|
|
150
|
+
const dereferencedSchema = await this.__dereferenceSchema(schema).catch(
|
|
151
|
+
(err) => {
|
|
152
|
+
this.__checkForHTTPErrorsAndThrow(err, model);
|
|
153
|
+
|
|
154
|
+
this.__checkForMissingPathAndThrow(err);
|
|
155
|
+
|
|
156
|
+
return schema;
|
|
157
|
+
}
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
this.logger.verbose(
|
|
161
|
+
`dereferenced model: ${JSON.stringify(dereferencedSchema)}`
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
this.logger.verbose(`converting model: ${name}`);
|
|
165
|
+
const convertedSchemas = SchemaConvertor.convert(dereferencedSchema, name);
|
|
166
|
+
|
|
167
|
+
this.logger.verbose(
|
|
168
|
+
`converted schemas: ${JSON.stringify(convertedSchemas)}`
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
return convertedSchemas;
|
|
172
|
+
}
|
|
173
|
+
|
|
150
174
|
async __dereferenceSchema(schema) {
|
|
151
175
|
const bundledSchema = await $RefParser
|
|
152
176
|
.bundle(schema, this.refParserOptions)
|
|
@@ -228,9 +252,23 @@ class SchemaHandler {
|
|
|
228
252
|
}
|
|
229
253
|
}
|
|
230
254
|
|
|
255
|
+
__checkForMissingPathAndThrow(error) {
|
|
256
|
+
if (error.message === "Expected a file path, URL, or object. Got undefined")
|
|
257
|
+
throw error;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
__checkForHTTPErrorsAndThrow(error, model) {
|
|
261
|
+
if (error.errors) {
|
|
262
|
+
for (const err of error?.errors) {
|
|
263
|
+
this.__HTTPError(err, model);
|
|
264
|
+
}
|
|
265
|
+
} else {
|
|
266
|
+
this.__HTTPError(error, model);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
231
270
|
__HTTPError(error, model) {
|
|
232
271
|
if (error.message.includes("HTTP ERROR")) {
|
|
233
|
-
// throw err;
|
|
234
272
|
throw new Error(
|
|
235
273
|
`There was an error dereferencing ${
|
|
236
274
|
model.name
|
|
@@ -23,7 +23,7 @@ describe("DefinitionGenerator", () => {
|
|
|
23
23
|
);
|
|
24
24
|
|
|
25
25
|
beforeEach(function () {
|
|
26
|
-
mockServerless =
|
|
26
|
+
mockServerless = structuredClone(serverlessMock);
|
|
27
27
|
Object.assign(mockServerless.service.custom.documentation, modelsDocument);
|
|
28
28
|
});
|
|
29
29
|
|
|
@@ -39,9 +39,7 @@ describe("DefinitionGenerator", () => {
|
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
it("should default to version 3.0.0 of openAPI when openAPI version is not passed in", function () {
|
|
42
|
-
const serverlessWithoutOpenAPIVersion =
|
|
43
|
-
JSON.stringify(mockServerless)
|
|
44
|
-
);
|
|
42
|
+
const serverlessWithoutOpenAPIVersion = structuredClone(mockServerless);
|
|
45
43
|
delete serverlessWithoutOpenAPIVersion.processedInput;
|
|
46
44
|
let expected = new DefinitionGenerator(
|
|
47
45
|
serverlessWithoutOpenAPIVersion,
|
|
@@ -108,9 +106,7 @@ describe("DefinitionGenerator", () => {
|
|
|
108
106
|
});
|
|
109
107
|
|
|
110
108
|
it("should respect the version of openAPI when passed in", function () {
|
|
111
|
-
const serverlessWithOpenAPIVersion =
|
|
112
|
-
JSON.stringify(mockServerless)
|
|
113
|
-
);
|
|
109
|
+
const serverlessWithOpenAPIVersion = structuredClone(mockServerless);
|
|
114
110
|
serverlessWithOpenAPIVersion.processedInput.options.openApiVersion =
|
|
115
111
|
"3.0.2";
|
|
116
112
|
let expected = new DefinitionGenerator(
|
|
@@ -57,6 +57,7 @@ describe("OpenAPIGenerator", () => {
|
|
|
57
57
|
notice: (str) => {},
|
|
58
58
|
error: (str) => {},
|
|
59
59
|
success: (str) => {},
|
|
60
|
+
verbose: (str) => {},
|
|
60
61
|
},
|
|
61
62
|
};
|
|
62
63
|
});
|
|
@@ -106,9 +107,7 @@ describe("OpenAPIGenerator", () => {
|
|
|
106
107
|
const getAllFuncsStub = sinon
|
|
107
108
|
.stub(sls.service, "getAllFunctions")
|
|
108
109
|
.returns(["createUser"]);
|
|
109
|
-
const basicInvalidFunction =
|
|
110
|
-
JSON.stringify(basicValidFunction)
|
|
111
|
-
);
|
|
110
|
+
const basicInvalidFunction = structuredClone(basicValidFunction);
|
|
112
111
|
|
|
113
112
|
delete basicInvalidFunction.createUser.events[0].http.documentation
|
|
114
113
|
.methodResponses[0].responseModels;
|
|
@@ -144,9 +143,7 @@ describe("OpenAPIGenerator", () => {
|
|
|
144
143
|
const getAllFuncsStub = sinon
|
|
145
144
|
.stub(sls.service, "getAllFunctions")
|
|
146
145
|
.returns(["createUser"]);
|
|
147
|
-
const basicInvalidFunction =
|
|
148
|
-
JSON.stringify(basicValidFunction)
|
|
149
|
-
);
|
|
146
|
+
const basicInvalidFunction = structuredClone(basicValidFunction);
|
|
150
147
|
|
|
151
148
|
const getFuncStub = sinon
|
|
152
149
|
.stub(sls.service, "getFunction")
|
|
@@ -181,9 +178,7 @@ describe("OpenAPIGenerator", () => {
|
|
|
181
178
|
.stub(sls.service, "getAllFunctions")
|
|
182
179
|
.returns(["createUser"]);
|
|
183
180
|
|
|
184
|
-
const basicInvalidFunction =
|
|
185
|
-
JSON.stringify(basicValidFunction)
|
|
186
|
-
);
|
|
181
|
+
const basicInvalidFunction = structuredClone(basicValidFunction);
|
|
187
182
|
|
|
188
183
|
delete basicInvalidFunction.createUser.events[0].http.documentation
|
|
189
184
|
.pathParams;
|
package/test/unit/owasp.spec.js
CHANGED
|
@@ -56,7 +56,7 @@ describe(`owasp`, function () {
|
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
it(`adds any properties contained in a new release`, async function () {
|
|
59
|
-
const newOWASPJSONAdded =
|
|
59
|
+
const newOWASPJSONAdded = structuredClone(newOWASPJSON);
|
|
60
60
|
newOWASPJSONAdded.headers.push({ name: "x-added", value: "true" });
|
|
61
61
|
|
|
62
62
|
nock("https://owasp.org")
|