serverless-openapi-documenter 0.0.120-beta.1 → 0.0.123
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 +2 -3
- package/package.json +7 -3
- package/src/bruno.js +32 -0
- package/src/collection.js +29 -0
- package/src/definitionGenerator.js +49 -39
- package/src/openAPIGenerator.js +32 -37
- package/src/postman.js +53 -0
- package/src/schemaHandler.js +65 -61
- package/test/.mocharc.js +0 -9
- package/test/helpers/redocly.json +0 -4
- package/test/helpers/ref-parser.js +0 -5
- package/test/helpers/serverless.js +0 -19
- package/test/json/complex.json +0 -91
- package/test/json/newOWASP.json +0 -53
- package/test/json/valid-openAPI.json +0 -274
- package/test/models/BasicDocumentation.json +0 -48
- package/test/models/BasicValidFunction.json +0 -44
- package/test/models/ErrorResponse.json +0 -118
- package/test/models/PutDocumentResponse.json +0 -5
- package/test/models/models/models-alt.json +0 -17
- package/test/models/models/models.json +0 -20
- package/test/models/models/modelsList-alt.json +0 -17
- package/test/models/models/modelsList.json +0 -20
- package/test/unit/definitionGenerator.spec.js +0 -981
- package/test/unit/logger.spec.js +0 -160
- package/test/unit/openAPIGenerator.spec.js +0 -275
- package/test/unit/owasp.spec.js +0 -120
- package/test/unit/schemaHandler.spec.js +0 -1023
package/README.md
CHANGED
|
@@ -12,9 +12,7 @@
|
|
|
12
12
|
</a>
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
|
-
This will generate an
|
|
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.
|
|
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) or (as of 0.0.120) [Bruno Collection](https://docs.usebruno.com/) from the OpenAPI file. This currently works for `http` and `httpApi` configurations.
|
|
18
16
|
|
|
19
17
|
Originally based off of: https://github.com/temando/serverless-openapi-documentation
|
|
20
18
|
|
|
@@ -51,6 +49,7 @@ Options:
|
|
|
51
49
|
--indent -i File indentation in spaces. Default: 2
|
|
52
50
|
--openApiVersion -a OpenAPI version to generate for. Default: 3.0.0
|
|
53
51
|
--postmanCollection -p Will generate a postman collection (from the generated OpenAPI Description), in json only, if passed in. Default: postman.json
|
|
52
|
+
--brunoCollection -b Will generate a Bruno collection (from the generated OpenAPI Description), in json only, if passed in. Default: bruno.json
|
|
54
53
|
--validationWarn -w Warn about validation errors only. Will write the OpenAPI file if generation is successful. Default: false
|
|
55
54
|
```
|
|
56
55
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "serverless-openapi-documenter",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.123",
|
|
4
4
|
"description": "Generate OpenAPI v3 documentation and Postman Collections from your Serverless Config",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -22,6 +22,9 @@
|
|
|
22
22
|
"PostmanCollections",
|
|
23
23
|
"Postman-Collections",
|
|
24
24
|
"Postman Collections",
|
|
25
|
+
"Bruno Collection",
|
|
26
|
+
"Bruno",
|
|
27
|
+
"Use Bruno",
|
|
25
28
|
"AWS",
|
|
26
29
|
"AWS APIGateway",
|
|
27
30
|
"Api Gateway",
|
|
@@ -46,11 +49,12 @@
|
|
|
46
49
|
"license": "MIT",
|
|
47
50
|
"dependencies": {
|
|
48
51
|
"@apidevtools/json-schema-ref-parser": "^9.1.0",
|
|
49
|
-
"@redocly/openapi-core": "^1.
|
|
52
|
+
"@redocly/openapi-core": "^1.2.0",
|
|
53
|
+
"@usebruno/converters": "^0.16.0",
|
|
50
54
|
"chalk": "^4.1.2",
|
|
51
55
|
"js-yaml": "^4.1.1",
|
|
52
56
|
"json-schema-for-openapi": "^0.5.0",
|
|
53
|
-
"openapi-to-postmanv2": "^
|
|
57
|
+
"openapi-to-postmanv2": "^6.0.0",
|
|
54
58
|
"uuid": "^11.1.0"
|
|
55
59
|
},
|
|
56
60
|
"engines": {
|
package/src/bruno.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { openApiToBruno } = require('@usebruno/converters');
|
|
4
|
+
|
|
5
|
+
const fs = require('fs/promises')
|
|
6
|
+
|
|
7
|
+
class Bruno {
|
|
8
|
+
constructor(output, serverless, logger) {
|
|
9
|
+
this.output = output;
|
|
10
|
+
this.logger = logger;
|
|
11
|
+
this.serverless = serverless;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async create(openAPI) {
|
|
15
|
+
try {
|
|
16
|
+
const brunoCollection = openApiToBruno(openAPI);
|
|
17
|
+
|
|
18
|
+
await fs.writeFile(this.output, JSON.stringify(brunoCollection, null, 2));
|
|
19
|
+
this.logger.success(
|
|
20
|
+
"Bruno collection Documentation Successfully Written"
|
|
21
|
+
);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
this.logger.error(
|
|
24
|
+
`ERROR: An error was thrown whilst writing the Bruno collection`
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
throw new this.serverless.classes.Error(error);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = Bruno;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Bruno = require('./bruno');
|
|
4
|
+
const Postman = require('./postman');
|
|
5
|
+
|
|
6
|
+
class CollectionFactory {
|
|
7
|
+
constructor(outputFile, serverless, logger) {
|
|
8
|
+
this.outputFile = outputFile;
|
|
9
|
+
this.serverless = serverless;
|
|
10
|
+
this.logger = logger;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
createCollection(type) {
|
|
14
|
+
let creator;
|
|
15
|
+
switch (type){
|
|
16
|
+
case 'bruno':
|
|
17
|
+
creator = new Bruno(this.outputFile, this.serverless, this.logger);
|
|
18
|
+
break;
|
|
19
|
+
|
|
20
|
+
case 'postman':
|
|
21
|
+
creator = new Postman(this.outputFile, this.serverless, this.logger);
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return creator;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = CollectionFactory;
|
|
@@ -167,11 +167,12 @@ class DefinitionGenerator {
|
|
|
167
167
|
|
|
168
168
|
if (documentation.contact) {
|
|
169
169
|
const contactObj = {};
|
|
170
|
-
|
|
170
|
+
|
|
171
|
+
if (documentation.contact.name) contactObj.name = documentation.contact.name;
|
|
171
172
|
|
|
172
173
|
if (documentation.contact.url) contactObj.url = documentation.contact.url;
|
|
173
174
|
|
|
174
|
-
contactObj.email = documentation.contact.email
|
|
175
|
+
if (documentation.contact.email) contactObj.email = documentation.contact.email;
|
|
175
176
|
|
|
176
177
|
const extendedSpec = this.extendSpecification(documentation.contact);
|
|
177
178
|
|
|
@@ -591,7 +592,9 @@ class DefinitionGenerator {
|
|
|
591
592
|
obj.headers = corsHeaders;
|
|
592
593
|
addHeaders(owaspHeaders);
|
|
593
594
|
} else {
|
|
594
|
-
|
|
595
|
+
if (Object.keys(owaspHeaders).length) {
|
|
596
|
+
obj.headers = owaspHeaders;
|
|
597
|
+
}
|
|
595
598
|
}
|
|
596
599
|
}
|
|
597
600
|
|
|
@@ -677,10 +680,13 @@ class DefinitionGenerator {
|
|
|
677
680
|
|
|
678
681
|
async createRequestBody(requestBodyDetails) {
|
|
679
682
|
const obj = {
|
|
680
|
-
description: requestBodyDetails.description,
|
|
681
683
|
required: requestBodyDetails.required || false,
|
|
682
684
|
};
|
|
683
685
|
|
|
686
|
+
if (requestBodyDetails.description) {
|
|
687
|
+
obj.description = requestBodyDetails.description;
|
|
688
|
+
}
|
|
689
|
+
|
|
684
690
|
obj.content = await this.createMediaTypeObject(
|
|
685
691
|
requestBodyDetails.models
|
|
686
692
|
).catch((err) => {
|
|
@@ -692,7 +698,6 @@ class DefinitionGenerator {
|
|
|
692
698
|
|
|
693
699
|
async createMediaTypeObject(models, type) {
|
|
694
700
|
const mediaTypeObj = {};
|
|
695
|
-
|
|
696
701
|
for (const mediaTypeDocumentation of this.schemaHandler.models) {
|
|
697
702
|
if (models === undefined || models === null) {
|
|
698
703
|
throw new Error(
|
|
@@ -700,48 +705,53 @@ class DefinitionGenerator {
|
|
|
700
705
|
);
|
|
701
706
|
}
|
|
702
707
|
|
|
703
|
-
|
|
704
|
-
let contentKey
|
|
705
|
-
|
|
706
|
-
|
|
708
|
+
for (const modelContentType in models) {
|
|
709
|
+
let contentKey
|
|
710
|
+
|
|
711
|
+
if (models[modelContentType] === mediaTypeDocumentation.name) {
|
|
712
|
+
contentKey = modelContentType;
|
|
707
713
|
}
|
|
708
|
-
const obj = {};
|
|
709
714
|
|
|
710
|
-
|
|
711
|
-
if (mediaTypeDocumentation?.content) {
|
|
712
|
-
if (mediaTypeDocumentation.content[contentKey]?.example)
|
|
713
|
-
obj.example = mediaTypeDocumentation.content[contentKey].example;
|
|
715
|
+
if (contentKey) {
|
|
714
716
|
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
)
|
|
717
|
+
const obj = {};
|
|
718
|
+
let schema;
|
|
719
|
+
if (mediaTypeDocumentation.content) {
|
|
720
|
+
if (mediaTypeDocumentation.content[contentKey]?.example) {
|
|
721
|
+
obj.example = mediaTypeDocumentation.content[contentKey]?.example;
|
|
722
|
+
}
|
|
719
723
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
if (mediaTypeDocumentation?.example)
|
|
726
|
-
obj.example = mediaTypeDocumentation.example;
|
|
724
|
+
if (mediaTypeDocumentation.content[contentKey]?.examples) {
|
|
725
|
+
obj.examples = this.createExamples(
|
|
726
|
+
mediaTypeDocumentation.content[contentKey].examples
|
|
727
|
+
);
|
|
728
|
+
}
|
|
727
729
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
+
schema = (mediaTypeDocumentation.schema) ? mediaTypeDocumentation.schema : mediaTypeDocumentation.schemas[contentKey];
|
|
731
|
+
} else if (mediaTypeDocumentation?.contentType && mediaTypeDocumentation.schema) {
|
|
732
|
+
if (mediaTypeDocumentation.example) {
|
|
733
|
+
obj.example = mediaTypeDocumentation.example;
|
|
734
|
+
}
|
|
730
735
|
|
|
731
|
-
|
|
732
|
-
|
|
736
|
+
if (mediaTypeDocumentation.examples) {
|
|
737
|
+
obj.example = mediaTypeDocumentation.examples;
|
|
738
|
+
}
|
|
733
739
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
.catch((err) => {
|
|
737
|
-
throw err;
|
|
738
|
-
});
|
|
740
|
+
schema = mediaTypeDocumentation.schema;
|
|
741
|
+
}
|
|
739
742
|
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
+
const schemaRef = await this.schemaHandler
|
|
744
|
+
.createSchema(mediaTypeDocumentation.name)
|
|
745
|
+
.catch((err) => {
|
|
746
|
+
throw err;
|
|
747
|
+
});
|
|
743
748
|
|
|
744
|
-
|
|
749
|
+
obj.schema = {
|
|
750
|
+
$ref: schemaRef,
|
|
751
|
+
};
|
|
752
|
+
|
|
753
|
+
Object.assign(mediaTypeObj, { [contentKey]: obj });
|
|
754
|
+
}
|
|
745
755
|
}
|
|
746
756
|
}
|
|
747
757
|
|
|
@@ -861,7 +871,7 @@ class DefinitionGenerator {
|
|
|
861
871
|
if (
|
|
862
872
|
this.openAPI.components[type][name] &&
|
|
863
873
|
isEqual(schemaObj[name], this.openAPI.components[type][name]) ===
|
|
864
|
-
|
|
874
|
+
false
|
|
865
875
|
) {
|
|
866
876
|
delete schemaObj[name];
|
|
867
877
|
newName = `${name}-${uuid()}`;
|
package/src/openAPIGenerator.js
CHANGED
|
@@ -4,9 +4,9 @@ const fs = require("fs");
|
|
|
4
4
|
const yaml = require("js-yaml");
|
|
5
5
|
const chalk = require("chalk");
|
|
6
6
|
|
|
7
|
+
const Collection = require('./collection')
|
|
7
8
|
const DefinitionGenerator = require("./definitionGenerator");
|
|
8
9
|
const Logger = require("./logger");
|
|
9
|
-
const PostmanGenerator = require("openapi-to-postmanv2");
|
|
10
10
|
|
|
11
11
|
class OpenAPIGenerator {
|
|
12
12
|
constructor(serverless, options, { log = {} } = {}) {
|
|
@@ -44,10 +44,16 @@ class OpenAPIGenerator {
|
|
|
44
44
|
},
|
|
45
45
|
postmanCollection: {
|
|
46
46
|
usage:
|
|
47
|
-
"Output a
|
|
47
|
+
"Output a Postman collection and attach to OpenApi external documents [default: postman.json if passed]",
|
|
48
48
|
shortcut: "p",
|
|
49
49
|
type: "string",
|
|
50
50
|
},
|
|
51
|
+
brunoCollection: {
|
|
52
|
+
usage:
|
|
53
|
+
"Output a Bruno collection and attach to OpenApi external documents [default: bruno.json if passed]",
|
|
54
|
+
shortcut: "b",
|
|
55
|
+
type: "string",
|
|
56
|
+
},
|
|
51
57
|
validationWarn: {
|
|
52
58
|
usage:
|
|
53
59
|
"Only warn about validation errors of the OpenAPI Description, write the file if parsing is successful [default: false]",
|
|
@@ -144,8 +150,9 @@ class OpenAPIGenerator {
|
|
|
144
150
|
throw new this.serverless.classes.Error(err);
|
|
145
151
|
});
|
|
146
152
|
|
|
147
|
-
if (this.
|
|
148
|
-
this.
|
|
153
|
+
if (this.shouldCreateCollection()) {
|
|
154
|
+
await this.createCollection(validOpenAPI)
|
|
155
|
+
|
|
149
156
|
}
|
|
150
157
|
|
|
151
158
|
let output;
|
|
@@ -210,41 +217,21 @@ class OpenAPIGenerator {
|
|
|
210
217
|
return generator.openAPI;
|
|
211
218
|
}
|
|
212
219
|
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
`ERROR: An error was thrown when generating the postman collection`
|
|
218
|
-
);
|
|
219
|
-
throw new this.serverless.classes.Error(err);
|
|
220
|
-
}
|
|
220
|
+
async createCollection(validOpenAPI) {
|
|
221
|
+
const collectionOutputFile = this.config.postmanCollection || this.config.brunoCollection
|
|
222
|
+
const collection = new Collection(collectionOutputFile, this.serverless, this.logger)
|
|
223
|
+
const collectionCreator = collection.createCollection(this.collectionType())
|
|
221
224
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
);
|
|
225
|
+
await collectionCreator.create(validOpenAPI)
|
|
226
|
+
}
|
|
225
227
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
JSON.stringify(result.output[0].data)
|
|
230
|
-
);
|
|
231
|
-
this.logger.success(
|
|
232
|
-
"postman collection v2 Documentation Successfully Written"
|
|
233
|
-
);
|
|
234
|
-
} catch (err) {
|
|
235
|
-
this.logger.error(
|
|
236
|
-
`ERROR: An error was thrown whilst writing the postman collection`
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
throw new this.serverless.classes.Error(err);
|
|
240
|
-
}
|
|
241
|
-
};
|
|
228
|
+
shouldCreateCollection() {
|
|
229
|
+
return Boolean(this.config.postmanCollection || this.config.brunoCollection)
|
|
230
|
+
}
|
|
242
231
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
postmanGeneration
|
|
247
|
-
);
|
|
232
|
+
collectionType() {
|
|
233
|
+
if (this.config.postmanCollection) return 'postman'
|
|
234
|
+
else return 'bruno'
|
|
248
235
|
}
|
|
249
236
|
|
|
250
237
|
processCliInput() {
|
|
@@ -254,6 +241,7 @@ class OpenAPIGenerator {
|
|
|
254
241
|
indent: 2,
|
|
255
242
|
openApiVersion: "3.0.0",
|
|
256
243
|
postmanCollection: "postman.json",
|
|
244
|
+
brunoCollection: "bruno.json",
|
|
257
245
|
validationWarn: false,
|
|
258
246
|
};
|
|
259
247
|
|
|
@@ -263,6 +251,8 @@ class OpenAPIGenerator {
|
|
|
263
251
|
this.serverless.processedInput.options.openApiVersion || "3.0.0";
|
|
264
252
|
config.postmanCollection =
|
|
265
253
|
this.serverless.processedInput.options.postmanCollection || null;
|
|
254
|
+
config.brunoCollection =
|
|
255
|
+
this.serverless.processedInput.options.brunoCollection || null;
|
|
266
256
|
config.validationWarn =
|
|
267
257
|
this.serverless.processedInput.options.validationWarn || false;
|
|
268
258
|
|
|
@@ -285,7 +275,12 @@ class OpenAPIGenerator {
|
|
|
285
275
|
validationWarn: ${chalk.bold.green(String(config.validationWarn))}
|
|
286
276
|
${
|
|
287
277
|
config.postmanCollection
|
|
288
|
-
? `
|
|
278
|
+
? `Postman collection: ${chalk.bold.green(config.postmanCollection)}`
|
|
279
|
+
: `\n\n`
|
|
280
|
+
}
|
|
281
|
+
${
|
|
282
|
+
config.brunoCollection
|
|
283
|
+
? `Bruno collection: ${chalk.bold.green(config.brunoCollection)}`
|
|
289
284
|
: `\n\n`
|
|
290
285
|
}`
|
|
291
286
|
);
|
package/src/postman.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const PostmanGenerator = require("openapi-to-postmanv2");
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
|
|
7
|
+
class Postman {
|
|
8
|
+
constructor(output, serverless, logger) {
|
|
9
|
+
this.output = output;
|
|
10
|
+
this.logger = logger;
|
|
11
|
+
this.serverless = serverless;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
create(openAPI) {
|
|
15
|
+
const postmanGeneration = (err, result) => {
|
|
16
|
+
if (err) {
|
|
17
|
+
this.logger.error(
|
|
18
|
+
`ERROR: An error was thrown when generating the Postman collection`
|
|
19
|
+
);
|
|
20
|
+
throw new this.serverless.classes.Error(err);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this.logger.success(
|
|
24
|
+
"Postman collection v2 Documentation Successfully Generated"
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
fs.writeFileSync(
|
|
29
|
+
this.output,
|
|
30
|
+
JSON.stringify(result.output[0].data)
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
this.logger.success(
|
|
34
|
+
"Postman collection v2 Documentation Successfully Written"
|
|
35
|
+
);
|
|
36
|
+
} catch (err) {
|
|
37
|
+
this.logger.error(
|
|
38
|
+
`ERROR: An error was thrown whilst writing the Postman collection`
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
throw new this.serverless.classes.Error(err);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
PostmanGenerator.convert(
|
|
46
|
+
{ type: "json", data: structuredClone(openAPI) },
|
|
47
|
+
{},
|
|
48
|
+
postmanGeneration
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = Postman;
|
package/src/schemaHandler.js
CHANGED
|
@@ -16,12 +16,6 @@ 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
|
-
|
|
25
19
|
this.modelReferences = {};
|
|
26
20
|
|
|
27
21
|
this.__standardiseModels();
|
|
@@ -48,9 +42,21 @@ class SchemaHandler {
|
|
|
48
42
|
return model;
|
|
49
43
|
}
|
|
50
44
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
if (Object.keys(model.content).length === 1) {
|
|
46
|
+
const contentType = Object.keys(model.content)[0];
|
|
47
|
+
model.contentType = contentType;
|
|
48
|
+
model.contentTypes = [contentType];
|
|
49
|
+
model.schema = model.content[contentType].schema;
|
|
50
|
+
} else {
|
|
51
|
+
model.contentType = null;
|
|
52
|
+
model.contentTypes = Object.keys(model.content);
|
|
53
|
+
model.schema = null;
|
|
54
|
+
model.schemas = {};
|
|
55
|
+
for (const key in model.content) {
|
|
56
|
+
Object.assign(model.schemas, {[key]: {schema: model.content[key].schema}});
|
|
57
|
+
}
|
|
58
|
+
// model.schema = model.content[contentType].schema;
|
|
59
|
+
}
|
|
54
60
|
|
|
55
61
|
return model;
|
|
56
62
|
};
|
|
@@ -75,43 +81,53 @@ class SchemaHandler {
|
|
|
75
81
|
async addModelsToOpenAPI() {
|
|
76
82
|
for (const model of this.models) {
|
|
77
83
|
const modelName = model.name;
|
|
78
|
-
const
|
|
84
|
+
const schemas = []
|
|
85
|
+
if (model.schema){
|
|
86
|
+
// const modelSchema = model.schema;
|
|
87
|
+
schemas.push(model.schema)
|
|
88
|
+
} else {
|
|
89
|
+
for (const key in model.schemas) {
|
|
90
|
+
schemas.push(model.schemas[key].schema);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
79
93
|
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
94
|
+
for (const modelSchema of schemas) {
|
|
95
|
+
const convertedSchemas = await this.__dereferenceAndConvert(
|
|
96
|
+
modelSchema,
|
|
97
|
+
modelName,
|
|
98
|
+
model
|
|
99
|
+
).catch((err) => {
|
|
100
|
+
if (err instanceof Error) throw err;
|
|
101
|
+
else return err;
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
if (
|
|
105
|
+
typeof convertedSchemas.schemas === "object" &&
|
|
106
|
+
!Array.isArray(convertedSchemas.schemas) &&
|
|
107
|
+
convertedSchemas.schemas !== null
|
|
108
|
+
) {
|
|
109
|
+
for (const [schemaName, schemaValue] of Object.entries(
|
|
110
|
+
convertedSchemas.schemas
|
|
111
|
+
)) {
|
|
112
|
+
if (schemaName === modelName) {
|
|
113
|
+
this.modelReferences[
|
|
114
|
+
schemaName
|
|
115
|
+
] = `#/components/schemas/${modelName}`;
|
|
116
|
+
}
|
|
88
117
|
|
|
89
|
-
|
|
90
|
-
typeof convertedSchemas.schemas === "object" &&
|
|
91
|
-
!Array.isArray(convertedSchemas.schemas) &&
|
|
92
|
-
convertedSchemas.schemas !== null
|
|
93
|
-
) {
|
|
94
|
-
for (const [schemaName, schemaValue] of Object.entries(
|
|
95
|
-
convertedSchemas.schemas
|
|
96
|
-
)) {
|
|
97
|
-
if (schemaName === modelName) {
|
|
98
|
-
this.modelReferences[
|
|
99
|
-
schemaName
|
|
100
|
-
] = `#/components/schemas/${modelName}`;
|
|
118
|
+
this.__addToComponents("schemas", schemaValue, schemaName);
|
|
101
119
|
}
|
|
102
|
-
|
|
103
|
-
|
|
120
|
+
} else {
|
|
121
|
+
throw new Error(
|
|
122
|
+
`There was an error converting the ${
|
|
123
|
+
model.name
|
|
124
|
+
} schema. Model received looks like: \n\n${JSON.stringify(
|
|
125
|
+
model
|
|
126
|
+
)}. The convereted schema looks like \n\n${JSON.stringify(
|
|
127
|
+
convertedSchemas
|
|
128
|
+
)}`
|
|
129
|
+
);
|
|
104
130
|
}
|
|
105
|
-
} else {
|
|
106
|
-
throw new Error(
|
|
107
|
-
`There was an error converting the ${
|
|
108
|
-
model.name
|
|
109
|
-
} schema. Model received looks like: \n\n${JSON.stringify(
|
|
110
|
-
model
|
|
111
|
-
)}. The convereted schema looks like \n\n${JSON.stringify(
|
|
112
|
-
convertedSchemas
|
|
113
|
-
)}`
|
|
114
|
-
);
|
|
115
131
|
}
|
|
116
132
|
}
|
|
117
133
|
}
|
|
@@ -163,30 +179,18 @@ class SchemaHandler {
|
|
|
163
179
|
}
|
|
164
180
|
);
|
|
165
181
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
);
|
|
170
|
-
|
|
171
|
-
this.logger.verbose(`converting model: ${name}`);
|
|
172
|
-
const convertedSchemas = SchemaConvertor.convert(
|
|
173
|
-
dereferencedSchema,
|
|
174
|
-
name
|
|
175
|
-
);
|
|
182
|
+
this.logger.verbose(
|
|
183
|
+
`dereferenced model: ${JSON.stringify(dereferencedSchema)}`
|
|
184
|
+
);
|
|
176
185
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
);
|
|
180
|
-
return convertedSchemas;
|
|
181
|
-
}
|
|
186
|
+
this.logger.verbose(`converting model: ${name}`);
|
|
187
|
+
const convertedSchemas = SchemaConvertor.convert(dereferencedSchema, name);
|
|
182
188
|
|
|
183
189
|
this.logger.verbose(
|
|
184
|
-
`
|
|
185
|
-
schemas: { [name]: dereferencedSchema },
|
|
186
|
-
})}`
|
|
190
|
+
`converted schemas: ${JSON.stringify(convertedSchemas)}`
|
|
187
191
|
);
|
|
188
192
|
|
|
189
|
-
return
|
|
193
|
+
return convertedSchemas;
|
|
190
194
|
}
|
|
191
195
|
|
|
192
196
|
async __dereferenceSchema(schema) {
|
package/test/.mocharc.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
module.exports = {
|
|
4
|
-
processedInput: {
|
|
5
|
-
options: {
|
|
6
|
-
openApiVersion: '3.0.1'
|
|
7
|
-
}
|
|
8
|
-
},
|
|
9
|
-
service: {
|
|
10
|
-
service: 'myAPI',
|
|
11
|
-
custom: {
|
|
12
|
-
documentation: {
|
|
13
|
-
title: 'My new API',
|
|
14
|
-
description: 'This API does things',
|
|
15
|
-
version: '0.0.1'
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|