serverless-openapi-documenter 0.0.26 → 0.0.30
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
|
@@ -63,6 +63,7 @@ Options:
|
|
|
63
63
|
| externalDocs.url | custom.documentation.externalDocumentation.url |
|
|
64
64
|
| servers[].description | custom.documentation.servers.description |
|
|
65
65
|
| servers[].url | custom.documentation.servers.url |
|
|
66
|
+
| servers[].variables | custom.documentation.servers.variables |
|
|
66
67
|
| tags[].name | custom.documentation.tags.name |
|
|
67
68
|
| tags[].description | custom.documentation.tags.description |
|
|
68
69
|
| tags[].externalDocs.url | custom.documentation.tags.externalDocumentation.url |
|
|
@@ -121,8 +122,15 @@ custom:
|
|
|
121
122
|
url: https://google.com
|
|
122
123
|
description: A link to google
|
|
123
124
|
servers:
|
|
124
|
-
url: https://example.com
|
|
125
|
+
url: https://example.com:{port}/
|
|
125
126
|
description: The server
|
|
127
|
+
variables:
|
|
128
|
+
port:
|
|
129
|
+
enum:
|
|
130
|
+
- 4000
|
|
131
|
+
- 3000
|
|
132
|
+
default: 3000
|
|
133
|
+
description: The port the server operates on
|
|
126
134
|
tags:
|
|
127
135
|
- name: tag1
|
|
128
136
|
description: this is a tag
|
|
@@ -222,6 +230,39 @@ custom:
|
|
|
222
230
|
type: "string"
|
|
223
231
|
```
|
|
224
232
|
|
|
233
|
+
##### Model re-use
|
|
234
|
+
|
|
235
|
+
Through the magic of YAML, you can re-use models:
|
|
236
|
+
|
|
237
|
+
```yml
|
|
238
|
+
custom:
|
|
239
|
+
documentation:
|
|
240
|
+
...
|
|
241
|
+
models:
|
|
242
|
+
- name: "ErrorResponse"
|
|
243
|
+
description: "This is an error"
|
|
244
|
+
content:
|
|
245
|
+
application/json:
|
|
246
|
+
schema: &ErrorItem
|
|
247
|
+
type: object
|
|
248
|
+
properties:
|
|
249
|
+
message:
|
|
250
|
+
type: string
|
|
251
|
+
code:
|
|
252
|
+
type: integer
|
|
253
|
+
|
|
254
|
+
- name: "PutDocumentResponse"
|
|
255
|
+
description: "PUT Document response model (external reference example)"
|
|
256
|
+
content:
|
|
257
|
+
application/json:
|
|
258
|
+
schema:
|
|
259
|
+
type: array
|
|
260
|
+
items: *ErrorItem
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
`&ErrorItem` in the above example creates a node anchor (&ErrorItem) to the `ErrorResponse` schema which then can be used in the `PutDocumentResponse` schema via the reference (*ErrorItem). The node anchor needs to be declared first before it can be used elsewhere via the reference, swapping the above example around would result in an error.
|
|
264
|
+
|
|
265
|
+
|
|
225
266
|
#### Functions
|
|
226
267
|
|
|
227
268
|
To define the documentation for a given function event, you need to create a `documentation` attribute for your http event in your `serverless.yml` file.
|
|
@@ -238,6 +279,7 @@ The `documentation` section of the event configuration can contain the following
|
|
|
238
279
|
* `queryParams`: a list of query parameters (see [queryParams](#queryparams) below)
|
|
239
280
|
* `pathParams`: a list of path parameters (see [pathParams](#pathparams) below)
|
|
240
281
|
* `cookieParams`: a list of cookie parameters (see [cookieParams](#cookieparams) below)
|
|
282
|
+
* `headerParams`: a list of headers (see [headerParams](#headerparams---request-headers) below)
|
|
241
283
|
* `methodResponses`: an array of response models and applicable status codes
|
|
242
284
|
* `statusCode`: applicable http status code (ie. 200/404/500 etc.)
|
|
243
285
|
* `responseBody`: contains description of the response
|
|
@@ -285,12 +327,22 @@ functions:
|
|
|
285
327
|
description: "A Session ID variable"
|
|
286
328
|
schema:
|
|
287
329
|
type: "string"
|
|
330
|
+
headerParams:
|
|
331
|
+
name: "Content-Type"
|
|
332
|
+
description: "The content type"
|
|
333
|
+
schema:
|
|
334
|
+
type: "string"
|
|
288
335
|
methodResponses:
|
|
289
336
|
- statusCode: 201
|
|
290
337
|
responseBody:
|
|
291
338
|
description: "A user object along with generated API Keys"
|
|
292
339
|
responseModels:
|
|
293
340
|
application/json: "PutDocumentResponse"
|
|
341
|
+
responseHeaders:
|
|
342
|
+
X-Rate-Limit-Limit:
|
|
343
|
+
description: The number of allowed requests in the current period
|
|
344
|
+
schema:
|
|
345
|
+
type: integer
|
|
294
346
|
- statusCode: 500
|
|
295
347
|
responseBody:
|
|
296
348
|
description: "An error message when creating a new user"
|
|
@@ -320,8 +372,8 @@ queryParams:
|
|
|
320
372
|
|
|
321
373
|
Path parameters can be described as follow:
|
|
322
374
|
|
|
323
|
-
* `name`: the name of the
|
|
324
|
-
* `description`: a description of the
|
|
375
|
+
* `name`: the name of the path parameter
|
|
376
|
+
* `description`: a description of the path parameter
|
|
325
377
|
* `schema`: JSON schema (inline, file or externally hosted)
|
|
326
378
|
|
|
327
379
|
```yml
|
|
@@ -336,9 +388,9 @@ pathParams:
|
|
|
336
388
|
|
|
337
389
|
Cookie parameters can be described as follow:
|
|
338
390
|
|
|
339
|
-
* `name`: the name of the
|
|
340
|
-
* `description`: a description of the
|
|
341
|
-
* `required`: whether the
|
|
391
|
+
* `name`: the name of the cookie parameter
|
|
392
|
+
* `description`: a description of the cookie parameter
|
|
393
|
+
* `required`: whether the cookie parameter is mandatory (boolean)
|
|
342
394
|
* `schema`: JSON schema (inline, file or externally hosted)
|
|
343
395
|
|
|
344
396
|
```yml
|
|
@@ -354,9 +406,9 @@ cookieParams:
|
|
|
354
406
|
|
|
355
407
|
Request Headers can be described as follow:
|
|
356
408
|
|
|
357
|
-
* `name`: the name of the
|
|
358
|
-
* `description`: a description of the
|
|
359
|
-
* `required`: whether the
|
|
409
|
+
* `name`: the name of the header
|
|
410
|
+
* `description`: a description of the header
|
|
411
|
+
* `required`: whether the header is mandatory (boolean)
|
|
360
412
|
* `schema`: JSON schema (inline, file or externally hosted)
|
|
361
413
|
|
|
362
414
|
```yml
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "serverless-openapi-documenter",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.30",
|
|
4
4
|
"description": "Generate OpenAPI v3 documentation and Postman Collections from your Serverless Config",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -28,21 +28,21 @@
|
|
|
28
28
|
},
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@apidevtools/json-schema-ref-parser": "^9.0
|
|
31
|
+
"@apidevtools/json-schema-ref-parser": "^9.1.0",
|
|
32
32
|
"chalk": "^4.1.2",
|
|
33
33
|
"js-yaml": "^4.1.0",
|
|
34
|
-
"json-schema-for-openapi": "^0.
|
|
34
|
+
"json-schema-for-openapi": "^0.3.0",
|
|
35
35
|
"oas-validator": "^5.0.8",
|
|
36
|
-
"openapi-to-postmanv2": "^4.1
|
|
36
|
+
"openapi-to-postmanv2": "^4.4.1",
|
|
37
37
|
"swagger2openapi": "^7.0.8",
|
|
38
|
-
"uuid": "^
|
|
38
|
+
"uuid": "^9.0.0"
|
|
39
39
|
},
|
|
40
40
|
"engines": {
|
|
41
41
|
"node": ">=14"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"chai": "^4.3.
|
|
45
|
-
"mocha": "^10.
|
|
46
|
-
"sinon": "^
|
|
44
|
+
"chai": "^4.3.7",
|
|
45
|
+
"mocha": "^10.1.0",
|
|
46
|
+
"sinon": "^15.0.0"
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -410,6 +410,14 @@ class DefinitionGenerator {
|
|
|
410
410
|
return params;
|
|
411
411
|
}
|
|
412
412
|
|
|
413
|
+
async dereferenceSchema(schema) {
|
|
414
|
+
return await $RefParser.dereference(schema, this.refParserOptions)
|
|
415
|
+
.catch(err => {
|
|
416
|
+
console.error(err)
|
|
417
|
+
throw err
|
|
418
|
+
})
|
|
419
|
+
}
|
|
420
|
+
|
|
413
421
|
async schemaCreator(schema, name) {
|
|
414
422
|
const addToComponents = (schema, name) => {
|
|
415
423
|
const schemaObj = {
|
|
@@ -433,14 +441,27 @@ class DefinitionGenerator {
|
|
|
433
441
|
}
|
|
434
442
|
}
|
|
435
443
|
|
|
436
|
-
|
|
437
|
-
.catch(err => {
|
|
438
|
-
console.error(err)
|
|
444
|
+
let deReferencedSchema = await this.dereferenceSchema(schema)
|
|
445
|
+
.catch((err) => {
|
|
439
446
|
throw err
|
|
440
447
|
})
|
|
441
448
|
|
|
449
|
+
// deal with schemas that have been de-referenced poorly
|
|
450
|
+
if (deReferencedSchema.$ref === '#') {
|
|
451
|
+
const oldRef = schema.$ref
|
|
452
|
+
const path = oldRef.split('/')
|
|
453
|
+
|
|
454
|
+
const pathTitle = path[path.length-1]
|
|
455
|
+
const property = deReferencedSchema.definitions[path[path.length-1]]
|
|
456
|
+
Object.assign(deReferencedSchema, {properties: {[pathTitle]: property}})
|
|
457
|
+
delete deReferencedSchema.$ref
|
|
458
|
+
deReferencedSchema = await this.dereferenceSchema(deReferencedSchema)
|
|
459
|
+
.catch((err) => {
|
|
460
|
+
throw err
|
|
461
|
+
})
|
|
462
|
+
}
|
|
442
463
|
|
|
443
|
-
const convertedSchema = SchemaConvertor.convert(deReferencedSchema)
|
|
464
|
+
const convertedSchema = SchemaConvertor.convert(deReferencedSchema, name)
|
|
444
465
|
let schemaName = name
|
|
445
466
|
if (this.schemaIDs.includes(schemaName))
|
|
446
467
|
schemaName = `${name}-${uuid()}`
|
|
@@ -448,7 +469,7 @@ class DefinitionGenerator {
|
|
|
448
469
|
this.schemaIDs.push(schemaName)
|
|
449
470
|
|
|
450
471
|
for (const key of Object.keys(convertedSchema.schemas)) {
|
|
451
|
-
if (key ===
|
|
472
|
+
if (key === name || key.split('-')[0] === name) {
|
|
452
473
|
let ref = `#/components/schemas/`
|
|
453
474
|
|
|
454
475
|
if (this.openAPI?.components?.schemas?.[name]) {
|
|
@@ -458,6 +458,35 @@ describe('DefinitionGenerator', () => {
|
|
|
458
458
|
expect(definitionGenerator.openAPI.components.schemas).to.have.property('ContactPutRequest')
|
|
459
459
|
expect(expected).to.equal('#/components/schemas/ContactPutRequest')
|
|
460
460
|
});
|
|
461
|
+
|
|
462
|
+
it('should handle a schema that has been improperly dereferenced', async function() {
|
|
463
|
+
const simpleSchema = {
|
|
464
|
+
$schema: 'http://json-schema.org/draft-04/schema#',
|
|
465
|
+
title: 'JSON API Schema',
|
|
466
|
+
$ref: '#/definitions/Error',
|
|
467
|
+
definitions: {
|
|
468
|
+
Error: {
|
|
469
|
+
type: 'string'
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
474
|
+
const expected = await definitionGenerator.schemaCreator(simpleSchema, 'simpleSchema')
|
|
475
|
+
.catch((err) => {
|
|
476
|
+
console.error(err)
|
|
477
|
+
})
|
|
478
|
+
|
|
479
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('simpleSchema')
|
|
480
|
+
expect(definitionGenerator.openAPI.components.schemas.simpleSchema).to.deep.equal({
|
|
481
|
+
title: 'JSON API Schema',
|
|
482
|
+
properties: {
|
|
483
|
+
Error: {
|
|
484
|
+
type: 'string'
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
})
|
|
488
|
+
expect(expected).to.equal('#/components/schemas/simpleSchema')
|
|
489
|
+
});
|
|
461
490
|
});
|
|
462
491
|
|
|
463
492
|
describe('schemas that are urls', () => {
|
|
@@ -473,9 +502,9 @@ describe('DefinitionGenerator', () => {
|
|
|
473
502
|
})
|
|
474
503
|
|
|
475
504
|
expect(definitionGenerator.openAPI.components.schemas).to.have.property('LicensedMember')
|
|
476
|
-
expect(definitionGenerator.openAPI.components.schemas).to.have.property('log')
|
|
477
|
-
expect(definitionGenerator.openAPI.components.schemas).to.have.property('template')
|
|
478
|
-
expect(definitionGenerator.openAPI.components.schemas).to.have.property('database')
|
|
505
|
+
expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('log')
|
|
506
|
+
expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('template')
|
|
507
|
+
expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('database')
|
|
479
508
|
expect(expected).to.equal('#/components/schemas/LicensedMember')
|
|
480
509
|
|
|
481
510
|
stub.restore()
|
|
@@ -485,13 +514,27 @@ describe('DefinitionGenerator', () => {
|
|
|
485
514
|
const complexSchema = 'https:///google.com/build/LicensedMember.json'
|
|
486
515
|
const LicensedMemberJSON = require('../json/complex.json')
|
|
487
516
|
|
|
488
|
-
const stub = sinon.stub($RefParser, 'dereference').resolves(LicensedMemberJSON)
|
|
517
|
+
// const stub = sinon.stub($RefParser, 'dereference').resolves(LicensedMemberJSON)
|
|
518
|
+
const stub = sinon.stub($RefParser, 'dereference')
|
|
519
|
+
.onFirstCall().resolves(LicensedMemberJSON)
|
|
520
|
+
.onSecondCall().resolves({
|
|
521
|
+
type: "object",
|
|
522
|
+
properties: {
|
|
523
|
+
UUID: {
|
|
524
|
+
$ref: "#/definitions/log"
|
|
525
|
+
},
|
|
526
|
+
name: {
|
|
527
|
+
type: "string"
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
})
|
|
489
531
|
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
490
532
|
let expected = await definitionGenerator.schemaCreator(complexSchema, 'LicensedMember')
|
|
491
533
|
.catch((err) => {
|
|
492
534
|
console.error(err)
|
|
493
535
|
})
|
|
494
536
|
|
|
537
|
+
// this will fail validation due to a missing definition
|
|
495
538
|
const simpleSchema = {
|
|
496
539
|
type: "object",
|
|
497
540
|
properties: {
|
|
@@ -511,10 +554,12 @@ describe('DefinitionGenerator', () => {
|
|
|
511
554
|
})
|
|
512
555
|
|
|
513
556
|
expect(definitionGenerator.openAPI.components.schemas).to.have.property('LicensedMember')
|
|
514
|
-
expect(definitionGenerator.openAPI.components.schemas).to.have.property('log')
|
|
515
|
-
expect(definitionGenerator.openAPI.components.schemas).to.have.property('template')
|
|
516
|
-
expect(definitionGenerator.openAPI.components.schemas).to.have.property('database')
|
|
557
|
+
expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('log')
|
|
558
|
+
expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('template')
|
|
559
|
+
expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('database')
|
|
517
560
|
expect(definitionGenerator.openAPI.components.schemas).to.have.property('simpleSchema')
|
|
561
|
+
expect(definitionGenerator.openAPI.components.schemas.simpleSchema.properties).to.have.property('UUID')
|
|
562
|
+
expect(definitionGenerator.openAPI.components.schemas.simpleSchema.properties).to.have.property('name')
|
|
518
563
|
expect(expected).to.equal('#/components/schemas/simpleSchema')
|
|
519
564
|
|
|
520
565
|
stub.restore()
|
|
@@ -528,6 +573,7 @@ describe('DefinitionGenerator', () => {
|
|
|
528
573
|
const expected = await definitionGenerator.schemaCreator(simpleSchema, 'simpleSchema')
|
|
529
574
|
.catch((err) => {
|
|
530
575
|
console.error(err)
|
|
576
|
+
expect(err).to.be.an('error')
|
|
531
577
|
})
|
|
532
578
|
|
|
533
579
|
expect(expected).to.be.undefined
|