Skip to content
This repository has been archived by the owner on Oct 5, 2023. It is now read-only.

feat: stop running schema dereferencing when running validation #153

Merged
merged 2 commits into from
Aug 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions __tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ describe('#validate', () => {
expect(definition.openapi).toBe('3.0.0');
expect(Object.keys(definition.paths)).toHaveLength(14);
expect(definition.paths['/pet'].post.operationId).toBe('addPet');
expect(definition.paths['/pet'].post.requestBody).toStrictEqual({ $ref: '#/components/requestBodies/Pet' });
expect(Object.keys(definition.components.requestBodies)).toHaveLength(2);
expect(Object.keys(definition.components.securitySchemes)).toHaveLength(2);
expect(Object.keys(definition.components.schemas)).toHaveLength(6);
Expand All @@ -145,6 +146,7 @@ describe('#validate', () => {
expect(definition.openapi).toBe('3.0.0');
expect(Object.keys(definition.paths)).toHaveLength(14);
expect(definition.paths['/pet'].post.operationId).toBe('addPet');
expect(definition.paths['/pet'].post.requestBody).toStrictEqual({ $ref: '#/components/requestBodies/Pet' });
expect(Object.keys(definition.components.requestBodies)).toHaveLength(2);
expect(Object.keys(definition.components.securitySchemes)).toHaveLength(2);
expect(Object.keys(definition.components.schemas)).toHaveLength(6);
Expand Down Expand Up @@ -202,6 +204,7 @@ describe('#validate', () => {

expect(definition.openapi).toBe('3.0.0');
expect(definition.paths['/pet'].post.operationId).toBe('addPet');
expect(definition.paths['/pet'].post.requestBody).toStrictEqual({ $ref: '#/components/requestBodies/Pet' });
expect(Object.keys(definition.paths)).toHaveLength(14);
expect(Object.keys(definition.components.schemas)).toHaveLength(6);

Expand All @@ -214,6 +217,7 @@ describe('#validate', () => {

expect(definition.openapi).toBe('3.0.0');
expect(definition.paths['/pet'].post.operationId).toBe('addPet');
expect(definition.paths['/pet'].post.requestBody).toStrictEqual({ $ref: '#/components/requestBodies/Pet' });
expect(Object.keys(definition.paths)).toHaveLength(14);
expect(Object.keys(definition.components.schemas)).toHaveLength(6);
});
Expand Down
43 changes: 24 additions & 19 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
const fetch = require('node-fetch');
const fs = require('fs');
const $RefParser = require('@apidevtools/json-schema-ref-parser');
const converter = require('swagger2openapi');
const SwaggerParser = require('swagger-parser');
const swaggerParser = require('@apidevtools/swagger-parser');
const utils = require('./lib/utils');

class oasNormalize {
Expand Down Expand Up @@ -52,7 +51,7 @@ class oasNormalize {
if (this.cache.bundle) return Promise.resolve(this.cache.bundle);

return this.load()
.then(schema => $RefParser.bundle(schema))
.then(schema => swaggerParser.bundle(schema))
.then(bundle => {
this.cache.bundle = bundle;
return bundle;
Expand All @@ -63,32 +62,39 @@ class oasNormalize {
if (this.cache.deref) return Promise.resolve(this.cache.deref);

return this.load()
.then(schema => $RefParser.dereference(schema))
.then(schema => swaggerParser.dereference(schema))
.then(dereferenced => {
this.cache.deref = dereferenced;
return dereferenced;
});
}

async validate(convertToLatest) {
return this.deref().then(async schema => {
return this.load().then(async schema => {
const baseVersion = parseInt(utils.version(schema), 10);

const resolve = out => {
if (!convertToLatest) {
return out;
}

return converter.convertObj(out, { anchors: true }).then(options => {
return options.openapi;
});
};

if (baseVersion === 1) {
return Promise.reject(new Error('Swagger v1.2 is unsupported.'));
} else if (baseVersion === 2 || baseVersion === 3) {
return resolve(
await SwaggerParser.validate(schema).catch(err => {
// `swaggerParser.validate()` dereferences schemas at the same time as validation and does
// not give us an option to disable this. Since all we already have a dereferencing method
// on this library and our `validate()` method here just needs to tell us if the definition
// is valid or not we need to clone it before passing it over to `swagger-parser` so as to
// not run into pass-by-reference problems.
const clonedSchema = JSON.parse(JSON.stringify(schema));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(sigh)


return swaggerParser
.validate(clonedSchema)
.then(() => {
if (!convertToLatest) {
return schema;
}

return converter.convertObj(schema, { anchors: true }).then(options => {
return options.openapi;
});
})
.catch(err => {
const error = new Error(err.message.replace(/\[object Object\]/g, 'Schema'));
error.full = err;

Expand All @@ -108,8 +114,7 @@ class oasNormalize {
}

return Promise.reject(error);
})
);
});
}

return Promise.reject(new Error('The supplied API definition is unsupported.'));
Expand Down
38 changes: 9 additions & 29 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@
},
"license": "MIT",
"dependencies": {
"@apidevtools/json-schema-ref-parser": "^9.0.7",
"@apidevtools/swagger-parser": "^10.0.3",
"js-yaml": "^4.1.0",
"node-fetch": "^2.6.1",
"swagger-parser": "^10.0.1",
Comment on lines -40 to -43
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

"swagger2openapi": "^7.0.8"
},
"devDependencies": {
Expand Down