swagger-endpoint-validator
Advanced tools
Comparing version 1.1.5 to 2.0.0
172
index.js
@@ -1,158 +0,44 @@ | ||
const expressSwaggerGenerator = require('express-swagger-generator'); | ||
const validator = require('swagger-model-validator'); | ||
const swaggerJSDoc = require('swagger-jsdoc'); | ||
const swaggerUi = require('swagger-ui-express'); | ||
const debug = require('debug')('swagger-endpoint-validator'); | ||
const { SUPPORTED_FORMATS } = require('./lib/constants'); | ||
const customErrorHandler = require('./lib/customErrorHandler'); | ||
const normalizeOptions = require('./lib/normalizeOptions'); | ||
const openAPISpecification = require('./lib/openAPISpecification'); | ||
const validationEndpoint = require('./lib/validationEndpoint'); | ||
const validator = require('./lib/validator'); | ||
const errorFactory = require('./lib/errors'); | ||
const swaggerValidatorError = errorFactory('swagger_validator'); | ||
const SwaggerValidatorError = errorFactory('swagger_validator'); | ||
let singleton = null; | ||
let paths = null; | ||
/** | ||
* Replaces :<string> by {string}. | ||
* @param {string} pathStr - string to replace. | ||
* @returns Replaced string. | ||
* Initializes the Swagger endpoint validator. | ||
* @param {Object} app - Express application object. | ||
* @param {Object} options - Configuration object. | ||
* @param {boolean} [options.validateRequests=true] - true to validate the requests. | ||
* @param {boolean} [options.validateResponses=true] - true to validate the responses. | ||
* @param {string} [options.validationEndpoint=null] - endpoint to do schemas validation agains the OpenAPI schema. | ||
* @param {string} options.format - format of the OpenAPI specification documentation. | ||
* @param {Object} [options.yaml={}] - Extra configuration when format = 'yaml'. | ||
* @param {string} [options.yaml.file=null] - path of the yaml file containing the OpenAPI specification. | ||
* @param {Object} [options.yaml_jsdoc={}] - Extra configuration when format = 'yaml_jsdoc'. | ||
* @param {Object} [options.jsdoc={}] - Extra configuration when format = 'jsdoc'. | ||
*/ | ||
const formatPath = pathStr => pathStr.replace(/{/g, ':').replace(/}/g, ''); | ||
const init = async (app, options) => { | ||
debug('Initializing middleware for this express app...'); | ||
/** | ||
* Creates the validator singleton instance. | ||
* @param {object} app - Express application object. | ||
* @param {object} swaggerOptions - Swagger options. | ||
* @param {string} format - One of: 'jsdoc' or 'yaml'. | ||
* @returns Validator singleton instance initialized. | ||
*/ | ||
const createInstance = (app, swaggerOptions, format) => { | ||
const instance = { | ||
jsdoc: () => { | ||
const { swaggerDefinition, ...rest } = swaggerOptions; | ||
// Options has to be built this way to avoid "TypeError: Cannot add property swagger, object is not extensible" | ||
const options = { | ||
swaggerDefinition: { | ||
...swaggerOptions.swaggerDefinition, | ||
}, | ||
...rest, | ||
}; | ||
const swaggerInstance = expressSwaggerGenerator(app)(options); | ||
validator(swaggerInstance); | ||
return swaggerInstance; | ||
}, | ||
yaml: () => { | ||
const { swaggerDefinition, ...rest } = swaggerOptions; | ||
// Options for the swagger docs | ||
const options = { | ||
// Import swaggerDefinitions | ||
swaggerDefinition, | ||
...rest, | ||
}; | ||
// Initialize swagger-jsdoc -> returns validated swagger spec in json format | ||
const swaggerSpec = swaggerJSDoc(options); | ||
const swaggerInstance = validator(swaggerSpec); | ||
// If a URL is included in the configuration, serve the API doc through it | ||
if (rest.url) { | ||
app.use(rest.url, swaggerUi.serve, swaggerUi.setup(swaggerSpec)); | ||
} | ||
return swaggerInstance.swagger; | ||
}, | ||
}; | ||
return instance[format](); | ||
}; | ||
/** | ||
* Validates the payload for a specific endpoint. | ||
* @param {object} payload - Payload to be validated. | ||
* @param {object} request - Express request object. | ||
* @param {boolean} isInput - true if it's an input payload for the endpoint, false otherwise. | ||
* @throws {swaggerValidatorError} Swagger validator error. | ||
*/ | ||
const validate = (payload, request, isInput) => { | ||
if (!singleton) { | ||
throw swaggerValidatorError('Swagger not initialized!'); | ||
if (!options.format || !Object.values(SUPPORTED_FORMATS).includes(options.format)) { | ||
throw SwaggerValidatorError(`You need to specify the format used in the options. Supported values are ${Object.values(SUPPORTED_FORMATS).join(',')}`); | ||
} | ||
if (!payload || !request) { | ||
throw swaggerValidatorError('payload and request are required to do API validation.'); | ||
} | ||
const normalizedOptions = normalizeOptions(options); | ||
const spec = await openAPISpecification.generate(app, normalizedOptions); | ||
await validator.init(app, normalizedOptions, spec); | ||
validationEndpoint.add(app, normalizedOptions); | ||
customErrorHandler.add(app); | ||
const { method } = request; | ||
const { path: routePath } = request.route; | ||
const path = paths[routePath]; | ||
if (path) { | ||
const pathMethod = path[method.toLowerCase()]; | ||
if (pathMethod) { | ||
let schemaToValidate = isInput | ||
? pathMethod.parameters.find(item => item.name === 'body').schema | ||
: pathMethod.responses['200'].schema; | ||
schemaToValidate = schemaToValidate[0] ? schemaToValidate[0] : schemaToValidate; | ||
const validation = singleton.validateModel(schemaToValidate, payload, false, true); | ||
if (!validation.valid) { | ||
const error = swaggerValidatorError(validation.GetErrorMessages()); | ||
error.extra = validation.GetFormattedErrors(); | ||
throw error; | ||
} | ||
return { valid: validation.valid }; | ||
} | ||
} | ||
throw swaggerValidatorError('payload data not valid for validation.'); | ||
debug('Middleware initialized!'); | ||
}; | ||
/** | ||
* Initializes the validator. | ||
* @param {*} app - Express application object. | ||
* @param {*} swaggerOptions - Swagger options. | ||
* @param {*} format - One of: 'jsdoc' or 'yaml'. | ||
*/ | ||
const init = (app, swaggerOptions, format = 'jsdoc') => { | ||
if (!['jsdoc', 'yaml'].includes(format)) { | ||
throw swaggerValidatorError(`${format} format not supported`); | ||
} | ||
if (!singleton) { | ||
singleton = createInstance(app, swaggerOptions, format); | ||
paths = Object.keys(singleton.paths).reduce((acum, item) => ( | ||
{ ...acum, [formatPath(item)]: singleton.paths[item] } | ||
), {}); | ||
} | ||
}; | ||
/** | ||
* Resets the validator. | ||
*/ | ||
const reset = () => { | ||
singleton = null; | ||
}; | ||
/** | ||
* Validates a payload used as input body to a REST endpoint. | ||
* @param {object} payload - Payload to be validated. | ||
* @param {object} request - Express request object details. | ||
*/ | ||
const validateAPIInput = (payload, request) => validate(payload, request, true); | ||
/** | ||
* Validates a payload returned by a REST endpoint. | ||
* @param {object} payload - Payload to be validated. | ||
* @param {object} request - Express request object details. | ||
*/ | ||
const validateAPIOutput = (payload, request) => validate(payload, request, false); | ||
module.exports = { | ||
init, | ||
reset, | ||
validateAPIInput, | ||
validateAPIOutput, | ||
}; |
{ | ||
"name": "swagger-endpoint-validator", | ||
"version": "1.1.5", | ||
"version": "2.0.0", | ||
"description": "A validator of API endpoints to check that input and output match with the swagger specification for the API", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "jest", | ||
"test": "jest --verbose", | ||
"lint": "eslint ." | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "npm run lint && npm run test", | ||
"pre-push": "npm run test" | ||
} | ||
}, | ||
"repository": { | ||
@@ -26,16 +32,23 @@ "type": "git", | ||
"dependencies": { | ||
"debug": "^4.1.1", | ||
"express-openapi-validator": "^3.10.0", | ||
"express-swagger-generator": "^1.1.17", | ||
"js-yaml": "^3.13.1", | ||
"openapi-enforcer": "^1.10.1", | ||
"swagger-jsdoc": "^4.0.0", | ||
"swagger-model-validator": "^3.0.18", | ||
"swagger-ui-express": "^4.1.4" | ||
"swagger-ui-express": "^4.1.4", | ||
"swagger2openapi": "^6.0.2" | ||
}, | ||
"devDependencies": { | ||
"body-parser": "^1.19.0", | ||
"eslint": "^6.8.0", | ||
"eslint-config-airbnb-base": "^14.1.0", | ||
"eslint-plugin-import": "^2.20.1", | ||
"eslint-plugin-import": "^2.20.2", | ||
"eslint-plugin-jest": "^23.8.2", | ||
"express": "^4.17.1", | ||
"husky": "^4.2.3", | ||
"jest": "^25.1.0", | ||
"jest": "^25.2.4", | ||
"jest-junit": "^10.0.0", | ||
"mock-express": "^1.3.1" | ||
"supertest": "^4.0.2" | ||
}, | ||
@@ -42,0 +55,0 @@ "jest-junit": { |
@@ -1,93 +0,107 @@ | ||
const MockExpress = require('mock-express'); | ||
const express = require('express'); | ||
const bodyParser = require('body-parser'); | ||
const validator = require('../..'); | ||
const app = MockExpress(); // notice there's no "new" | ||
const pets = [ | ||
{ id: 1, name: 'pet 1', tag: 'dog' }, | ||
{ id: 2, name: 'pet 2', tag: 'cat' }, | ||
{ id: 3, name: 'pet 3', tag: 'bird' }, | ||
{ id: 4, name: 'pet 4', tag: 'dog' }, | ||
{ id: 5, name: 'pet 5', tag: 'cat' }, | ||
{ id: 6, name: 'pet 6', tag: 'bird' }, | ||
]; | ||
const validatorOptions = { | ||
swaggerDefinition: { | ||
info: { | ||
title: 'Test API', | ||
description: 'Test Express API with autogenerated swagger doc', | ||
version: '1.0.0', | ||
}, | ||
basePath: '/', | ||
}, | ||
basedir: process.cwd(), | ||
files: ['./test/jsdoc/**/**.js'], | ||
}; | ||
const wrongPets = [ | ||
{ id: 1, tag: 'dog' }, | ||
{ id: 2, tag: 'cat' }, | ||
{ id: 3, tag: 'bird' }, | ||
{ id: 4, tag: 'dog' }, | ||
{ id: 5, tag: 'cat' }, | ||
{ id: 6, tag: 'bird' }, | ||
]; | ||
validator.init(app, validatorOptions); | ||
const runServer = async () => { | ||
const app = express(); | ||
app.use(bodyParser.urlencoded({ extended: true })); | ||
app.use(bodyParser.json()); | ||
/** | ||
* @route GET /test-invalid-output | ||
* @summary Test invalid output | ||
* @group test - Everything about tests | ||
* @param {Input.model} body.body.required | ||
* @returns {Output.model} 200 - Successful operation | ||
* @returns {Error.model} 404 - Error message | ||
*/ | ||
app.get('/test-invalid-input', (req, res) => { | ||
try { | ||
const result = validator.validateAPIInput({}, req); | ||
res.status(200).json(result); | ||
} catch (error) { | ||
res.status(404).json({ error }); | ||
} | ||
}); | ||
await validator.init(app, { | ||
validationEndpoint: '/test', | ||
validateRequests: true, | ||
validateResponses: true, | ||
format: 'jsdoc', | ||
jsdoc: { | ||
swaggerDefinition: { | ||
info: { | ||
version: '1.0.0', | ||
title: 'Swagger Petstore', | ||
description: 'A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.0 specification', | ||
termsOfService: 'http://swagger.io/terms/', | ||
contact: { | ||
name: 'Swagger API Team', | ||
email: 'apiteam@swagger.io', | ||
url: 'http://swagger.io', | ||
}, | ||
license: { | ||
name: 'Apache 2.0', | ||
url: 'https://www.apache.org/licenses/LICENSE-2.0.html', | ||
}, | ||
}, | ||
}, | ||
basedir: process.cwd(), | ||
files: [ | ||
'./test/jsdoc/fake-server.js', | ||
'./test/jsdoc/components.js', | ||
], | ||
}, | ||
}); | ||
/** | ||
* @route GET /test-invalid-output | ||
* @summary Test invalid output | ||
* @group test - Everything about tests | ||
* @param {Input.model} body.body.required | ||
* @returns {Output.model} 200 - Successful operation | ||
* @returns {Error.model} 404 - Error message | ||
*/ | ||
app.get('/test-invalid-output', (req, res) => { | ||
try { | ||
const result = validator.validateAPIOutput({}, req); | ||
res.status(200).json(result); | ||
} catch (error) { | ||
res.status(404).json({ error }); | ||
} | ||
}); | ||
/** | ||
* @route GET /pets | ||
* @summary Returns all pets from the system that the user has access to | ||
* @param {[string]} tags.query - tags to filter by | ||
* @param {integer} limit.query - maximum number of results to return | ||
* @param {boolean} wrong.query - flag to force the server to return invalid response | ||
* @produces application/json | ||
* @returns {Array.<Pet>} 200 - pet response | ||
* @returns {Error.model} default - unexpected error | ||
*/ | ||
app.get( | ||
'/pets', | ||
(req, res) => { | ||
const { wrong } = req.query; | ||
if (wrong) { | ||
res.status(200).json(wrongPets); | ||
} else { | ||
res.status(200).json(pets); | ||
} | ||
}, | ||
); | ||
/** | ||
* @route GET /test-valid-input | ||
* @summary Test valid input | ||
* @group test - Everything about tests | ||
* @param {Input.model} body.body.required | ||
* @returns {Output.model} 200 - Successful operation | ||
* @returns {Error.model} 404 - Error message | ||
*/ | ||
app.get('/test-valid-input', (req, res) => { | ||
const validInputModel = { name: 'Name is required' }; | ||
/** | ||
* @route POST /pets | ||
* @summary Creates a new pet in the store. Duplicates are allowed | ||
* @param {NewPet.model} body.body.required - Pet to add to the store | ||
* @produces application/json | ||
* @returns {Pet.model} 200 - pet response | ||
* @returns {Error.model} default - unexpected error | ||
*/ | ||
app.post( | ||
'/pets', | ||
(req, res) => { | ||
const { wrong } = req.query; | ||
if (wrong) { | ||
res.status(200).json({ ...req.body }); | ||
} else { | ||
res.status(200).json({ id: 7, ...req.body }); | ||
} | ||
}, | ||
); | ||
try { | ||
const result = validator.validateAPIInput(validInputModel, req); | ||
res.status(200).json(result); | ||
} catch (error) { | ||
res.status(404).json({ error }); | ||
} | ||
}); | ||
return app; | ||
}; | ||
/** | ||
* @route GET /test-valid-output | ||
* @summary Test valid endpoint | ||
* @group test - Everything about tests | ||
* @param {Input.model} body.body.required | ||
* @returns {Output.model} 200 - Successful operation | ||
* @returns {Error.model} 404 - Error message | ||
*/ | ||
app.get('/test-valid-output', (req, res) => { | ||
const validOutputModel = { name: 'Name is required', result: 'Valid result' }; | ||
try { | ||
const result = validator.validateAPIOutput(validOutputModel, req); | ||
res.status(200).json(result); | ||
} catch (error) { | ||
res.status(404).json({ error }); | ||
} | ||
}); | ||
module.exports = app; | ||
module.exports = { | ||
runServer, | ||
}; |
@@ -1,152 +0,68 @@ | ||
const MockExpress = require('mock-express'); | ||
const express = require('express'); | ||
const bodyParser = require('body-parser'); | ||
const validator = require('../..'); | ||
const app = MockExpress(); // notice there's no "new" | ||
const pets = [ | ||
{ id: 1, name: 'pet 1', tag: 'dog' }, | ||
{ id: 2, name: 'pet 2', tag: 'cat' }, | ||
{ id: 3, name: 'pet 3', tag: 'bird' }, | ||
{ id: 4, name: 'pet 4', tag: 'dog' }, | ||
{ id: 5, name: 'pet 5', tag: 'cat' }, | ||
{ id: 6, name: 'pet 6', tag: 'bird' }, | ||
]; | ||
const validatorOptions = { | ||
swaggerDefinition: { | ||
info: { | ||
// API informations (required) | ||
title: 'Hello World', // Title (required) | ||
version: '1.0.0', // Version (required) | ||
description: 'A sample API', // Description (optional) | ||
}, | ||
basePath: process.cwd(), | ||
}, | ||
apis: ['./test/yaml/**.js'], | ||
}; | ||
const wrongPets = [ | ||
{ id: 1, tag: 'dog' }, | ||
{ id: 2, tag: 'cat' }, | ||
{ id: 3, tag: 'bird' }, | ||
{ id: 4, tag: 'dog' }, | ||
{ id: 5, tag: 'cat' }, | ||
{ id: 6, tag: 'bird' }, | ||
]; | ||
validator.init(app, validatorOptions, 'yaml'); | ||
const runServer = async () => { | ||
const app = express(); | ||
app.use(bodyParser.urlencoded({ extended: true })); | ||
app.use(bodyParser.json()); | ||
/** | ||
* @swagger | ||
* /test-invalid-input: | ||
* post: | ||
* description: Test POST /test-invalid-input | ||
* tags: [Test] | ||
* produces: | ||
* - application/json | ||
* parameters: | ||
* - name: body | ||
* description: Input payload | ||
* required: true | ||
* type: object | ||
* schema: | ||
* - $ref: '#/definitions/Input' | ||
* responses: | ||
* 200: | ||
* description: successful operation | ||
*/ | ||
app.post('/test-invalid-input', (req, res) => { | ||
try { | ||
const result = validator.validateAPIInput({}, req); | ||
res.status(200).json(result); | ||
} catch (error) { | ||
res.status(404).json({ error }); | ||
} | ||
}); | ||
await validator.init(app, { | ||
validationEndpoint: '/test', | ||
validateRequests: true, | ||
validateResponses: true, | ||
format: 'yaml', | ||
yaml: { | ||
file: './test/yaml/api.yaml', | ||
}, | ||
}); | ||
/** | ||
* @swagger | ||
* /test-invalid-output: | ||
* get: | ||
* description: Test GET /test-invalid-output | ||
* tags: [Test] | ||
* produces: | ||
* - application/json | ||
* responses: | ||
* 200: | ||
* description: successful operation | ||
* schema: | ||
* $ref: '#/definitions/Output' | ||
*/ | ||
app.get('/test-invalid-output', (req, res) => { | ||
try { | ||
const result = validator.validateAPIOutput({}, req); | ||
res.status(200).json(result); | ||
} catch (error) { | ||
res.status(404).json({ error }); | ||
} | ||
}); | ||
app.get( | ||
'/pets', | ||
(req, res) => { | ||
const { wrong } = req.query; | ||
if (wrong) { | ||
res.status(200).json(wrongPets); | ||
} else { | ||
res.status(200).json(pets); | ||
} | ||
}, | ||
); | ||
/** | ||
* @swagger | ||
* /test-invalid-output-2: | ||
* get: | ||
* description: Test GET /test-invalid-output-2 | ||
* tags: [Test] | ||
* produces: | ||
* - application/json | ||
* responses: | ||
* 200: | ||
* description: successful operation | ||
* schema: | ||
* $ref: '#/definitions/Output' | ||
*/ | ||
app.get('/test-invalid-output-2', (req, res) => { | ||
const invalidOutputModel = { name: 'Name is required', result: 'Valid result', extra: 'no extra fields' }; | ||
app.post( | ||
'/pets', | ||
(req, res) => { | ||
const { wrong } = req.query; | ||
if (wrong) { | ||
res.status(200).json({ ...req.body }); | ||
} else { | ||
res.status(200).json({ id: 7, ...req.body }); | ||
} | ||
}, | ||
); | ||
try { | ||
const result = validator.validateAPIOutput(invalidOutputModel, req); | ||
res.status(200).json(result); | ||
} catch (error) { | ||
res.status(404).json({ error }); | ||
} | ||
}); | ||
return app; | ||
}; | ||
/** | ||
* @swagger | ||
* /test-valid-input: | ||
* post: | ||
* description: Test POST /test-valid-input | ||
* tags: [Test] | ||
* produces: | ||
* - application/json | ||
* parameters: | ||
* - name: body | ||
* description: Input payload | ||
* required: true | ||
* type: object | ||
* schema: | ||
* - $ref: '#/definitions/Input' | ||
* responses: | ||
* 200: | ||
* description: successful operation | ||
*/ | ||
app.post('/test-valid-input', (req, res) => { | ||
const validInputModel = { name: 'Name is required' }; | ||
try { | ||
const result = validator.validateAPIInput(validInputModel, req); | ||
res.status(200).json(result); | ||
} catch (error) { | ||
res.status(404).json({ error }); | ||
} | ||
}); | ||
/** | ||
* @swagger | ||
* /test-valid-output: | ||
* get: | ||
* description: Test GET /test-valid-output | ||
* tags: [Test] | ||
* produces: | ||
* - application/json | ||
* responses: | ||
* 200: | ||
* description: successful operation | ||
* schema: | ||
* $ref: '#/definitions/Output' | ||
*/ | ||
app.get('/test-valid-output', (req, res) => { | ||
const validOutputModel = { name: 'Name is required', result: 'Valid result' }; | ||
try { | ||
const result = validator.validateAPIOutput(validOutputModel, req); | ||
res.status(200).json(result); | ||
} catch (error) { | ||
res.status(404).json({ error }); | ||
} | ||
}); | ||
module.exports = app; | ||
module.exports = { | ||
runServer, | ||
}; |
@@ -1,44 +0,47 @@ | ||
const MockExpress = require('mock-express'); | ||
const validator = require('../..'); // diferent instance | ||
describe('init method', () => { | ||
it('should return an exeception when we don\'t send options or the app instance', () => { | ||
expect(() => { | ||
validator.init(); | ||
}).toThrow(); | ||
describe.skip('unit tests', () => { | ||
describe('sample', () => { | ||
it('should test that true === true', () => { | ||
expect(true).toBe(true); | ||
}); | ||
}); | ||
}); | ||
// describe('init method', () => { | ||
// it('should return an exeception when we don\'t send options or the app instance', () => { | ||
// expect(() => { | ||
// validator.init(); | ||
// }).toThrow(); | ||
// }); | ||
it('should return an exeception when we don\'t send params to validateAPIInput', () => { | ||
expect(() => { | ||
validator.validateAPIInput(); | ||
}).toThrow(); | ||
}); | ||
// it('should return an exeception when we don\'t send params to validateAPIInput', () => { | ||
// expect(() => { | ||
// validator.validateAPIInput(); | ||
// }).toThrow(); | ||
// }); | ||
it('should return an exeception when we don\'t send params to validateAPIOutput', () => { | ||
expect(() => { | ||
validator.validateAPIOutput(); | ||
}).toThrow(); | ||
}); | ||
// it('should return an exeception when we don\'t send params to validateAPIOutput', () => { | ||
// expect(() => { | ||
// validator.validateAPIOutput(); | ||
// }).toThrow(); | ||
// }); | ||
it('should return an exception when initializing validator with unrecognized format', () => { | ||
expect(() => { | ||
const app = MockExpress(); | ||
// it('should return an exception when initializing validator with unrecognized format', () => { | ||
// expect(() => { | ||
// const app = MockExpress(); | ||
const validatorOptions = { | ||
swaggerDefinition: { | ||
info: { | ||
// API informations (required) | ||
title: 'Hello World', // Title (required) | ||
version: '1.0.0', // Version (required) | ||
description: 'A sample API', // Description (optional) | ||
}, | ||
basePath: process.cwd(), | ||
}, | ||
apis: ['./test/yaml/**.js'], | ||
}; | ||
// const validatorOptions = { | ||
// swaggerDefinition: { | ||
// info: { | ||
// // API informations (required) | ||
// title: 'Hello World', // Title (required) | ||
// version: '1.0.0', // Version (required) | ||
// description: 'A sample API', // Description (optional) | ||
// }, | ||
// basePath: process.cwd(), | ||
// }, | ||
// apis: ['./test/yaml/**.js'], | ||
// }; | ||
validator.init(app, validatorOptions, 'wrong-format'); | ||
}).toThrow(); | ||
}); | ||
}); | ||
// validator.init(app, validatorOptions, 'wrong-format'); | ||
// }).toThrow(); | ||
// }); | ||
// }); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
54195
26
990
9
10
1
+ Addeddebug@^4.1.1
+ Addedjs-yaml@^3.13.1
+ Addedopenapi-enforcer@^1.10.1
+ Addedswagger2openapi@^6.0.2
+ Added@apidevtools/json-schema-ref-parser@9.0.9(transitive)
+ Added@babel/code-frame@7.24.2(transitive)
+ Added@babel/helper-validator-identifier@7.22.20(transitive)
+ Added@babel/highlight@7.24.2(transitive)
+ Added@babel/runtime@7.24.4(transitive)
+ Added@exodus/schemasafe@1.3.0(transitive)
+ Addedajv@5.5.26.12.6(transitive)
+ Addedansi-regex@5.0.1(transitive)
+ Addedansi-styles@3.2.14.3.0(transitive)
+ Addedappend-field@1.0.0(transitive)
+ Addedbetter-ajv-errors@0.6.7(transitive)
+ Addedbindings@1.5.0(transitive)
+ Addedbuffer-from@1.1.2(transitive)
+ Addedbusboy@0.2.14(transitive)
+ Addedcamelcase@5.3.1(transitive)
+ Addedchalk@2.4.2(transitive)
+ Addedcliui@6.0.08.0.1(transitive)
+ Addedco@4.6.0(transitive)
+ Addedcode-error-fragment@0.0.230(transitive)
+ Addedcolor-convert@1.9.32.0.1(transitive)
+ Addedcolor-name@1.1.31.1.4(transitive)
+ Addedconcat-stream@1.6.2(transitive)
+ Addedcore-js@3.37.0(transitive)
+ Addedcore-util-is@1.0.3(transitive)
+ Addeddeasync@0.1.29(transitive)
+ Addeddebug@4.3.4(transitive)
+ Addeddecamelize@1.2.0(transitive)
+ Addeddicer@0.2.5(transitive)
+ Addeddrange@1.1.1(transitive)
+ Addedemoji-regex@8.0.0(transitive)
+ Addedes6-promise@3.3.1(transitive)
+ Addedescalade@3.1.2(transitive)
+ Addedescape-string-regexp@1.0.5(transitive)
+ Addedexpress-openapi-validator@3.17.2(transitive)
+ Addedfast-deep-equal@1.1.03.1.3(transitive)
+ Addedfast-json-stable-stringify@2.1.0(transitive)
+ Addedfast-safe-stringify@2.1.1(transitive)
+ Addedfile-uri-to-path@1.0.0(transitive)
+ Addedfind-up@4.1.0(transitive)
+ Addedget-caller-file@2.0.5(transitive)
+ Addedgrapheme-splitter@1.0.4(transitive)
+ Addedhas-flag@3.0.0(transitive)
+ Addedhttp2-client@1.3.5(transitive)
+ Addedis-fullwidth-code-point@3.0.0(transitive)
+ Addedisarray@0.0.11.0.0(transitive)
+ Addedjs-tokens@4.0.0(transitive)
+ Addedjs-yaml@3.14.1(transitive)
+ Addedjson-schema-ref-parser@9.0.9(transitive)
+ Addedjson-schema-traverse@0.3.10.4.1(transitive)
+ Addedjson-to-ast@2.1.0(transitive)
+ Addedjsonpointer@4.1.0(transitive)
+ Addedleven@3.1.0(transitive)
+ Addedlocate-path@5.0.0(transitive)
+ Addedlodash.merge@4.6.2(transitive)
+ Addedlodash.uniq@4.5.0(transitive)
+ Addedlodash.zipobject@4.1.3(transitive)
+ Addedmedia-typer@1.1.0(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addedms@2.1.2(transitive)
+ Addedmulter@1.4.4(transitive)
+ Addednode-addon-api@1.7.2(transitive)
+ Addednode-fetch-h2@2.3.0(transitive)
+ Addednode-readfiles@0.2.0(transitive)
+ Addedoas-kit-common@1.0.8(transitive)
+ Addedoas-linter@3.2.2(transitive)
+ Addedoas-resolver@2.5.6(transitive)
+ Addedoas-schema-walker@1.1.5(transitive)
+ Addedoas-validator@4.0.8(transitive)
+ Addedobject-assign@4.1.1(transitive)
+ Addedono@7.1.3(transitive)
+ Addedopenapi-enforcer@1.23.0(transitive)
+ Addedp-limit@2.3.0(transitive)
+ Addedp-locate@4.1.0(transitive)
+ Addedp-try@2.2.0(transitive)
+ Addedpath-exists@4.0.0(transitive)
+ Addedpath-to-regexp@6.2.2(transitive)
+ Addedpicocolors@1.0.0(transitive)
+ Addedprocess-nextick-args@2.0.1(transitive)
+ Addedpunycode@2.3.1(transitive)
+ Addedrandexp@0.5.3(transitive)
+ Addedreadable-stream@1.1.142.3.8(transitive)
+ Addedreftools@1.1.9(transitive)
+ Addedregenerator-runtime@0.14.1(transitive)
+ Addedrequire-directory@2.1.1(transitive)
+ Addedrequire-main-filename@2.0.0(transitive)
+ Addedret@0.2.2(transitive)
+ Addedsafe-buffer@5.1.2(transitive)
+ Addedset-blocking@2.0.0(transitive)
+ Addedshould@13.2.3(transitive)
+ Addedshould-equal@2.0.0(transitive)
+ Addedshould-format@3.0.3(transitive)
+ Addedshould-type@1.4.0(transitive)
+ Addedshould-type-adaptors@1.1.0(transitive)
+ Addedshould-util@1.0.1(transitive)
+ Addedstreamsearch@0.1.2(transitive)
+ Addedstring-width@4.2.3(transitive)
+ Addedstring_decoder@0.10.311.1.1(transitive)
+ Addedstrip-ansi@6.0.1(transitive)
+ Addedsupports-color@5.5.0(transitive)
+ Addedswagger2openapi@6.2.3(transitive)
+ Addedtypedarray@0.0.6(transitive)
+ Addeduri-js@4.4.1(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
+ Addedwhich-module@2.0.1(transitive)
+ Addedwrap-ansi@6.2.07.0.0(transitive)
+ Addedxtend@4.0.2(transitive)
+ Addedy18n@4.0.35.0.8(transitive)
+ Addedyaml@1.10.2(transitive)
+ Addedyargs@15.4.117.7.2(transitive)
+ Addedyargs-parser@18.1.321.1.1(transitive)
- Removed@apidevtools/json-schema-ref-parser@9.1.2(transitive)