serverless-openapi-documenter 0.0.7 → 0.0.8
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 +81 -5
- package/package.json +3 -2
- package/src/definitionGenerator.js +120 -75
- package/src/openAPIGenerator.js +6 -3
package/README.md
CHANGED
|
@@ -153,7 +153,7 @@ The *required* directives for the models section are as follow:
|
|
|
153
153
|
* `name`: the name of the schema
|
|
154
154
|
* `description`: a description of the schema
|
|
155
155
|
* `contentType`: the content type of the described request/response (ie. `application/json` or `application/xml`).
|
|
156
|
-
* `schema`: The JSON Schema ([website](http://json-schema.org/)) that describes the model. You can either use inline `YAML` to define these
|
|
156
|
+
* `schema`: The JSON Schema ([website](http://json-schema.org/)) that describes the model. You can either use inline `YAML` to define these or use either an external file schema that serverless will resolve (as below), or a reference to an externally hosted schema that will be attempted to be resolved.
|
|
157
157
|
|
|
158
158
|
```yml
|
|
159
159
|
custom:
|
|
@@ -262,7 +262,7 @@ Query parameters can be described as follow:
|
|
|
262
262
|
* `name`: the name of the query variable
|
|
263
263
|
* `description`: a description of the query variable
|
|
264
264
|
* `required`: whether the query parameter is mandatory (boolean)
|
|
265
|
-
* `schema`: JSON schema (inline or
|
|
265
|
+
* `schema`: JSON schema (inline, file or externally hosted)
|
|
266
266
|
|
|
267
267
|
```yml
|
|
268
268
|
queryParams:
|
|
@@ -279,7 +279,7 @@ Path parameters can be described as follow:
|
|
|
279
279
|
|
|
280
280
|
* `name`: the name of the query variable
|
|
281
281
|
* `description`: a description of the query variable
|
|
282
|
-
* `schema`: JSON schema (inline or
|
|
282
|
+
* `schema`: JSON schema (inline, file or externally hosted)
|
|
283
283
|
|
|
284
284
|
```yml
|
|
285
285
|
pathParams:
|
|
@@ -296,7 +296,7 @@ Cookie parameters can be described as follow:
|
|
|
296
296
|
* `name`: the name of the query variable
|
|
297
297
|
* `description`: a description of the query variable
|
|
298
298
|
* `required`: whether the query parameter is mandatory (boolean)
|
|
299
|
-
* `schema`: JSON schema (inline or
|
|
299
|
+
* `schema`: JSON schema (inline, file or externally hosted)
|
|
300
300
|
|
|
301
301
|
```yml
|
|
302
302
|
cookieParams:
|
|
@@ -354,7 +354,7 @@ The attributes for a header are as follow:
|
|
|
354
354
|
|
|
355
355
|
* `name`: the name of the HTTP Header
|
|
356
356
|
* `description`: a description of the HTTP Header
|
|
357
|
-
* `schema`: JSON schema (inline or
|
|
357
|
+
* `schema`: JSON schema (inline, file or externally hosted)
|
|
358
358
|
|
|
359
359
|
```yml
|
|
360
360
|
responseHeaders:
|
|
@@ -373,6 +373,82 @@ requestHeaders:
|
|
|
373
373
|
|
|
374
374
|
Please view the example [serverless.yml](test/serverless\ 2/serverless.yml).
|
|
375
375
|
|
|
376
|
+
## Notes on schemas
|
|
377
|
+
|
|
378
|
+
Schemas can be either: inline, in file or externally hosted. If they're inline or in file, the plugin will attempt to normalise the schema to [OpenAPI 3.0.X specification](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#schemaObject).
|
|
379
|
+
|
|
380
|
+
If they exist as an external reference, for instance:
|
|
381
|
+
|
|
382
|
+
```yaml
|
|
383
|
+
schema: https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/bettercodehub.json
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
We use the plugin [JSON Schema $Ref Parser](https://apitools.dev/json-schema-ref-parser/) to attempt to parse and resolve the references. There are limitations to this. Consider the schema:
|
|
387
|
+
|
|
388
|
+
```json
|
|
389
|
+
{
|
|
390
|
+
"$schema": "https://json-schema.org/draft-04/schema",
|
|
391
|
+
"title": "Reusable Definitions",
|
|
392
|
+
"type": "object",
|
|
393
|
+
"id": "https://raw.githubusercontent.com/json-editor/json-editor/master/tests/fixtures/definitions.json",
|
|
394
|
+
"definitions": {
|
|
395
|
+
"address": {
|
|
396
|
+
"title": "Address",
|
|
397
|
+
"type": "object",
|
|
398
|
+
"properties": {
|
|
399
|
+
"street_address": { "type": "string" },
|
|
400
|
+
"city": { "type": "string" },
|
|
401
|
+
"state": { "type": "string" }
|
|
402
|
+
},
|
|
403
|
+
"required": ["street_address"]
|
|
404
|
+
},
|
|
405
|
+
"link" : {"$refs": "./properties.json#/properties/title"}
|
|
406
|
+
},
|
|
407
|
+
"properties": {
|
|
408
|
+
"address" : {"$refs": "#/definitions/address"}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
Where the definition "link" refers to a schema held in a directory that the resolver does not know about, we will not be able to fully resolve the schema which will likely cause errors in validation of the openAPI 3.0.X specification.
|
|
413
|
+
|
|
414
|
+
Because of the dependency we use to parse externally linked schemas, we can supply our own options to resolve schemas that are more difficult than a straight forward example.
|
|
415
|
+
|
|
416
|
+
You can create your own options file: https://apitools.dev/json-schema-ref-parser/docs/options.html to pass into the dependency that contains it's own resolver to allow you to resolve references that might be in hard to reach places. In your main project folder, you should have a folder called `options` with a file called `ref-parser.js` that looks like:
|
|
417
|
+
|
|
418
|
+
```js
|
|
419
|
+
'use strict'
|
|
420
|
+
|
|
421
|
+
// options from: https://apitools.dev/json-schema-ref-parser/docs/options.html
|
|
422
|
+
|
|
423
|
+
module.exports = {
|
|
424
|
+
continueOnError: true, // Don't throw on the first error
|
|
425
|
+
parse: {
|
|
426
|
+
json: false, // Disable the JSON parser
|
|
427
|
+
yaml: {
|
|
428
|
+
allowEmpty: false // Don't allow empty YAML files
|
|
429
|
+
},
|
|
430
|
+
text: {
|
|
431
|
+
canParse: [".txt", ".html"], // Parse .txt and .html files as plain text (strings)
|
|
432
|
+
encoding: 'utf16' // Use UTF-16 encoding
|
|
433
|
+
}
|
|
434
|
+
},
|
|
435
|
+
resolve: {
|
|
436
|
+
file: false, // Don't resolve local file references
|
|
437
|
+
http: {
|
|
438
|
+
timeout: 2000, // 2 second timeout
|
|
439
|
+
withCredentials: true, // Include auth credentials when resolving HTTP references
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
dereference: {
|
|
443
|
+
circular: false, // Don't allow circular $refs
|
|
444
|
+
excludedPathMatcher: (path) => // Skip dereferencing content under any 'example' key
|
|
445
|
+
path.includes("/example/")
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
If you don't supply this file, it will use the default options.
|
|
451
|
+
|
|
376
452
|
## License
|
|
377
453
|
|
|
378
454
|
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "serverless-openapi-documenter",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "Generate OpenAPI v3 documentation and Postman Collections from your Serverless Config",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -28,9 +28,10 @@
|
|
|
28
28
|
},
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"dependencies": {
|
|
31
|
+
"@apidevtools/json-schema-ref-parser": "^9.0.9",
|
|
31
32
|
"chalk": "^4.1.2",
|
|
32
33
|
"js-yaml": "^4.1.0",
|
|
33
|
-
"json-schema-for-openapi": "^0.1.
|
|
34
|
+
"json-schema-for-openapi": "^0.1.2",
|
|
34
35
|
"oas-validator": "^5.0.8",
|
|
35
36
|
"openapi-to-postmanv2": "^3.2.0",
|
|
36
37
|
"swagger2openapi": "^7.0.8",
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const path = require('path')
|
|
4
|
+
|
|
3
5
|
const { v4: uuid } = require('uuid')
|
|
4
6
|
const validator = require('oas-validator');
|
|
5
7
|
const SchemaConvertor = require('json-schema-for-openapi')
|
|
8
|
+
const $RefParser = require("@apidevtools/json-schema-ref-parser");
|
|
6
9
|
|
|
7
10
|
class DefinitionGenerator {
|
|
8
11
|
constructor(serverless, options = {}) {
|
|
@@ -24,11 +27,21 @@ class DefinitionGenerator {
|
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
this.operationIds = []
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
this.refParserOptions = require(path.resolve('options', 'ref-parser.js'))
|
|
33
|
+
} catch (err) {
|
|
34
|
+
this.refParserOptions = {}
|
|
35
|
+
}
|
|
36
|
+
|
|
27
37
|
}
|
|
28
38
|
|
|
29
|
-
parse() {
|
|
39
|
+
async parse() {
|
|
30
40
|
this.createInfo()
|
|
31
|
-
this.createPaths()
|
|
41
|
+
await this.createPaths()
|
|
42
|
+
.catch(err => {
|
|
43
|
+
throw err
|
|
44
|
+
})
|
|
32
45
|
|
|
33
46
|
if (this.serverless.service.custom.documentation.servers) {
|
|
34
47
|
const servers = this.createServers(this.serverless.service.custom.documentation.servers)
|
|
@@ -57,7 +70,7 @@ class DefinitionGenerator {
|
|
|
57
70
|
Object.assign(this.openAPI, {info})
|
|
58
71
|
}
|
|
59
72
|
|
|
60
|
-
createPaths() {
|
|
73
|
+
async createPaths() {
|
|
61
74
|
const paths = {}
|
|
62
75
|
const httpFunctions = this.getHTTPFunctions()
|
|
63
76
|
|
|
@@ -74,7 +87,11 @@ class DefinitionGenerator {
|
|
|
74
87
|
opId = `${httpFunction.functionInfo.name}-${uuid()}`
|
|
75
88
|
}
|
|
76
89
|
|
|
77
|
-
const path = this.createOperationObject(event.http.method || event.httpApi.method, documentation, opId)
|
|
90
|
+
const path = await this.createOperationObject(event.http.method || event.httpApi.method, documentation, opId)
|
|
91
|
+
.catch(err => {
|
|
92
|
+
throw err
|
|
93
|
+
})
|
|
94
|
+
|
|
78
95
|
if (httpFunction.functionInfo?.summary)
|
|
79
96
|
path.summary = httpFunction.functionInfo.summary
|
|
80
97
|
|
|
@@ -158,7 +175,7 @@ class DefinitionGenerator {
|
|
|
158
175
|
Object.assign(this.openAPI, {tags: tags})
|
|
159
176
|
}
|
|
160
177
|
|
|
161
|
-
createOperationObject(method, documentation, name = uuid()) {
|
|
178
|
+
async createOperationObject(method, documentation, name = uuid()) {
|
|
162
179
|
const obj = {
|
|
163
180
|
summary: documentation.summary || '',
|
|
164
181
|
description: documentation.description || '',
|
|
@@ -168,22 +185,34 @@ class DefinitionGenerator {
|
|
|
168
185
|
}
|
|
169
186
|
|
|
170
187
|
if (documentation.pathParams) {
|
|
171
|
-
const paramObject = this.createParamObject('path', documentation)
|
|
188
|
+
const paramObject = await this.createParamObject('path', documentation)
|
|
189
|
+
.catch(err => {
|
|
190
|
+
throw err
|
|
191
|
+
})
|
|
172
192
|
obj.parameters = obj.parameters.concat(paramObject)
|
|
173
193
|
}
|
|
174
194
|
|
|
175
195
|
if (documentation.queryParams) {
|
|
176
|
-
const paramObject = this.createParamObject('query', documentation)
|
|
196
|
+
const paramObject = await this.createParamObject('query', documentation)
|
|
197
|
+
.catch(err => {
|
|
198
|
+
throw err
|
|
199
|
+
})
|
|
177
200
|
obj.parameters = obj.parameters.concat(paramObject)
|
|
178
201
|
}
|
|
179
202
|
|
|
180
203
|
if (documentation.headerParams) {
|
|
181
|
-
const paramObject = this.createParamObject('header', documentation)
|
|
204
|
+
const paramObject = await this.createParamObject('header', documentation)
|
|
205
|
+
.catch(err => {
|
|
206
|
+
throw err
|
|
207
|
+
})
|
|
182
208
|
obj.parameters = obj.parameters.concat(paramObject)
|
|
183
209
|
}
|
|
184
210
|
|
|
185
211
|
if (documentation.cookieParams) {
|
|
186
|
-
const paramObject = this.createParamObject('cookie', documentation)
|
|
212
|
+
const paramObject = await this.createParamObject('cookie', documentation)
|
|
213
|
+
.catch(err => {
|
|
214
|
+
throw err
|
|
215
|
+
})
|
|
187
216
|
obj.parameters = obj.parameters.concat(paramObject)
|
|
188
217
|
}
|
|
189
218
|
|
|
@@ -195,10 +224,16 @@ class DefinitionGenerator {
|
|
|
195
224
|
obj.deprecated = documentation.deprecated
|
|
196
225
|
|
|
197
226
|
if (documentation.requestBody)
|
|
198
|
-
obj.requestBody = this.createRequestBody(documentation)
|
|
227
|
+
obj.requestBody = await this.createRequestBody(documentation)
|
|
228
|
+
.catch(err => {
|
|
229
|
+
throw err
|
|
230
|
+
})
|
|
199
231
|
|
|
200
232
|
if (documentation.methodResponses)
|
|
201
|
-
obj.responses = this.createResponses(documentation)
|
|
233
|
+
obj.responses = await this.createResponses(documentation)
|
|
234
|
+
.catch(err => {
|
|
235
|
+
throw err
|
|
236
|
+
})
|
|
202
237
|
|
|
203
238
|
if (documentation.servers) {
|
|
204
239
|
const servers = this.createServers(documentation.servers)
|
|
@@ -208,14 +243,17 @@ class DefinitionGenerator {
|
|
|
208
243
|
return {[method]: obj}
|
|
209
244
|
}
|
|
210
245
|
|
|
211
|
-
createResponses(documentation) {
|
|
246
|
+
async createResponses(documentation) {
|
|
212
247
|
const responses = {}
|
|
213
248
|
for (const response of documentation.methodResponses) {
|
|
214
249
|
const obj = {
|
|
215
250
|
description: response.responseBody.description || '',
|
|
216
251
|
}
|
|
217
252
|
|
|
218
|
-
obj.content = this.createMediaTypeObject(response.responseModels, 'responses')
|
|
253
|
+
obj.content = await this.createMediaTypeObject(response.responseModels, 'responses')
|
|
254
|
+
.catch(err => {
|
|
255
|
+
throw err
|
|
256
|
+
})
|
|
219
257
|
|
|
220
258
|
Object.assign(responses,{[response.statusCode]: obj})
|
|
221
259
|
}
|
|
@@ -223,18 +261,21 @@ class DefinitionGenerator {
|
|
|
223
261
|
return responses
|
|
224
262
|
}
|
|
225
263
|
|
|
226
|
-
createRequestBody(documentation) {
|
|
264
|
+
async createRequestBody(documentation) {
|
|
227
265
|
const obj = {
|
|
228
266
|
description: documentation.requestBody.description,
|
|
229
267
|
required: documentation.requestBody.required || false,
|
|
230
268
|
}
|
|
231
269
|
|
|
232
|
-
obj.content = this.createMediaTypeObject(documentation.requestModels, 'requestBody')
|
|
270
|
+
obj.content = await this.createMediaTypeObject(documentation.requestModels, 'requestBody')
|
|
271
|
+
.catch(err => {
|
|
272
|
+
throw err
|
|
273
|
+
})
|
|
233
274
|
|
|
234
275
|
return obj
|
|
235
276
|
}
|
|
236
277
|
|
|
237
|
-
createMediaTypeObject(models, type) {
|
|
278
|
+
async createMediaTypeObject(models, type) {
|
|
238
279
|
const mediaTypeObj = {}
|
|
239
280
|
for (const mediaTypeDocumentation of this.serverless.service.custom.documentation.models) {
|
|
240
281
|
if (Object.values(models).includes(mediaTypeDocumentation.name)) {
|
|
@@ -252,59 +293,12 @@ class DefinitionGenerator {
|
|
|
252
293
|
obj.examples = this.createExamples(mediaTypeDocumentation.examples)
|
|
253
294
|
|
|
254
295
|
if (mediaTypeDocumentation.content[contentKey].schema) {
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
if (this.openAPI?.components) {
|
|
263
|
-
if (this.openAPI.components?.schemas) {
|
|
264
|
-
const schemaObj = {
|
|
265
|
-
[mediaTypeDocumentation.name]: schema.schemas[key]
|
|
266
|
-
}
|
|
267
|
-
Object.assign(this.openAPI.components.schemas, schemaObj)
|
|
268
|
-
} else {
|
|
269
|
-
const schemaObj = {
|
|
270
|
-
[mediaTypeDocumentation.name]: schema.schemas[key]
|
|
271
|
-
}
|
|
272
|
-
Object.assign(this.openAPI.components, {schemas: schemaObj})
|
|
273
|
-
}
|
|
274
|
-
} else {
|
|
275
|
-
const components = {
|
|
276
|
-
components: {
|
|
277
|
-
schemas: {
|
|
278
|
-
[mediaTypeDocumentation.name]: schema.schemas[key]
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
Object.assign(this.openAPI, components)
|
|
283
|
-
}
|
|
284
|
-
} else {
|
|
285
|
-
if (this.openAPI?.components) {
|
|
286
|
-
if (this.openAPI.components?.schemas) {
|
|
287
|
-
const schemaObj = {
|
|
288
|
-
[key]: schema.schemas[key]
|
|
289
|
-
}
|
|
290
|
-
Object.assign(this.openAPI.components.schemas, schemaObj)
|
|
291
|
-
} else {
|
|
292
|
-
const schemaObj = {
|
|
293
|
-
[key]: schema.schemas[key]
|
|
294
|
-
}
|
|
295
|
-
Object.assign(this.openAPI.components, {schemas: schemaObj})
|
|
296
|
-
}
|
|
297
|
-
} else {
|
|
298
|
-
const components = {
|
|
299
|
-
components: {
|
|
300
|
-
schemas: {
|
|
301
|
-
[key]: schema.schemas[key]
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
Object.assign(this.openAPI, components)
|
|
306
|
-
}
|
|
307
|
-
}
|
|
296
|
+
const schemaRef = await this.schemaCreator(mediaTypeDocumentation.content[contentKey].schema, mediaTypeDocumentation.name)
|
|
297
|
+
.catch(err => {
|
|
298
|
+
throw err
|
|
299
|
+
})
|
|
300
|
+
obj.schema = {
|
|
301
|
+
$ref: schemaRef
|
|
308
302
|
}
|
|
309
303
|
}
|
|
310
304
|
|
|
@@ -314,7 +308,7 @@ class DefinitionGenerator {
|
|
|
314
308
|
return mediaTypeObj
|
|
315
309
|
}
|
|
316
310
|
|
|
317
|
-
createParamObject(paramIn, documentation) {
|
|
311
|
+
async createParamObject(paramIn, documentation) {
|
|
318
312
|
const params = []
|
|
319
313
|
for (const param of documentation[`${paramIn}Params`]) {
|
|
320
314
|
const obj = {
|
|
@@ -335,7 +329,7 @@ class DefinitionGenerator {
|
|
|
335
329
|
if (param.style)
|
|
336
330
|
obj.style = param.style
|
|
337
331
|
|
|
338
|
-
if (param.explode)
|
|
332
|
+
if (Object.keys(param).includes('explode'))
|
|
339
333
|
obj.explode = param.explode
|
|
340
334
|
|
|
341
335
|
if (paramIn === 'query' && param.allowReserved)
|
|
@@ -348,10 +342,12 @@ class DefinitionGenerator {
|
|
|
348
342
|
obj.examples = this.createExamples(param.examples)
|
|
349
343
|
|
|
350
344
|
if (param.schema) {
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
345
|
+
const schemaRef = await this.schemaCreator(param.schema, param.name)
|
|
346
|
+
.catch(err => {
|
|
347
|
+
throw err
|
|
348
|
+
})
|
|
349
|
+
obj.schema = {
|
|
350
|
+
$ref: schemaRef
|
|
355
351
|
}
|
|
356
352
|
}
|
|
357
353
|
|
|
@@ -360,6 +356,55 @@ class DefinitionGenerator {
|
|
|
360
356
|
return params;
|
|
361
357
|
}
|
|
362
358
|
|
|
359
|
+
async schemaCreator(schema, name) {
|
|
360
|
+
const addToComponents = (schema, name) => {
|
|
361
|
+
const schemaObj = {
|
|
362
|
+
[name]: schema
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (this.openAPI?.components) {
|
|
366
|
+
if (this.openAPI.components?.schemas) {
|
|
367
|
+
Object.assign(this.openAPI.components.schemas, schemaObj)
|
|
368
|
+
} else {
|
|
369
|
+
Object.assign(this.openAPI.components, {schemas: schemaObj})
|
|
370
|
+
}
|
|
371
|
+
} else {
|
|
372
|
+
const components = {
|
|
373
|
+
components: {
|
|
374
|
+
schemas: schemaObj
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
Object.assign(this.openAPI, components)
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (typeof schema !== 'string' && Object.keys(schema).length > 0) {
|
|
383
|
+
const convertedSchema = SchemaConvertor.convert(schema)
|
|
384
|
+
for (const key of Object.keys(convertedSchema.schemas)) {
|
|
385
|
+
if (key === 'main' || key.split('-')[0] === 'main') {
|
|
386
|
+
const ref = `#/components/schemas/${name}`
|
|
387
|
+
|
|
388
|
+
addToComponents(convertedSchema.schemas[key], name)
|
|
389
|
+
return ref
|
|
390
|
+
} else {
|
|
391
|
+
addToComponents(convertedSchema.schemas[key], key)
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
} else {
|
|
395
|
+
const combinedSchema = await $RefParser.dereference(schema, this.refParserOptions)
|
|
396
|
+
.catch(err => {
|
|
397
|
+
console.error(err)
|
|
398
|
+
throw err
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
return await this.schemaCreator(combinedSchema, name)
|
|
402
|
+
.catch(err => {
|
|
403
|
+
throw err
|
|
404
|
+
})
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
363
408
|
createExamples(examples) {
|
|
364
409
|
const examplesObj = {}
|
|
365
410
|
|
package/src/openAPIGenerator.js
CHANGED
|
@@ -104,12 +104,15 @@ class OpenAPIGenerator {
|
|
|
104
104
|
const config = this.processCliInput()
|
|
105
105
|
const generator = new DefinitionGenerator(this.serverless);
|
|
106
106
|
|
|
107
|
-
generator.parse()
|
|
107
|
+
await generator.parse()
|
|
108
|
+
.catch(err => {
|
|
109
|
+
this.log('error', chalk.bold.red(`ERROR: An error was thrown generating the OpenAPI v3 documentation`))
|
|
110
|
+
throw new this.serverless.classes.Error(err)
|
|
111
|
+
})
|
|
108
112
|
|
|
109
113
|
const valid = await generator.validate()
|
|
110
114
|
.catch(err => {
|
|
111
|
-
|
|
112
|
-
this.log('error', chalk.bold.red(`ERROR: An error was thrown generation the OpenAPI v3 documentation`))
|
|
115
|
+
this.log('error', chalk.bold.red(`ERROR: An error was thrown validating the OpenAPI v3 documentation`))
|
|
113
116
|
throw new this.serverless.classes.Error(err)
|
|
114
117
|
})
|
|
115
118
|
|