serverless-openapi-documenter 0.0.15 → 0.0.18
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/.github/workflows/node.yml +31 -0
- package/README.md +5 -0
- package/package.json +7 -2
- package/src/definitionGenerator.js +38 -6
- package/src/openAPIGenerator.js +0 -2
- package/test/.mocharc.js +9 -0
- package/test/helpers/ref-parser.js +5 -0
- package/test/helpers/serverless.js +19 -0
- package/test/json/complex.json +91 -0
- package/test/unit/definitionGenerator.spec.js +603 -0
- package/test/unit/openAPIGenerator.spec.js +10 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
|
2
|
+
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
|
3
|
+
|
|
4
|
+
name: Node.js CI
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [ "main" ]
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [ "main" ]
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
strategy:
|
|
18
|
+
matrix:
|
|
19
|
+
node-version: [14.x, 16.x]
|
|
20
|
+
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v3
|
|
24
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
25
|
+
uses: actions/setup-node@v3
|
|
26
|
+
with:
|
|
27
|
+
node-version: ${{ matrix.node-version }}
|
|
28
|
+
cache: 'npm'
|
|
29
|
+
- run: npm ci
|
|
30
|
+
- run: npm run build --if-present
|
|
31
|
+
- run: npm test
|
package/README.md
CHANGED
|
@@ -7,8 +7,13 @@
|
|
|
7
7
|
<a href="https://www.npmjs.com/package/serverless-openapi-documenter">
|
|
8
8
|
<img src="https://img.shields.io/npm/v/serverless-openapi-documenter.svg?style=flat-square">
|
|
9
9
|
</a>
|
|
10
|
+
<a href="https://github.com/JaredCE/serverless-openapi-documenter/actions/workflows/node.yml">
|
|
11
|
+
<img src="https://github.com/JaredCE/serverless-openapi-documenter/actions/workflows/node.yml/badge.svg">
|
|
12
|
+
</a>
|
|
10
13
|
</p>
|
|
11
14
|
|
|
15
|
+
|
|
16
|
+
|
|
12
17
|
This will generate an OpenAPI V3 (up to v3.0.3) file for you from your serverless file. It can optionally generate a Postman Collection V2 from the OpenAPI file for you too.
|
|
13
18
|
|
|
14
19
|
Originally based off of: https://github.com/temando/serverless-openapi-documentation
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "serverless-openapi-documenter",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"description": "Generate OpenAPI v3 documentation and Postman Collections from your Serverless Config",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"Postman-Collections"
|
|
15
15
|
],
|
|
16
16
|
"scripts": {
|
|
17
|
-
"test": "
|
|
17
|
+
"test": "mocha --config './test/.mocharc.js'"
|
|
18
18
|
},
|
|
19
19
|
"author": {
|
|
20
20
|
"name": "Jared Evans"
|
|
@@ -39,5 +39,10 @@
|
|
|
39
39
|
},
|
|
40
40
|
"engines": {
|
|
41
41
|
"node": ">=14"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"chai": "^4.3.6",
|
|
45
|
+
"mocha": "^10.0.0",
|
|
46
|
+
"sinon": "^14.0.0"
|
|
42
47
|
}
|
|
43
48
|
}
|
|
@@ -9,7 +9,7 @@ const $RefParser = require("@apidevtools/json-schema-ref-parser");
|
|
|
9
9
|
|
|
10
10
|
class DefinitionGenerator {
|
|
11
11
|
constructor(serverless, options = {}) {
|
|
12
|
-
this.version = serverless
|
|
12
|
+
this.version = serverless?.processedInput?.options?.openApiVersion || '3.0.0'
|
|
13
13
|
|
|
14
14
|
this.serverless = serverless
|
|
15
15
|
this.httpKeys = {
|
|
@@ -27,6 +27,7 @@ class DefinitionGenerator {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
this.operationIds = []
|
|
30
|
+
this.schemaIDs = []
|
|
30
31
|
|
|
31
32
|
try {
|
|
32
33
|
this.refParserOptions = require(path.resolve('options', 'ref-parser.js'))
|
|
@@ -108,7 +109,11 @@ class DefinitionGenerator {
|
|
|
108
109
|
slashPath = `/${event?.http?.path||event.httpApi?.path}`
|
|
109
110
|
}
|
|
110
111
|
|
|
111
|
-
|
|
112
|
+
if (paths[slashPath]) {
|
|
113
|
+
Object.assign(paths[slashPath], path);
|
|
114
|
+
} else {
|
|
115
|
+
Object.assign(paths, {[slashPath]: path});
|
|
116
|
+
}
|
|
112
117
|
}
|
|
113
118
|
}
|
|
114
119
|
}
|
|
@@ -129,6 +134,10 @@ class DefinitionGenerator {
|
|
|
129
134
|
obj.description = server.description
|
|
130
135
|
}
|
|
131
136
|
|
|
137
|
+
if (server.variables) {
|
|
138
|
+
obj.variables = server.variables
|
|
139
|
+
}
|
|
140
|
+
|
|
132
141
|
newServers.push(obj)
|
|
133
142
|
}
|
|
134
143
|
} else {
|
|
@@ -140,6 +149,10 @@ class DefinitionGenerator {
|
|
|
140
149
|
obj.description = servers.description
|
|
141
150
|
}
|
|
142
151
|
|
|
152
|
+
if (servers.variables) {
|
|
153
|
+
obj.variables = servers.variables
|
|
154
|
+
}
|
|
155
|
+
|
|
143
156
|
newServers.push(obj)
|
|
144
157
|
}
|
|
145
158
|
|
|
@@ -385,14 +398,33 @@ class DefinitionGenerator {
|
|
|
385
398
|
|
|
386
399
|
if (typeof schema !== 'string' && Object.keys(schema).length > 0) {
|
|
387
400
|
const convertedSchema = SchemaConvertor.convert(schema)
|
|
401
|
+
|
|
402
|
+
let schemaName = name
|
|
403
|
+
if (this.schemaIDs.includes(schemaName))
|
|
404
|
+
schemaName = `${name}-${uuid()}`
|
|
405
|
+
|
|
406
|
+
this.schemaIDs.push(schemaName)
|
|
407
|
+
|
|
388
408
|
for (const key of Object.keys(convertedSchema.schemas)) {
|
|
389
409
|
if (key === 'main' || key.split('-')[0] === 'main') {
|
|
390
|
-
|
|
410
|
+
let ref = `#/components/schemas/`
|
|
411
|
+
|
|
412
|
+
if (this.openAPI?.components?.schemas?.[name]) {
|
|
413
|
+
if (JSON.stringify(convertedSchema.schemas[key]) === JSON.stringify(this.openAPI.components.schemas[name])) {
|
|
414
|
+
return `${ref}${name}`
|
|
415
|
+
}
|
|
416
|
+
}
|
|
391
417
|
|
|
392
|
-
addToComponents(convertedSchema.schemas[key],
|
|
393
|
-
return ref
|
|
418
|
+
addToComponents(convertedSchema.schemas[key], schemaName)
|
|
419
|
+
return `${ref}${schemaName}`
|
|
394
420
|
} else {
|
|
395
|
-
|
|
421
|
+
if (this.openAPI?.components?.schemas?.[key]) {
|
|
422
|
+
if (JSON.stringify(convertedSchema.schemas[key]) !== JSON.stringify(this.openAPI.components.schemas[key])) {
|
|
423
|
+
addToComponents(convertedSchema.schemas[key], key)
|
|
424
|
+
}
|
|
425
|
+
} else {
|
|
426
|
+
addToComponents(convertedSchema.schemas[key], key)
|
|
427
|
+
}
|
|
396
428
|
}
|
|
397
429
|
}
|
|
398
430
|
} else {
|
package/src/openAPIGenerator.js
CHANGED
|
@@ -54,7 +54,6 @@ class OpenAPIGenerator {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
this.hooks = {
|
|
57
|
-
// 'before:deploy': this.beforeDeploy.bind(this),
|
|
58
57
|
'openapi:generate:serverless': this.generate.bind(this),
|
|
59
58
|
};
|
|
60
59
|
|
|
@@ -76,7 +75,6 @@ class OpenAPIGenerator {
|
|
|
76
75
|
|
|
77
76
|
this.serverless.configSchemaHandler.defineFunctionProperties('aws', {
|
|
78
77
|
properties: {
|
|
79
|
-
// description: {type: 'string'},
|
|
80
78
|
summary: {type: 'string'},
|
|
81
79
|
servers: {anyOf: [{type:'object'}, {type:'array'}]},
|
|
82
80
|
}
|
package/test/.mocharc.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "JSON Schema for CSR Framework",
|
|
3
|
+
"$schema": "http://json-schema.org/draft-04/schema",
|
|
4
|
+
"definitions": {
|
|
5
|
+
"log": {
|
|
6
|
+
"type": "object",
|
|
7
|
+
"title": "Logger options",
|
|
8
|
+
"properties": {
|
|
9
|
+
"channel": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"default": "console"
|
|
12
|
+
},
|
|
13
|
+
"path": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"default": "../src/logs"
|
|
16
|
+
},
|
|
17
|
+
"template": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"properties": {
|
|
20
|
+
"message": {
|
|
21
|
+
"type": "string"
|
|
22
|
+
},
|
|
23
|
+
"file": {
|
|
24
|
+
"type": "string"
|
|
25
|
+
},
|
|
26
|
+
"dir": {
|
|
27
|
+
"type": "string"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"telegram": {
|
|
32
|
+
"type": "object",
|
|
33
|
+
"properties": {
|
|
34
|
+
"bot_token": {
|
|
35
|
+
"type": "string"
|
|
36
|
+
},
|
|
37
|
+
"chat_id": {
|
|
38
|
+
"type": "string"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"required": ["chat_id", "bot_token"]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"template": {
|
|
46
|
+
"type": "object",
|
|
47
|
+
"properties": {
|
|
48
|
+
"path": {
|
|
49
|
+
"type": "string"
|
|
50
|
+
},
|
|
51
|
+
"cache": {
|
|
52
|
+
"type": "string"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"database": {
|
|
57
|
+
"type": "object",
|
|
58
|
+
"patternProperties": {
|
|
59
|
+
".*": {
|
|
60
|
+
"type": "object",
|
|
61
|
+
"properties": {
|
|
62
|
+
"provider": {
|
|
63
|
+
"type": "string"
|
|
64
|
+
},
|
|
65
|
+
"user": {
|
|
66
|
+
"type": "string"
|
|
67
|
+
},
|
|
68
|
+
"password": {
|
|
69
|
+
"type": "string"
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"required": ["provider"]
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"id": "https://json.schemastore.org/csr",
|
|
78
|
+
"properties": {
|
|
79
|
+
"log": {
|
|
80
|
+
"$ref": "#/definitions/log"
|
|
81
|
+
},
|
|
82
|
+
"template": {
|
|
83
|
+
"$ref": "#/definitions/template"
|
|
84
|
+
},
|
|
85
|
+
"database": {
|
|
86
|
+
"$ref": "#/definitions/database"
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"title": "CSR Framework schema",
|
|
90
|
+
"type": "object"
|
|
91
|
+
}
|
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const fs = require('fs').promises
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const sinon = require('sinon')
|
|
6
|
+
const $RefParser = require("@apidevtools/json-schema-ref-parser");
|
|
7
|
+
const expect = require('chai').expect
|
|
8
|
+
|
|
9
|
+
const serverlessMock = require('../helpers/serverless')
|
|
10
|
+
const DefinitionGenerator = require('../../src/definitionGenerator')
|
|
11
|
+
|
|
12
|
+
describe('DefinitionGenerator', () => {
|
|
13
|
+
let mockServerless
|
|
14
|
+
const v4 = new RegExp(/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i);
|
|
15
|
+
beforeEach(function() {
|
|
16
|
+
mockServerless = JSON.parse(JSON.stringify(serverlessMock))
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe('constructor', () => {
|
|
20
|
+
it('should return a definitionGenerator', function() {
|
|
21
|
+
const expected = new DefinitionGenerator({}, {})
|
|
22
|
+
expect(expected).to.be.an.instanceOf(DefinitionGenerator)
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should default to version 3.0.0 of openAPI when openAPI version is not passed in', function() {
|
|
26
|
+
let expected = new DefinitionGenerator({}, {})
|
|
27
|
+
expect(expected.version).to.be.equal('3.0.0')
|
|
28
|
+
|
|
29
|
+
let serverlessObj = {
|
|
30
|
+
processedInput: {}
|
|
31
|
+
}
|
|
32
|
+
expected = new DefinitionGenerator(serverlessObj, {})
|
|
33
|
+
expect(expected.version).to.be.equal('3.0.0')
|
|
34
|
+
|
|
35
|
+
serverlessObj.processedInput = {
|
|
36
|
+
options: {}
|
|
37
|
+
}
|
|
38
|
+
expected = new DefinitionGenerator(serverlessObj, {})
|
|
39
|
+
expect(expected.version).to.be.equal('3.0.0')
|
|
40
|
+
|
|
41
|
+
serverlessObj.processedInput.options = {
|
|
42
|
+
test: 'abc'
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
expected = new DefinitionGenerator(serverlessObj, {})
|
|
46
|
+
expect(expected.version).to.be.equal('3.0.0')
|
|
47
|
+
|
|
48
|
+
serverlessObj.processedInput.options = {
|
|
49
|
+
openApiVersion: null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
expected = new DefinitionGenerator(serverlessObj, {})
|
|
53
|
+
expect(expected.version).to.be.equal('3.0.0')
|
|
54
|
+
|
|
55
|
+
serverlessObj.processedInput.options = {
|
|
56
|
+
openApiVersion: undefined
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
expected = new DefinitionGenerator(serverlessObj, {})
|
|
60
|
+
expect(expected.version).to.be.equal('3.0.0')
|
|
61
|
+
|
|
62
|
+
serverlessObj.processedInput.options = {
|
|
63
|
+
openapiVersion: undefined
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
expected = new DefinitionGenerator(serverlessObj, {})
|
|
67
|
+
expect(expected.version).to.be.equal('3.0.0')
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should respect the version of openAPI when passed in', function() {
|
|
71
|
+
let serverlessObj = {
|
|
72
|
+
processedInput: {
|
|
73
|
+
options: {
|
|
74
|
+
openApiVersion: '3.0.0'
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
let expected = new DefinitionGenerator(serverlessObj, {})
|
|
79
|
+
expect(expected.version).to.be.equal('3.0.0')
|
|
80
|
+
|
|
81
|
+
serverlessObj = {
|
|
82
|
+
processedInput: {
|
|
83
|
+
options: {
|
|
84
|
+
openApiVersion: '3.0.1'
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
expected = new DefinitionGenerator(serverlessObj, {})
|
|
89
|
+
expect(expected.version).to.be.equal('3.0.1')
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should correctly resolve the RefParserOptions', async function() {
|
|
93
|
+
let expected = new DefinitionGenerator({}, {})
|
|
94
|
+
expect(expected.refParserOptions).to.be.an('object')
|
|
95
|
+
expect(expected.refParserOptions).to.be.empty
|
|
96
|
+
|
|
97
|
+
await fs.mkdir(path.resolve('options'))
|
|
98
|
+
.catch(err => {
|
|
99
|
+
console.error(err)
|
|
100
|
+
throw err
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
await fs.copyFile(path.resolve('test/helpers/ref-parser.js'), path.resolve('options/ref-parser.js'))
|
|
104
|
+
.catch(err => {
|
|
105
|
+
console.error(err)
|
|
106
|
+
throw err
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
expected = new DefinitionGenerator({}, {})
|
|
110
|
+
expect(expected.refParserOptions).to.be.an('object')
|
|
111
|
+
expect(expected.refParserOptions).to.have.property('continueOnError')
|
|
112
|
+
|
|
113
|
+
await fs.rm(path.resolve('options/ref-parser.js'))
|
|
114
|
+
.catch(err => {
|
|
115
|
+
console.error(err)
|
|
116
|
+
throw err
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
await fs.rmdir(path.resolve('options'))
|
|
120
|
+
.catch(err => {
|
|
121
|
+
console.error(err)
|
|
122
|
+
throw err
|
|
123
|
+
})
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe('createInfo', () => {
|
|
128
|
+
it('should create openAPI info object correctly', function() {
|
|
129
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
130
|
+
definitionGenerator.createInfo()
|
|
131
|
+
|
|
132
|
+
expect(definitionGenerator.openAPI).to.be.an('object')
|
|
133
|
+
expect(definitionGenerator.openAPI.info).to.be.an('object')
|
|
134
|
+
expect(definitionGenerator.openAPI.info).to.deep.equal(mockServerless.service.custom.documentation)
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('should use the service name when documentation title has not been supplied', function() {
|
|
138
|
+
delete mockServerless.service.custom.documentation.title
|
|
139
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
140
|
+
definitionGenerator.createInfo()
|
|
141
|
+
|
|
142
|
+
expect(definitionGenerator.openAPI).to.be.an('object')
|
|
143
|
+
expect(definitionGenerator.openAPI.info).to.be.an('object')
|
|
144
|
+
expect(definitionGenerator.openAPI.info.title).to.be.equal(mockServerless.service.service)
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('should use the service name when documentation description has not been supplied', function() {
|
|
148
|
+
delete mockServerless.service.custom.documentation.description
|
|
149
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
150
|
+
definitionGenerator.createInfo()
|
|
151
|
+
|
|
152
|
+
expect(definitionGenerator.openAPI).to.be.an('object')
|
|
153
|
+
expect(definitionGenerator.openAPI.info).to.be.an('object')
|
|
154
|
+
expect(definitionGenerator.openAPI.info.description).to.be.equal('')
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('should use an empty string when documentation description has not been supplied', function() {
|
|
158
|
+
delete mockServerless.service.custom.documentation.description
|
|
159
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
160
|
+
definitionGenerator.createInfo()
|
|
161
|
+
|
|
162
|
+
expect(definitionGenerator.openAPI).to.be.an('object')
|
|
163
|
+
expect(definitionGenerator.openAPI.info).to.be.an('object')
|
|
164
|
+
expect(definitionGenerator.openAPI.info.description).to.be.equal('')
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('should generate a uuid for version when documentation version has not been supplied', function() {
|
|
168
|
+
delete mockServerless.service.custom.documentation.version
|
|
169
|
+
|
|
170
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
171
|
+
definitionGenerator.createInfo()
|
|
172
|
+
|
|
173
|
+
expect(definitionGenerator.openAPI).to.be.an('object')
|
|
174
|
+
expect(definitionGenerator.openAPI.info).to.be.an('object')
|
|
175
|
+
expect(v4.test(definitionGenerator.openAPI.info.version)).to.be.true
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe('createTags', () => {
|
|
180
|
+
it('should add tags to the openAPI object correctly', function() {
|
|
181
|
+
mockServerless.service.custom.documentation.tags = [{name: 'tag1'}]
|
|
182
|
+
|
|
183
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
184
|
+
definitionGenerator.createTags()
|
|
185
|
+
|
|
186
|
+
expect(definitionGenerator.openAPI).to.be.an('object')
|
|
187
|
+
expect(definitionGenerator.openAPI.tags).to.be.an('array')
|
|
188
|
+
expect(definitionGenerator.openAPI.tags[0].name).to.be.equal('tag1')
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('should not add tags when they are not defined', function() {
|
|
192
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
193
|
+
expect(() => {
|
|
194
|
+
definitionGenerator.createTags()
|
|
195
|
+
}).to.throw()
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
describe('schemaCreator', () => {
|
|
200
|
+
describe('schemas that are objects', () => {
|
|
201
|
+
it('should add a simple schema to the components object', async function() {
|
|
202
|
+
const simpleSchema = {
|
|
203
|
+
type: 'string'
|
|
204
|
+
}
|
|
205
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
206
|
+
const expected = await definitionGenerator.schemaCreator(simpleSchema, 'simpleSchema')
|
|
207
|
+
.catch((err) => {
|
|
208
|
+
console.error(err)
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('simpleSchema')
|
|
212
|
+
expect(JSON.stringify(definitionGenerator.openAPI.components.schemas.simpleSchema)).to.equal(JSON.stringify(simpleSchema))
|
|
213
|
+
expect(expected).to.equal('#/components/schemas/simpleSchema')
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('should add a complex schema to the components object', async function() {
|
|
217
|
+
const complexSchema = {
|
|
218
|
+
type: 'object',
|
|
219
|
+
properties: {
|
|
220
|
+
error: {
|
|
221
|
+
type: 'string'
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
226
|
+
const expected = await definitionGenerator.schemaCreator(complexSchema, 'main')
|
|
227
|
+
.catch((err) => {
|
|
228
|
+
console.error(err)
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('main')
|
|
232
|
+
expect(JSON.stringify(definitionGenerator.openAPI.components.schemas.main)).to.equal(JSON.stringify(complexSchema))
|
|
233
|
+
expect(expected).to.equal('#/components/schemas/main')
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('should add each definition of a complex schema to the components object', async function() {
|
|
237
|
+
const complexSchema = {
|
|
238
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
|
239
|
+
"title": "JSON API Schema",
|
|
240
|
+
"description": "This is a blah blah for responses in the JSON API format. For more, see http://jsonapi.org",
|
|
241
|
+
"type": "object",
|
|
242
|
+
"required": [
|
|
243
|
+
"errors"
|
|
244
|
+
],
|
|
245
|
+
"properties": {
|
|
246
|
+
"errors": {
|
|
247
|
+
"type": "array",
|
|
248
|
+
"items": {
|
|
249
|
+
"$ref": "#/definitions/error"
|
|
250
|
+
},
|
|
251
|
+
"uniqueItems": true
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
"definitions": {
|
|
255
|
+
"error": {
|
|
256
|
+
"type": "object",
|
|
257
|
+
"properties": {
|
|
258
|
+
"id": {
|
|
259
|
+
"description": "A unique identifier for this particular occurrence of the problem.",
|
|
260
|
+
"type": "string"
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
267
|
+
const expected = await definitionGenerator.schemaCreator(complexSchema, 'PutRequest')
|
|
268
|
+
.catch((err) => {
|
|
269
|
+
console.error(err)
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('PutRequest')
|
|
273
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('error')
|
|
274
|
+
expect(expected).to.equal('#/components/schemas/PutRequest')
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it(`should not overwrite an object that already exists in the components if they're the same`, async function() {
|
|
278
|
+
const complexSchema = {
|
|
279
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
|
280
|
+
"title": "JSON API Schema",
|
|
281
|
+
"description": "This is a blah blah for responses in the JSON API format. For more, see http://jsonapi.org",
|
|
282
|
+
"type": "object",
|
|
283
|
+
"required": [
|
|
284
|
+
"errors"
|
|
285
|
+
],
|
|
286
|
+
"properties": {
|
|
287
|
+
"errors": {
|
|
288
|
+
"type": "array",
|
|
289
|
+
"items": {
|
|
290
|
+
"$ref": "#/definitions/error"
|
|
291
|
+
},
|
|
292
|
+
"uniqueItems": true
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
"definitions": {
|
|
296
|
+
"error": {
|
|
297
|
+
"type": "object",
|
|
298
|
+
"properties": {
|
|
299
|
+
"id": {
|
|
300
|
+
"description": "A unique identifier for this particular occurrence of the problem.",
|
|
301
|
+
"type": "string"
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
308
|
+
let expected = await definitionGenerator.schemaCreator(complexSchema, 'PutRequest')
|
|
309
|
+
.catch((err) => {
|
|
310
|
+
console.error(err)
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('PutRequest')
|
|
314
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('error')
|
|
315
|
+
expect(expected).to.equal('#/components/schemas/PutRequest')
|
|
316
|
+
|
|
317
|
+
expected = await definitionGenerator.schemaCreator(complexSchema, 'PutRequest')
|
|
318
|
+
.catch((err) => {
|
|
319
|
+
console.error(err)
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('PutRequest')
|
|
323
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('error')
|
|
324
|
+
expect(expected).to.equal('#/components/schemas/PutRequest')
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it(`should create a new object for a similarly named object but with different properties`, async function() {
|
|
328
|
+
const complexSchema = {
|
|
329
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
|
330
|
+
"title": "JSON API Schema",
|
|
331
|
+
"description": "This is a blah blah for responses in the JSON API format. For more, see http://jsonapi.org",
|
|
332
|
+
"type": "object",
|
|
333
|
+
"required": [
|
|
334
|
+
"errors"
|
|
335
|
+
],
|
|
336
|
+
"properties": {
|
|
337
|
+
"errors": {
|
|
338
|
+
"type": "array",
|
|
339
|
+
"items": {
|
|
340
|
+
"$ref": "#/definitions/error"
|
|
341
|
+
},
|
|
342
|
+
"uniqueItems": true
|
|
343
|
+
}
|
|
344
|
+
},
|
|
345
|
+
"definitions": {
|
|
346
|
+
"error": {
|
|
347
|
+
"type": "object",
|
|
348
|
+
"properties": {
|
|
349
|
+
"id": {
|
|
350
|
+
"description": "A unique identifier for this particular occurrence of the problem.",
|
|
351
|
+
"type": "string"
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
358
|
+
let expected = await definitionGenerator.schemaCreator(complexSchema, 'PutRequest')
|
|
359
|
+
.catch((err) => {
|
|
360
|
+
console.error(err)
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('PutRequest')
|
|
364
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('error')
|
|
365
|
+
expect(expected).to.equal('#/components/schemas/PutRequest')
|
|
366
|
+
|
|
367
|
+
complexSchema.properties.cheese = {
|
|
368
|
+
type: 'string'
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
expected = await definitionGenerator.schemaCreator(complexSchema, 'PutRequest')
|
|
372
|
+
.catch((err) => {
|
|
373
|
+
console.error(err)
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('PutRequest')
|
|
377
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('error')
|
|
378
|
+
|
|
379
|
+
let newSchemaStr = expected.split('/')
|
|
380
|
+
expect(v4.test(newSchemaStr[newSchemaStr.length-1].split('PutRequest-')[1])).to.be.true
|
|
381
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property(newSchemaStr[newSchemaStr.length-1])
|
|
382
|
+
|
|
383
|
+
// expected = await definitionGenerator.schemaCreator(complexSchema, 'PutRequest')
|
|
384
|
+
// .catch((err) => {
|
|
385
|
+
// console.error(err)
|
|
386
|
+
// })
|
|
387
|
+
|
|
388
|
+
// expect(definitionGenerator.openAPI.components.schemas).to.have.property('PutRequest')
|
|
389
|
+
// expect(definitionGenerator.openAPI.components.schemas).to.have.property('error')
|
|
390
|
+
// console.log(expected)
|
|
391
|
+
// expect(expected)
|
|
392
|
+
// expect(expected).to.equal('#/components/schemas/PutRequest1')
|
|
393
|
+
|
|
394
|
+
complexSchema.properties.wine = {
|
|
395
|
+
type: 'string'
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
expected = await definitionGenerator.schemaCreator(complexSchema, 'PutRequest')
|
|
399
|
+
.catch((err) => {
|
|
400
|
+
console.error(err)
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('PutRequest')
|
|
404
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('error')
|
|
405
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property(newSchemaStr[newSchemaStr.length-1])
|
|
406
|
+
newSchemaStr = expected.split('/')
|
|
407
|
+
expect(v4.test(newSchemaStr[newSchemaStr.length-1].split('PutRequest-')[1])).to.be.true
|
|
408
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property(newSchemaStr[newSchemaStr.length-1])
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
it(`should create a new object for a differently named object but with same properties`, async function() {
|
|
412
|
+
const complexSchema = {
|
|
413
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
|
414
|
+
"title": "JSON API Schema",
|
|
415
|
+
"description": "This is a blah blah for responses in the JSON API format. For more, see http://jsonapi.org",
|
|
416
|
+
"type": "object",
|
|
417
|
+
"required": [
|
|
418
|
+
"errors"
|
|
419
|
+
],
|
|
420
|
+
"properties": {
|
|
421
|
+
"errors": {
|
|
422
|
+
"type": "array",
|
|
423
|
+
"items": {
|
|
424
|
+
"$ref": "#/definitions/error"
|
|
425
|
+
},
|
|
426
|
+
"uniqueItems": true
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
"definitions": {
|
|
430
|
+
"error": {
|
|
431
|
+
"type": "object",
|
|
432
|
+
"properties": {
|
|
433
|
+
"id": {
|
|
434
|
+
"description": "A unique identifier for this particular occurrence of the problem.",
|
|
435
|
+
"type": "string"
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
442
|
+
let expected = await definitionGenerator.schemaCreator(complexSchema, 'PutRequest')
|
|
443
|
+
.catch((err) => {
|
|
444
|
+
console.error(err)
|
|
445
|
+
})
|
|
446
|
+
|
|
447
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('PutRequest')
|
|
448
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('error')
|
|
449
|
+
expect(expected).to.equal('#/components/schemas/PutRequest')
|
|
450
|
+
|
|
451
|
+
expected = await definitionGenerator.schemaCreator(complexSchema, 'ContactPutRequest')
|
|
452
|
+
.catch((err) => {
|
|
453
|
+
console.error(err)
|
|
454
|
+
})
|
|
455
|
+
|
|
456
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('PutRequest')
|
|
457
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('error')
|
|
458
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('ContactPutRequest')
|
|
459
|
+
expect(expected).to.equal('#/components/schemas/ContactPutRequest')
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
it('should not create an object that already references schemas in components', async function() {
|
|
463
|
+
const simpleSchema = {
|
|
464
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
|
465
|
+
"title": "JSON API Schema",
|
|
466
|
+
"description": "This is a blah blah for responses in the JSON API format. For more, see http://jsonapi.org",
|
|
467
|
+
"type": "object",
|
|
468
|
+
"properties": {
|
|
469
|
+
"meta": {
|
|
470
|
+
"type": "string",
|
|
471
|
+
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
476
|
+
let expected = await definitionGenerator.schemaCreator(simpleSchema, 'meta')
|
|
477
|
+
.catch((err) => {
|
|
478
|
+
console.error(err)
|
|
479
|
+
})
|
|
480
|
+
|
|
481
|
+
expect(expected).to.equal('#/components/schemas/meta')
|
|
482
|
+
|
|
483
|
+
const complexSchema = {
|
|
484
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
|
485
|
+
"title": "JSON API Schema",
|
|
486
|
+
"description": "This is a blah blah for responses in the JSON API format. For more, see http://jsonapi.org",
|
|
487
|
+
"type": "object",
|
|
488
|
+
"required": [
|
|
489
|
+
"errors"
|
|
490
|
+
],
|
|
491
|
+
"properties": {
|
|
492
|
+
"errors": {
|
|
493
|
+
"type": "array",
|
|
494
|
+
"items": {
|
|
495
|
+
"$ref": "#/definitions/error"
|
|
496
|
+
},
|
|
497
|
+
"uniqueItems": true
|
|
498
|
+
},
|
|
499
|
+
"meta": {
|
|
500
|
+
"$ref": "#/definitions/meta"
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
"definitions": {
|
|
504
|
+
"error": {
|
|
505
|
+
"type": "object",
|
|
506
|
+
"properties": {
|
|
507
|
+
"id": {
|
|
508
|
+
"description": "A unique identifier for this particular occurrence of the problem.",
|
|
509
|
+
"type": "string"
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
expected = await definitionGenerator.schemaCreator(complexSchema, 'PutRequest')
|
|
517
|
+
.catch((err) => {
|
|
518
|
+
console.error(err)
|
|
519
|
+
})
|
|
520
|
+
|
|
521
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('PutRequest')
|
|
522
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('error')
|
|
523
|
+
expect(expected).to.equal('#/components/schemas/PutRequest')
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
describe('schemas that are urls', () => {
|
|
528
|
+
it('should attempt to download a schema and convert it', async function() {
|
|
529
|
+
const simpleSchema = 'https:///google.com/build/LicensedMember.json'
|
|
530
|
+
const LicensedMemberJSON = require('../json/complex.json')
|
|
531
|
+
|
|
532
|
+
const stub = sinon.stub($RefParser, 'dereference').resolves(LicensedMemberJSON)
|
|
533
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
534
|
+
const expected = await definitionGenerator.schemaCreator(simpleSchema, 'LicensedMember')
|
|
535
|
+
.catch((err) => {
|
|
536
|
+
console.error(err)
|
|
537
|
+
})
|
|
538
|
+
|
|
539
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('LicensedMember')
|
|
540
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('log')
|
|
541
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('template')
|
|
542
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('database')
|
|
543
|
+
expect(expected).to.equal('#/components/schemas/LicensedMember')
|
|
544
|
+
|
|
545
|
+
stub.restore()
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
it('should take a mix of schemas', async function() {
|
|
549
|
+
const complexSchema = 'https:///google.com/build/LicensedMember.json'
|
|
550
|
+
const LicensedMemberJSON = require('../json/complex.json')
|
|
551
|
+
|
|
552
|
+
const stub = sinon.stub($RefParser, 'dereference').resolves(LicensedMemberJSON)
|
|
553
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
554
|
+
let expected = await definitionGenerator.schemaCreator(complexSchema, 'LicensedMember')
|
|
555
|
+
.catch((err) => {
|
|
556
|
+
console.error(err)
|
|
557
|
+
})
|
|
558
|
+
|
|
559
|
+
const simpleSchema = {
|
|
560
|
+
type: "object",
|
|
561
|
+
properties: {
|
|
562
|
+
UUID: {
|
|
563
|
+
$ref: "#/definitions/log"
|
|
564
|
+
},
|
|
565
|
+
name: {
|
|
566
|
+
type: "string"
|
|
567
|
+
}
|
|
568
|
+
},
|
|
569
|
+
definitions: {}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
expected = await definitionGenerator.schemaCreator(simpleSchema, 'simpleSchema')
|
|
573
|
+
.catch((err) => {
|
|
574
|
+
console.error(err)
|
|
575
|
+
})
|
|
576
|
+
|
|
577
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('LicensedMember')
|
|
578
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('log')
|
|
579
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('template')
|
|
580
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('database')
|
|
581
|
+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('simpleSchema')
|
|
582
|
+
expect(expected).to.equal('#/components/schemas/simpleSchema')
|
|
583
|
+
|
|
584
|
+
stub.restore()
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
it('should throw an error when a url can not be resolved', async function() {
|
|
588
|
+
const simpleSchema = 'https:///google.com/build/LicensedMember.json'
|
|
589
|
+
|
|
590
|
+
const stub = sinon.stub($RefParser, 'dereference').rejects(new Error())
|
|
591
|
+
const definitionGenerator = new DefinitionGenerator(mockServerless)
|
|
592
|
+
const expected = await definitionGenerator.schemaCreator(simpleSchema, 'simpleSchema')
|
|
593
|
+
.catch((err) => {
|
|
594
|
+
console.error(err)
|
|
595
|
+
})
|
|
596
|
+
|
|
597
|
+
expect(expected).to.be.undefined
|
|
598
|
+
|
|
599
|
+
stub.restore()
|
|
600
|
+
});
|
|
601
|
+
});
|
|
602
|
+
});
|
|
603
|
+
});
|