From 306d8498a1cf70270a5007b192f8a094de8bfd12 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Mon, 3 Feb 2020 11:41:08 -0800 Subject: [PATCH 1/2] chore: update dependencies --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b8960db..1a1eadc 100644 --- a/package.json +++ b/package.json @@ -15,16 +15,16 @@ "debug": "^4.1.1", "js-yaml": "^3.12.2", "swagger-client": "^3.8.25", - "swagger-parser": "^6.0.5" + "swagger-parser": "^8.0.4" }, "devDependencies": { "@loopback/example-todo": "^1.5.1", - "eslint": "^5.14.1", + "eslint": "^6.8.0", "eslint-config-loopback": "^13.0.0", "loopback": "^3.25.0", - "mocha": "^6.0.2", + "mocha": "^7.0.1", "p-event": "^4.0.0", - "should": "^11.1.2" + "should": "^13.2.3" }, "repository": { "type": "git", From fddc1dfa5e02c8f0971f6bd329d5887a4b986004 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Mon, 3 Feb 2020 11:41:40 -0800 Subject: [PATCH 2/2] Ensure swagger parser instances are not shared Fixes https://github.com/strongloop/loopback-next/issues/4553 --- lib/openapi-connector.js | 6 ++---- lib/spec-resolver.js | 14 +++++++++----- test/test-spec-resolver.js | 32 ++++++++++++++++++-------------- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/lib/openapi-connector.js b/lib/openapi-connector.js index ad1528f..0c6c957 100644 --- a/lib/openapi-connector.js +++ b/lib/openapi-connector.js @@ -47,6 +47,7 @@ function OpenApiConnector(settings) { this.spec = settings.spec; this.cache = settings.cache; this.connectorHooks = new ConnectorHooks(); + this.specResolver = new SpecResolver(); if (debug.enabled) { debug('Settings: %j', settings); @@ -82,7 +83,7 @@ OpenApiConnector.prototype.connect = function(cb) { } const validate = !!self.settings.validate; - SpecResolver.resolve( + self.specResolver.resolve( self.spec, {validate: {schema: validate, spec: validate}}, function(err, api) { @@ -135,7 +136,6 @@ OpenApiConnector.prototype.setupDataAccessObject = function() { this.specParsed = true; - /* eslint-disable one-const */ for (const tag in this.client.apis) { const api = this.client.apis[tag]; @@ -185,8 +185,6 @@ OpenApiConnector.prototype.setupDataAccessObject = function() { this.dataSource.mixin(this._models[model].model); } return this.DataAccessObject; - - /* eslint-enable one-const */ }; function createWrapper(method, operation, options = {positional: false}) { diff --git a/lib/spec-resolver.js b/lib/spec-resolver.js index 60cab39..4f51852 100644 --- a/lib/spec-resolver.js +++ b/lib/spec-resolver.js @@ -7,16 +7,20 @@ const SwaggerParser = require('swagger-parser'); -const parser = new SwaggerParser(); +function SpecResolver() { + this.parser = new SwaggerParser(); +} -exports.resolve = function resolveSpec(spec, options, cb) { +SpecResolver.prototype.resolve = function resolveSpec(spec, options, cb) { if (typeof options === 'function' && !cb) { cb = options; } options = Object.assign({validate: {schema: false, spec: false}}, options); - return parser.validate(spec, options, cb); + return this.parser.validate(spec, options, cb); }; -exports.validate = function validateSpec(spec, cb) { - return parser.validate(spec, {validate: {spec: true, schema: true}}, cb); +SpecResolver.prototype.validate = function validateSpec(spec, cb) { + return this.parser.validate(spec, {validate: {spec: true, schema: true}}, cb); }; + +module.exports = SpecResolver; diff --git a/test/test-spec-resolver.js b/test/test-spec-resolver.js index bb7ef85..e1c8def 100644 --- a/test/test-spec-resolver.js +++ b/test/test-spec-resolver.js @@ -8,18 +8,22 @@ /* eslint-disable max-len */ const should = require('should'); -const resolveSpec = require('../lib/spec-resolver').resolve; -const validateSpec = require('../lib/spec-resolver').validate; +const SpecResolver = require('../lib/spec-resolver'); + +describe('OpenAPI Spec SpecResolver', () => { + let specResolver; + beforeEach(() => { + specResolver = new SpecResolver(); + }); -describe('OpenAPI Spec resolver', () => { it('Should set url when given spec is a url', async () => { const spec = 'http://sample.com/swaggerAPI.json'; - resolveSpec(spec).should.be.rejectedWith(''); + specResolver.resolve(spec).should.be.rejectedWith(''); }); it('Should set spec object when given spec is swagger specification object', function(done) { const spec = require('./fixtures/2.0/petstore'); - resolveSpec(spec, function(err, api) { + specResolver.resolve(spec, function(err, api) { if (err) return done(err); api.should.have.property('swagger'); done(); @@ -28,7 +32,7 @@ describe('OpenAPI Spec resolver', () => { it('Should not accept specification types other than string/plain object', function(done) { const spec = function test() {}; - resolveSpec(spec, function(err, api) { + specResolver.resolve(spec, function(err, api) { should.exist(err); done(); }); @@ -37,7 +41,7 @@ describe('OpenAPI Spec resolver', () => { describe('File handling & spec resolution', function() { it('should read & set swagger spec from a local .json file', function(done) { const spec = './test/fixtures/2.0/petstore.json'; - resolveSpec(spec, function(err, api) { + specResolver.resolve(spec, function(err, api) { if (err) return done(err); api.should.have.property('swagger'); done(); @@ -46,7 +50,7 @@ describe('OpenAPI Spec resolver', () => { it('should read & set swagger spec from a local .yaml file', function(done) { const spec = './test/fixtures/2.0/petstore.yaml'; - resolveSpec(spec, function(err, api) { + specResolver.resolve(spec, function(err, api) { if (err) return done(err); api.should.have.property('swagger'); done(); @@ -55,7 +59,7 @@ describe('OpenAPI Spec resolver', () => { it('should support .yml extension for YAML spec files', function(done) { const spec = './test/fixtures/2.0/petstore.yml'; - resolveSpec(spec, function(err, api) { + specResolver.resolve(spec, function(err, api) { if (err) return done(err); api.should.have.property('swagger'); done(); @@ -64,7 +68,7 @@ describe('OpenAPI Spec resolver', () => { it('should not accept other spec file formats than .json/.yaml', function(done) { const spec = './test/fixtures/2.0/petstore.yaaml'; - resolveSpec(spec, function(err, api) { + specResolver.resolve(spec, function(err, api) { should.exist(err); done(); }); @@ -74,16 +78,16 @@ describe('OpenAPI Spec resolver', () => { describe('Spec validation against Swagger schema 2.0', function() { it('should validate provided specification against swagger spec. 2.0', function(done) { const spec = './test/fixtures/2.0/petstore.yaml'; - resolveSpec(spec, function(err, api) { + specResolver.resolve(spec, function(err, api) { if (err) return done(err); - validateSpec(api, done); + specResolver.validate(api, done); }); }); it('should throw error if validation fails', function(done) { const spec = {this: 'that'}; - validateSpec(spec, function(err, api) { + specResolver.validate(spec, function(err, api) { should.exist(err); done(); }); @@ -93,7 +97,7 @@ describe('OpenAPI Spec resolver', () => { describe('OpenAPI 3.0', function() { it('loads OpenAPI spec 3.0 yaml', function(done) { const spec = './test/fixtures/3.0/petstore.yaml'; - resolveSpec(spec, function(err, api) { + specResolver.resolve(spec, function(err, api) { if (err) return done(err); api.should.have.property('openapi', '3.0.0'); done();