serverless-openapi-documenter 0.0.118 → 0.0.120-beta.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/README.md
CHANGED
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
</a>
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
|
-
This will generate an OpenAPI V3 (up to v3.0.4) file for you from your serverless file. It can optionally generate a [Postman Collection V2](https://github.com/postmanlabs/openapi-to-postman) from the OpenAPI file for you too. This currently works for `http` and `httpApi` configurations.
|
|
15
|
+
This will generate an [OpenAPI V3](https://spec.openapis.org/oas/v3.0.0.html) (up to v3.0.4) specification file for you from your serverless file. It can optionally generate a [Postman Collection V2](https://github.com/postmanlabs/openapi-to-postman) from the OpenAPI file for you too. This currently works for `http` and `httpApi` configurations.
|
|
16
|
+
|
|
17
|
+
If you are using the beta of 0.0.115, it will now try and create [OpenAPI V3.1 (3.1.x)](https://spec.openapis.org/oas/v3.1.0.html) specification file for you, should you run the command `serverless openapi generate -o openapi.json -f json -a 3.1.1 -p postman.json`. Please see this [guide on migrating to V3.1](https://www.openapis.org/blog/2021/02/16/migrating-from-openapi-3-0-to-3-1-0). Whilst I perosnally use this plugin all the time, please do open and report bugs, and I will do my best to fix them.
|
|
16
18
|
|
|
17
19
|
Originally based off of: https://github.com/temando/serverless-openapi-documentation
|
|
18
20
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "serverless-openapi-documenter",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.120-beta.1",
|
|
4
4
|
"description": "Generate OpenAPI v3 documentation and Postman Collections from your Serverless Config",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -46,11 +46,11 @@
|
|
|
46
46
|
"license": "MIT",
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@apidevtools/json-schema-ref-parser": "^9.1.0",
|
|
49
|
-
"@redocly/openapi-core": "^1.
|
|
49
|
+
"@redocly/openapi-core": "^1.34.5",
|
|
50
50
|
"chalk": "^4.1.2",
|
|
51
51
|
"js-yaml": "^4.1.1",
|
|
52
52
|
"json-schema-for-openapi": "^0.5.0",
|
|
53
|
-
"openapi-to-postmanv2": "^5.
|
|
53
|
+
"openapi-to-postmanv2": "^5.6.0",
|
|
54
54
|
"uuid": "^11.1.0"
|
|
55
55
|
},
|
|
56
56
|
"engines": {
|
package/src/schemaHandler.js
CHANGED
|
@@ -16,6 +16,12 @@ class SchemaHandler {
|
|
|
16
16
|
this.documentation = serverless.service.custom.documentation;
|
|
17
17
|
this.openAPI = openAPI;
|
|
18
18
|
|
|
19
|
+
this.shouldConvert = true;
|
|
20
|
+
if (/(3\.1\.\d)/g.test(this.openAPI.openapi)) this.shouldConvert = false;
|
|
21
|
+
|
|
22
|
+
this.logger.verbose(`OpenAPI version: ${this.openAPI.openapi}`);
|
|
23
|
+
this.logger.verbose(`Convert Schemas: ${this.shouldConvert}`);
|
|
24
|
+
|
|
19
25
|
this.modelReferences = {};
|
|
20
26
|
|
|
21
27
|
this.__standardiseModels();
|
|
@@ -157,18 +163,30 @@ class SchemaHandler {
|
|
|
157
163
|
}
|
|
158
164
|
);
|
|
159
165
|
|
|
160
|
-
this.
|
|
161
|
-
|
|
162
|
-
|
|
166
|
+
if (this.shouldConvert) {
|
|
167
|
+
this.logger.verbose(
|
|
168
|
+
`dereferenced model: ${JSON.stringify(dereferencedSchema)}`
|
|
169
|
+
);
|
|
163
170
|
|
|
164
|
-
|
|
165
|
-
|
|
171
|
+
this.logger.verbose(`converting model: ${name}`);
|
|
172
|
+
const convertedSchemas = SchemaConvertor.convert(
|
|
173
|
+
dereferencedSchema,
|
|
174
|
+
name
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
this.logger.verbose(
|
|
178
|
+
`converted schemas: ${JSON.stringify(convertedSchemas)}`
|
|
179
|
+
);
|
|
180
|
+
return convertedSchemas;
|
|
181
|
+
}
|
|
166
182
|
|
|
167
183
|
this.logger.verbose(
|
|
168
|
-
`
|
|
184
|
+
`dereferenced model: ${JSON.stringify({
|
|
185
|
+
schemas: { [name]: dereferencedSchema },
|
|
186
|
+
})}`
|
|
169
187
|
);
|
|
170
188
|
|
|
171
|
-
return
|
|
189
|
+
return { schemas: { [name]: dereferencedSchema } };
|
|
172
190
|
}
|
|
173
191
|
|
|
174
192
|
async __dereferenceSchema(schema) {
|
|
@@ -38,7 +38,7 @@ describe("DefinitionGenerator", () => {
|
|
|
38
38
|
expect(expected).to.be.an.instanceOf(DefinitionGenerator);
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
it("should default to version 3.0.0 of
|
|
41
|
+
it("should default to version 3.0.0 of OpenAPI when OpenAPI version is not passed in", function () {
|
|
42
42
|
const serverlessWithoutOpenAPIVersion = structuredClone(mockServerless);
|
|
43
43
|
delete serverlessWithoutOpenAPIVersion.processedInput;
|
|
44
44
|
let expected = new DefinitionGenerator(
|
|
@@ -105,7 +105,7 @@ describe("DefinitionGenerator", () => {
|
|
|
105
105
|
expect(expected.version).to.be.equal("3.0.0");
|
|
106
106
|
});
|
|
107
107
|
|
|
108
|
-
it("should respect the version of
|
|
108
|
+
it("should respect the version of OpenAPI when passed in", function () {
|
|
109
109
|
const serverlessWithOpenAPIVersion = structuredClone(mockServerless);
|
|
110
110
|
serverlessWithOpenAPIVersion.processedInput.options.openApiVersion =
|
|
111
111
|
"3.0.2";
|
|
@@ -157,7 +157,7 @@ describe("DefinitionGenerator", () => {
|
|
|
157
157
|
});
|
|
158
158
|
|
|
159
159
|
describe("createInfo", () => {
|
|
160
|
-
it("should create
|
|
160
|
+
it("should create OpenAPI info object correctly", function () {
|
|
161
161
|
const definitionGenerator = new DefinitionGenerator(
|
|
162
162
|
mockServerless,
|
|
163
163
|
logger
|
|
@@ -918,14 +918,15 @@ describe("DefinitionGenerator", () => {
|
|
|
918
918
|
definitionGenerator.openAPI.components.securitySchemes
|
|
919
919
|
).to.have.property("x_amazon_api_key");
|
|
920
920
|
expect(
|
|
921
|
-
definitionGenerator.openAPI.components.securitySchemes
|
|
921
|
+
definitionGenerator.openAPI.components.securitySchemes
|
|
922
|
+
.x_amazon_api_key
|
|
922
923
|
).to.have.property("x-amazon-apigateway-authtype");
|
|
923
924
|
});
|
|
924
925
|
});
|
|
925
926
|
});
|
|
926
927
|
|
|
927
928
|
describe("createTags", () => {
|
|
928
|
-
it("should add tags to the
|
|
929
|
+
it("should add tags to the OpenAPI object correctly", function () {
|
|
929
930
|
mockServerless.service.custom.documentation.tags = [{ name: "tag1" }];
|
|
930
931
|
|
|
931
932
|
const definitionGenerator = new DefinitionGenerator(
|
|
@@ -68,7 +68,7 @@ describe("OpenAPIGenerator", () => {
|
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
describe("generationAndValidation", () => {
|
|
71
|
-
it("should correctly generate a valid
|
|
71
|
+
it("should correctly generate a valid OpenAPI document", async function () {
|
|
72
72
|
const succSpy = sinon.spy(logOutput.log, "success");
|
|
73
73
|
const errSpy = sinon.spy(logOutput.log, "error");
|
|
74
74
|
|
|
@@ -99,7 +99,7 @@ describe("OpenAPIGenerator", () => {
|
|
|
99
99
|
getFuncStub.reset();
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
-
xit("should throw an error when trying to generate an invalid
|
|
102
|
+
xit("should throw an error when trying to generate an invalid OpenAPI document", async function () {
|
|
103
103
|
const succSpy = sinon.spy(logOutput.log, "success");
|
|
104
104
|
const errSpy = sinon.spy(logOutput.log, "error");
|
|
105
105
|
|
|
@@ -135,7 +135,7 @@ describe("OpenAPIGenerator", () => {
|
|
|
135
135
|
getFuncStub.reset();
|
|
136
136
|
});
|
|
137
137
|
|
|
138
|
-
it("should correctly validate a valid
|
|
138
|
+
it("should correctly validate a valid OpenAPI document", async function () {
|
|
139
139
|
const succSpy = sinon.spy(logOutput.log, "success");
|
|
140
140
|
const errSpy = sinon.spy(logOutput.log, "error");
|
|
141
141
|
|
|
@@ -168,7 +168,7 @@ describe("OpenAPIGenerator", () => {
|
|
|
168
168
|
getFuncStub.reset();
|
|
169
169
|
});
|
|
170
170
|
|
|
171
|
-
it("should throw an error when trying to validate an invalid
|
|
171
|
+
it("should throw an error when trying to validate an invalid OpenAPI document", async function () {
|
|
172
172
|
const succSpy = sinon.spy(logOutput.log, "success");
|
|
173
173
|
const errSpy = sinon.spy(logOutput.log, "error");
|
|
174
174
|
|
|
@@ -212,7 +212,7 @@ describe("OpenAPIGenerator", () => {
|
|
|
212
212
|
});
|
|
213
213
|
|
|
214
214
|
describe("createPostman", () => {
|
|
215
|
-
it("should generate a postman collection when a valid
|
|
215
|
+
it("should generate a postman collection when a valid OpenAPI file is generated", function () {
|
|
216
216
|
const fsStub = sinon.stub(fs, "writeFileSync").returns(true);
|
|
217
217
|
const succSpy = sinon.spy(logOutput.log, "success");
|
|
218
218
|
const errSpy = sinon.spy(logOutput.log, "error");
|
|
@@ -4,7 +4,9 @@ const fs = require("fs").promises;
|
|
|
4
4
|
const path = require("path");
|
|
5
5
|
|
|
6
6
|
const expect = require("chai").expect;
|
|
7
|
+
const SchemaConvertor = require("json-schema-for-openapi");
|
|
7
8
|
const nock = require("nock");
|
|
9
|
+
const sinon = require("sinon");
|
|
8
10
|
|
|
9
11
|
const modelsDocumentOG = require("../models/models/models.json");
|
|
10
12
|
const modelsAltDocumentOG = require("../models/models/models-alt.json");
|
|
@@ -36,7 +38,7 @@ describe(`SchemaHandler`, function () {
|
|
|
36
38
|
);
|
|
37
39
|
|
|
38
40
|
const openAPISchema = {
|
|
39
|
-
|
|
41
|
+
openapi: "3.0.3",
|
|
40
42
|
components: {
|
|
41
43
|
schemas: {},
|
|
42
44
|
},
|
|
@@ -277,7 +279,7 @@ describe(`SchemaHandler`, function () {
|
|
|
277
279
|
|
|
278
280
|
describe(`addModelsToOpenAPI`, function () {
|
|
279
281
|
describe(`embedded simple schemas`, function () {
|
|
280
|
-
it(`should add the model to the
|
|
282
|
+
it(`should add the model to the OpenAPI schema`, async function () {
|
|
281
283
|
Object.assign(
|
|
282
284
|
mockServerless.service.custom.documentation,
|
|
283
285
|
modelsDocument
|
|
@@ -306,7 +308,7 @@ describe(`SchemaHandler`, function () {
|
|
|
306
308
|
});
|
|
307
309
|
});
|
|
308
310
|
|
|
309
|
-
it(`should add a model with references to the
|
|
311
|
+
it(`should add a model with references to the OpenAPI schema`, async function () {
|
|
310
312
|
Object.assign(
|
|
311
313
|
mockServerless.service.custom.documentation,
|
|
312
314
|
modelsDocument
|
|
@@ -379,7 +381,7 @@ describe(`SchemaHandler`, function () {
|
|
|
379
381
|
});
|
|
380
382
|
});
|
|
381
383
|
|
|
382
|
-
it(`should add a model with poorly dereferenced references to the
|
|
384
|
+
it(`should add a model with poorly dereferenced references to the OpenAPI schema`, async function () {
|
|
383
385
|
Object.assign(
|
|
384
386
|
mockServerless.service.custom.documentation,
|
|
385
387
|
modelsDocument
|
|
@@ -446,7 +448,7 @@ describe(`SchemaHandler`, function () {
|
|
|
446
448
|
});
|
|
447
449
|
|
|
448
450
|
describe(`component references`, function () {
|
|
449
|
-
it(`should add schemas with component references to the
|
|
451
|
+
it(`should add schemas with component references to the OpenAPI schema`, async function () {
|
|
450
452
|
Object.assign(
|
|
451
453
|
mockServerless.service.custom.documentation,
|
|
452
454
|
modelsDocument
|
|
@@ -517,10 +519,86 @@ describe(`SchemaHandler`, function () {
|
|
|
517
519
|
type: "string",
|
|
518
520
|
});
|
|
519
521
|
});
|
|
522
|
+
|
|
523
|
+
it(`should add schemas with component references to the OpenAPI schema using OpenAPI 3.1`, async function () {
|
|
524
|
+
Object.assign(
|
|
525
|
+
mockServerless.service.custom.documentation,
|
|
526
|
+
modelsDocument
|
|
527
|
+
);
|
|
528
|
+
|
|
529
|
+
mockServerless.service.custom.documentation.models.push({
|
|
530
|
+
name: "SuccessResponse",
|
|
531
|
+
contentType: "application/json",
|
|
532
|
+
schema: {
|
|
533
|
+
type: "array",
|
|
534
|
+
items: {
|
|
535
|
+
$ref: "#/components/schemas/Agency",
|
|
536
|
+
},
|
|
537
|
+
},
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
mockServerless.service.custom.documentation.models.push({
|
|
541
|
+
name: "Agency",
|
|
542
|
+
contentType: "application/json",
|
|
543
|
+
schema: {
|
|
544
|
+
type: "string",
|
|
545
|
+
},
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
openAPI.openapi = "3.1.0";
|
|
549
|
+
|
|
550
|
+
const schemaHandler = new SchemaHandler(
|
|
551
|
+
mockServerless,
|
|
552
|
+
openAPI,
|
|
553
|
+
logger
|
|
554
|
+
);
|
|
555
|
+
|
|
556
|
+
await schemaHandler.addModelsToOpenAPI();
|
|
557
|
+
|
|
558
|
+
expect(schemaHandler.openAPI).to.have.property("components");
|
|
559
|
+
expect(schemaHandler.openAPI.components).to.have.property("schemas");
|
|
560
|
+
expect(schemaHandler.openAPI.components.schemas).to.have.property(
|
|
561
|
+
"ErrorResponse"
|
|
562
|
+
);
|
|
563
|
+
expect(
|
|
564
|
+
schemaHandler.openAPI.components.schemas.ErrorResponse
|
|
565
|
+
).to.be.an("object");
|
|
566
|
+
expect(
|
|
567
|
+
schemaHandler.openAPI.components.schemas.ErrorResponse
|
|
568
|
+
).to.be.eql({
|
|
569
|
+
type: "object",
|
|
570
|
+
properties: { error: { type: "string" } },
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
expect(schemaHandler.openAPI.components.schemas).to.have.property(
|
|
574
|
+
"SuccessResponse"
|
|
575
|
+
);
|
|
576
|
+
expect(
|
|
577
|
+
schemaHandler.openAPI.components.schemas.SuccessResponse
|
|
578
|
+
).to.be.an("object");
|
|
579
|
+
expect(
|
|
580
|
+
schemaHandler.openAPI.components.schemas.SuccessResponse
|
|
581
|
+
).to.be.eql({
|
|
582
|
+
type: "array",
|
|
583
|
+
items: {
|
|
584
|
+
$ref: "#/components/schemas/Agency",
|
|
585
|
+
},
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
expect(schemaHandler.openAPI.components.schemas).to.have.property(
|
|
589
|
+
"Agency"
|
|
590
|
+
);
|
|
591
|
+
expect(schemaHandler.openAPI.components.schemas.Agency).to.be.an(
|
|
592
|
+
"object"
|
|
593
|
+
);
|
|
594
|
+
expect(schemaHandler.openAPI.components.schemas.Agency).to.be.eql({
|
|
595
|
+
type: "string",
|
|
596
|
+
});
|
|
597
|
+
});
|
|
520
598
|
});
|
|
521
599
|
|
|
522
600
|
describe(`other references`, function () {
|
|
523
|
-
it(`should add a model that is a webUrl to the
|
|
601
|
+
it(`should add a model that is a webUrl to the OpenAPI schema`, async function () {
|
|
524
602
|
Object.assign(
|
|
525
603
|
mockServerless.service.custom.documentation,
|
|
526
604
|
modelsDocument
|
|
@@ -589,7 +667,7 @@ describe(`SchemaHandler`, function () {
|
|
|
589
667
|
});
|
|
590
668
|
});
|
|
591
669
|
|
|
592
|
-
it(`should add a complex model that is a webUrl to the
|
|
670
|
+
it(`should add a complex model that is a webUrl to the OpenAPI schema`, async function () {
|
|
593
671
|
Object.assign(
|
|
594
672
|
mockServerless.service.custom.documentation,
|
|
595
673
|
modelsDocument
|
|
@@ -710,6 +788,28 @@ describe(`SchemaHandler`, function () {
|
|
|
710
788
|
});
|
|
711
789
|
|
|
712
790
|
describe(`createSchema`, function () {
|
|
791
|
+
it(`does not convert schemas when using OpenAPI 3.1.x`, async function () {
|
|
792
|
+
Object.assign(
|
|
793
|
+
mockServerless.service.custom.documentation,
|
|
794
|
+
modelsDocument
|
|
795
|
+
);
|
|
796
|
+
|
|
797
|
+
openAPI.openapi = "3.1.0";
|
|
798
|
+
|
|
799
|
+
const schemaHandler = new SchemaHandler(mockServerless, openAPI, logger);
|
|
800
|
+
|
|
801
|
+
const spy = sinon.spy(SchemaConvertor, "convert");
|
|
802
|
+
|
|
803
|
+
await schemaHandler.addModelsToOpenAPI();
|
|
804
|
+
|
|
805
|
+
const expected = await schemaHandler.createSchema("ErrorResponse");
|
|
806
|
+
|
|
807
|
+
expect(expected).to.be.equal("#/components/schemas/ErrorResponse");
|
|
808
|
+
expect(spy.calledOnce).to.be.false;
|
|
809
|
+
|
|
810
|
+
spy.restore();
|
|
811
|
+
});
|
|
812
|
+
|
|
713
813
|
it(`returns a reference to the schema when the schema already exists in components and we don't pass through a schema`, async function () {
|
|
714
814
|
Object.assign(
|
|
715
815
|
mockServerless.service.custom.documentation,
|