Skip to content

Commit 479afc5

Browse files
authored
Merge pull request #77 from JaredCE/improve-dereferencing-schemas
Improve dereferencing schemas
2 parents b09e109 + 1c47411 commit 479afc5

File tree

4 files changed

+124
-36
lines changed

4 files changed

+124
-36
lines changed

package-lock.json

Lines changed: 57 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
{
22
"name": "serverless-openapi-documenter",
3-
"version": "0.0.41",
3+
"version": "0.0.42",
44
"description": "Generate OpenAPI v3 documentation and Postman Collections from your Serverless Config",
55
"main": "index.js",
66
"keywords": [
77
"serverless",
88
"serverless2",
99
"serverless3",
10+
"serverless framework",
11+
"serverless framework plugin",
12+
"serverless plugin",
1013
"openAPI",
1114
"openAPIv3",
1215
"openAPI3",
1316
"PostmanCollections",
14-
"Postman-Collections"
17+
"Postman-Collections",
18+
"Postman Collections"
1519
],
1620
"scripts": {
1721
"test": "mocha --config './test/.mocharc.js'"
@@ -44,6 +48,7 @@
4448
"devDependencies": {
4549
"chai": "^4.3.7",
4650
"mocha": "^10.2.0",
51+
"nock": "^13.2.9",
4752
"sinon": "^15.0.0"
4853
}
4954
}

src/definitionGenerator.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,15 +461,21 @@ class DefinitionGenerator {
461461
}
462462

463463
async dereferenceSchema(schema) {
464-
let deReferencedSchema = await $RefParser.dereference(schema, this.refParserOptions)
464+
let originalSchema = await $RefParser.bundle(schema, this.refParserOptions)
465+
.catch(err => {
466+
console.error(err)
467+
throw err
468+
})
469+
470+
let deReferencedSchema = await $RefParser.dereference(originalSchema, this.refParserOptions)
465471
.catch(err => {
466472
console.error(err)
467473
throw err
468474
})
469475

470476
// deal with schemas that have been de-referenced poorly: naive
471-
if (deReferencedSchema.$ref === '#') {
472-
const oldRef = schema.$ref
477+
if (deReferencedSchema?.$ref === '#') {
478+
const oldRef = originalSchema.$ref
473479
const path = oldRef.split('/')
474480

475481
const pathTitle = path[path.length-1]

test/unit/definitionGenerator.spec.js

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const fs = require('fs').promises
44
const path = require('path')
55
const sinon = require('sinon')
66
const $RefParser = require("@apidevtools/json-schema-ref-parser")
7+
const nock = require('nock')
78
const expect = require('chai').expect
89

910
const serverlessMock = require('../helpers/serverless')
@@ -948,10 +949,13 @@ describe('DefinitionGenerator', () => {
948949

949950
describe('schemas that are urls', () => {
950951
it('should attempt to download a schema and convert it', async function() {
951-
const simpleSchema = 'https:///google.com/build/LicensedMember.json'
952+
const simpleSchema = 'https://google.com/build/LicensedMember.json'
952953
const LicensedMemberJSON = require('../json/complex.json')
953954

954-
const stub = sinon.stub($RefParser, 'dereference').resolves(LicensedMemberJSON)
955+
const scope = nock('https://google.com')
956+
.get('/build/LicensedMember.json')
957+
.reply(200, LicensedMemberJSON)
958+
955959
const definitionGenerator = new DefinitionGenerator(mockServerless)
956960
const expected = await definitionGenerator.schemaCreator(simpleSchema, 'LicensedMember')
957961
.catch((err) => {
@@ -963,28 +967,16 @@ describe('DefinitionGenerator', () => {
963967
expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('template')
964968
expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('database')
965969
expect(expected).to.equal('#/components/schemas/LicensedMember')
966-
967-
stub.restore()
968970
});
969971

970972
it('should take a mix of schemas', async function() {
971-
const complexSchema = 'https:///google.com/build/LicensedMember.json'
973+
const complexSchema = 'https://google.com/build/LicensedMember.json'
972974
const LicensedMemberJSON = require('../json/complex.json')
973975

974-
// const stub = sinon.stub($RefParser, 'dereference').resolves(LicensedMemberJSON)
975-
const stub = sinon.stub($RefParser, 'dereference')
976-
.onFirstCall().resolves(LicensedMemberJSON)
977-
.onSecondCall().resolves({
978-
type: "object",
979-
properties: {
980-
UUID: {
981-
$ref: "#/definitions/log"
982-
},
983-
name: {
984-
type: "string"
985-
}
986-
}
987-
})
976+
const scope = nock('https://google.com')
977+
.get('/build/LicensedMember.json')
978+
.reply(200, LicensedMemberJSON)
979+
988980
const definitionGenerator = new DefinitionGenerator(mockServerless)
989981
let expected = await definitionGenerator.schemaCreator(complexSchema, 'LicensedMember')
990982
.catch((err) => {
@@ -1007,35 +999,65 @@ describe('DefinitionGenerator', () => {
1007999

10081000
expected = await definitionGenerator.schemaCreator(simpleSchema, 'simpleSchema')
10091001
.catch((err) => {
1002+
expect(err).to.be.an('error')
10101003
console.error(err)
10111004
})
10121005

1006+
expect(expected).to.be.undefined
10131007
expect(definitionGenerator.openAPI.components.schemas).to.have.property('LicensedMember')
10141008
expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('log')
10151009
expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('template')
10161010
expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('database')
1017-
expect(definitionGenerator.openAPI.components.schemas).to.have.property('simpleSchema')
1018-
expect(definitionGenerator.openAPI.components.schemas.simpleSchema.properties).to.have.property('UUID')
1019-
expect(definitionGenerator.openAPI.components.schemas.simpleSchema.properties).to.have.property('name')
1020-
expect(expected).to.equal('#/components/schemas/simpleSchema')
1021-
1022-
stub.restore()
10231011
});
10241012

10251013
it('should throw an error when a url can not be resolved', async function() {
1026-
const simpleSchema = 'https:///google.com/build/LicensedMember.json'
1014+
const simpleSchema = 'https://google.com/build/LicensedMember.json'
1015+
1016+
const scope = nock('https://google.com')
1017+
.get('/build/LicensedMember.json')
1018+
.reply(404)
10271019

1028-
const stub = sinon.stub($RefParser, 'dereference').rejects(new Error())
10291020
const definitionGenerator = new DefinitionGenerator(mockServerless)
10301021
const expected = await definitionGenerator.schemaCreator(simpleSchema, 'simpleSchema')
10311022
.catch((err) => {
1032-
console.error(err)
10331023
expect(err).to.be.an('error')
10341024
})
10351025

10361026
expect(expected).to.be.undefined
1027+
});
10371028

1038-
stub.restore()
1029+
it('should handle a poorly dereferenced schema', async function() {
1030+
const simpleSchema = 'https://google.com/build/LicensedMember.json'
1031+
1032+
const externalSchema = {
1033+
$schema: 'http://json-schema.org/draft-04/schema#',
1034+
title: 'JSON API Schema',
1035+
$ref: '#/definitions/Error',
1036+
definitions: {
1037+
Error: {
1038+
type: 'string'
1039+
}
1040+
}
1041+
}
1042+
1043+
const scope = nock('https://google.com')
1044+
.get('/build/LicensedMember.json')
1045+
.reply(200, externalSchema)
1046+
1047+
1048+
const definitionGenerator = new DefinitionGenerator(mockServerless)
1049+
const expected = await definitionGenerator.schemaCreator(simpleSchema, 'LicensedMember')
1050+
.catch((err) => {
1051+
console.error(err)
1052+
})
1053+
1054+
expect(definitionGenerator.openAPI.components.schemas).to.have.property('LicensedMember')
1055+
expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties).to.have.property('Error')
1056+
expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties.Error).to.have.property('type')
1057+
expect(definitionGenerator.openAPI.components.schemas.LicensedMember.properties.Error.type).to.be.equal('string')
1058+
expect(definitionGenerator.openAPI.components.schemas.LicensedMember).to.not.have.property('$schema')
1059+
expect(definitionGenerator.openAPI.components.schemas.LicensedMember).to.not.have.property('$definitions')
1060+
expect(expected).to.equal('#/components/schemas/LicensedMember')
10391061
});
10401062
});
10411063
});

0 commit comments

Comments
 (0)