Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

api-schema-builder

Package Overview
Dependencies
Maintainers
2
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

api-schema-builder - npm Package Compare versions

Comparing version 1.0.5 to 1.0.6

src/utils/createContentTypeHeaders.js

6

package.json
{
"name": "api-schema-builder",
"version": "1.0.5",
"version": "1.0.6",
"description": "build schema with validators for each endpoint",

@@ -63,4 +63,6 @@ "main": "src/index.js",

"eslint-plugin-standard": "^4.0.0",
"lodash.get": "^4.4.2",
"mocha": "^6.0.2",
"nyc": "^13.3.0"
"nyc": "^13.3.0",
"uuid": "^3.3.2"
},

@@ -67,0 +69,0 @@ "publishConfig": {

@@ -149,3 +149,3 @@

- Objects - it is important to set any objects with the property `type: object` inside your swagger file, although it isn't a must in the Swagger (OpenAPI) spec in order to validate it accurately with [ajv](https://www.npmjs.com/package/ajv) it must be marked as `object`
- Response validator - it support now only open api 2.
- Response validator does not support readOnly attribute

@@ -156,2 +156,4 @@ ## Open api 3 - known issues

so child with no discriminator cant point to other child with discriminator,
- Response validator support only application/json content type
- Response validator does not support links and writeOnly attribute

@@ -158,0 +160,0 @@ ## Running Tests

@@ -5,8 +5,10 @@ 'use strict';

schemaPreprocessor = require('./utils/schema-preprocessor'),
oas3 = require('./parsers/open-api3'),
oas2 = require('./parsers/open-api2'),
oai3 = require('./parsers/open-api3'),
oai2 = require('./parsers/open-api2'),
ajvUtils = require('./utils/ajv-utils'),
Ajv = require('ajv'),
sourceResolver = require('./utils/sourceResolver'),
Validators = require('./validators/index');
Validators = require('./validators/index'),
createContentTypeHeaders = require('./utils/createContentTypeHeaders'),
get = require('lodash.get');

@@ -47,3 +49,3 @@ const DEFAULT_SETTINGS = {

let responseValidator;
if (buildResponses){
if (buildResponses) {
responseValidator = buildResponseValidator(referenced, dereferenced, currentPath, parsedPath, currentMethod, options);

@@ -60,2 +62,3 @@ }

let requestSchema = {};
let localParameters = [];
let pathParameters = dereferenced.paths[currentPath].parameters || [];

@@ -65,3 +68,4 @@ const isOpenApi3 = dereferenced.openapi === '3.0.0';

if (isOpenApi3) {
requestSchema.body = oas3.buildRequestBodyValidation(dereferenced, referenced, currentPath, currentMethod, options);
requestSchema.body = oai3.buildRequestBodyValidation(dereferenced, referenced, currentPath, currentMethod, options);
localParameters = oai3.buildPathParameters(parameters, pathParameters);
} else {

@@ -78,12 +82,10 @@ let bodySchema = options.expectFormFieldsInBody

if (bodySchema.length > 0) {
const validatedBodySchema = oas2.getValidatedBodySchema(bodySchema);
requestSchema.body = oas2.buildRequestBodyValidation(validatedBodySchema, dereferenced.definitions, referenced,
const validatedBodySchema = oai2.getValidatedBodySchema(bodySchema);
requestSchema.body = oai2.buildRequestBodyValidation(validatedBodySchema, dereferenced.definitions, referenced,
currentPath, currentMethod, options);
}
localParameters = oai2.buildPathParameters(parameters, pathParameters);
}
let localParameters = parameters.filter(function (parameter) {
return parameter.in !== 'body';
}).concat(pathParameters);
if (localParameters.length > 0 || options.contentTypeValidation) {

@@ -98,18 +100,19 @@ requestSchema.parameters = buildParametersValidation(localParameters,

function buildResponseValidator(referenced, dereferenced, currentPath, parsedPath, currentMethod, options){
// support now only oas2
if (dereferenced.openapi === '3.0.0'){ return }
const responsesSchema = {};
const responses = dereferenced.paths[currentPath][currentMethod].responses;
let responsesSchema = {};
const isOpenApi3 = dereferenced.openapi === '3.0.0';
let responses = get(dereferenced, `paths[${currentPath}][${currentMethod}].responses`);
if (responses) {
Object.keys(responses).forEach(statusCode => {
let responseDereferenceSchema = responses[statusCode].schema;
let responseDereferenceHeaders = responses[statusCode].headers;
let contentTypes = dereferenced.paths[currentPath][currentMethod].produces || dereferenced.paths[currentPath].produces || dereferenced.produces;
let headersValidator = (responseDereferenceHeaders || contentTypes) ? buildHeadersValidation(responseDereferenceHeaders, contentTypes, options) : undefined;
let headersValidator, bodyValidator;
if (isOpenApi3) {
headersValidator = oai3.buildHeadersValidation(responses, statusCode, options);
bodyValidator = oai3.buildResponseBodyValidation(dereferenced, referenced,
currentPath, currentMethod, statusCode, options);
} else {
let contentTypes = dereferenced.paths[currentPath][currentMethod].produces || dereferenced.paths[currentPath].produces || dereferenced.produces;
headersValidator = oai2.buildHeadersValidation(responses, contentTypes, statusCode, options);
bodyValidator = oai2.buildResponseBodyValidation(responses,
dereferenced.definitions, referenced, currentPath, currentMethod, statusCode, options);
}
let bodyValidator = responseDereferenceSchema ? oas2.buildResponseBodyValidation(responseDereferenceSchema,
dereferenced.definitions, referenced, currentPath, currentMethod, options, statusCode) : undefined;
if (headersValidator || bodyValidator) {

@@ -126,10 +129,3 @@ responsesSchema[statusCode] = new Validators.ResponseValidator({

}
function createContentTypeHeaders(validate, contentTypes) {
if (!validate || !contentTypes) return;
return {
types: contentTypes
};
}
function buildParametersValidation(parameters, contentTypes, options) {

@@ -213,34 +209,2 @@ const defaultAjvOptions = {

function buildHeadersValidation(headers, contentTypes, options) {
const defaultAjvOptions = {
allErrors: true,
coerceTypes: 'array'
};
const ajvOptions = Object.assign({}, defaultAjvOptions, options.ajvConfigParams);
let ajv = new Ajv(ajvOptions);
ajvUtils.addCustomKeyword(ajv, options.formats, options.keywords);
var ajvHeadersSchema = {
title: 'HTTP headers',
type: 'object',
properties: {},
additionalProperties: true
};
if (headers) {
Object.keys(headers).forEach(key => {
let headerObj = Object.assign({}, headers[key]);
const headerName = key.toLowerCase();
delete headerObj.name;
delete headerObj.required;
ajvHeadersSchema.properties[headerName] = headerObj;
});
}
ajvHeadersSchema.content = createContentTypeHeaders(options.contentTypeValidation, contentTypes);
return new Validators.SimpleValidator(ajv.compile(ajvHeadersSchema));
}
module.exports = {

@@ -247,0 +211,0 @@ buildSchema,

const Validators = require('../validators'),
Ajv = require('ajv'),
ajvUtils = require('../utils/ajv-utils');
ajvUtils = require('../utils/ajv-utils'),
createContentTypeHeaders = require('../utils/createContentTypeHeaders'),
get = require('lodash.get');

@@ -9,5 +11,14 @@ module.exports = {

buildResponseBodyValidation,
buildRequestBodyValidation
buildRequestBodyValidation,
buildHeadersValidation,
buildPathParameters
};
function buildPathParameters(parameters, pathParameters) {
let localParameters = parameters.filter(function (parameter) {
return parameter.in !== 'body';
}).concat(pathParameters);
return localParameters;
}
function getValidatedBodySchema(bodySchema) {

@@ -38,2 +49,36 @@ let validatedBodySchema;

function buildHeadersValidation(responses, contentTypes, statusCode, options) {
let headers = get(responses, `[${statusCode}].headers`);
if (!headers && !contentTypes) return;
const defaultAjvOptions = {
allErrors: true,
coerceTypes: 'array'
};
const ajvOptions = Object.assign({}, defaultAjvOptions, options.ajvConfigParams);
let ajv = new Ajv(ajvOptions);
ajvUtils.addCustomKeyword(ajv, options.formats, options.keywords);
var ajvHeadersSchema = {
title: 'HTTP headers',
type: 'object',
properties: {},
additionalProperties: true
};
if (headers) {
Object.keys(headers).forEach(key => {
let headerObj = Object.assign({}, headers[key]);
const headerName = key.toLowerCase();
delete headerObj.name;
ajvHeadersSchema.properties[headerName] = headerObj;
});
}
ajvHeadersSchema.content = createContentTypeHeaders(options.contentTypeValidation, contentTypes);
return new Validators.SimpleValidator(ajv.compile(ajvHeadersSchema));
}
function buildAjvValidator(ajvConfigBody, formats, keywords){

@@ -50,8 +95,11 @@ const defaultAjvOptions = {

function buildResponseBodyValidation(schema, swaggerDefinitions, originalSwagger, currentPath, currentMethod, options, statusCode) {
function buildResponseBodyValidation(responses, swaggerDefinitions, originalSwagger, currentPath, currentMethod, statusCode, options) {
let schema = get(responses, `[${statusCode}].schema`);
if (!schema) return;
let ajv = buildAjvValidator(options.ajvConfigBody, options.formats, options.keywords);
if (schema.discriminator) {
let schemaReference = originalSwagger.paths[currentPath][currentMethod].responses[statusCode].schema;
return buildInheritance(schema.discriminator, swaggerDefinitions, originalSwagger, currentPath, currentMethod, ajv, schemaReference);
let referenceName = originalSwagger.paths[currentPath][currentMethod].responses[statusCode].schema['$ref'];
return buildInheritance(schema.discriminator, swaggerDefinitions, originalSwagger, ajv, referenceName);
} else {

@@ -61,2 +109,3 @@ return new Validators.SimpleValidator(ajv.compile(schema));

}
function buildRequestBodyValidation(schema, swaggerDefinitions, originalSwagger, currentPath, currentMethod, options) {

@@ -66,4 +115,4 @@ let ajv = buildAjvValidator(options.ajvConfigBody, options.formats, options.keywords);

if (schema.discriminator) {
let schemaReference = originalSwagger.paths[currentPath][currentMethod].parameters.filter(function (parameter) { return parameter.in === 'body' })[0].schema;
return buildInheritance(schema.discriminator, swaggerDefinitions, originalSwagger, currentPath, currentMethod, ajv, schemaReference);
let referenceName = originalSwagger.paths[currentPath][currentMethod].parameters.filter(function (parameter) { return parameter.in === 'body' })[0].schema['$ref'];
return buildInheritance(schema.discriminator, swaggerDefinitions, originalSwagger, ajv, referenceName);
} else {

@@ -74,3 +123,3 @@ return new Validators.SimpleValidator(ajv.compile(schema));

function buildInheritance(discriminator, dereferencedDefinitions, swagger, currentPath, currentMethod, ajv, schemaReference = {}) {
function buildInheritance(discriminator, dereferencedDefinitions, swagger, ajv, referenceName) {
var inheritsObject = {

@@ -84,3 +133,3 @@ inheritance: []

swagger.definitions[key].allOf.forEach(element => {
if (element['$ref'] && element['$ref'] === schemaReference['$ref']) {
if (element['$ref'] && element['$ref'] === referenceName) {
inheritsObject[key] = ajv.compile(dereferencedDefinitions[key]);

@@ -87,0 +136,0 @@ inheritsObject.inheritance.push(key);

@@ -1,2 +0,1 @@

const Validators = require('../validators/index'),

@@ -6,16 +5,42 @@ Ajv = require('ajv'),

ajvUtils = require('../utils/ajv-utils'),
{ Node } = require('../data_structures/tree');
{ Node } = require('../data_structures/tree'),
createContentTypeHeaders = require('../utils/createContentTypeHeaders'),
get = require('lodash.get');
const OAI3_RESPONSE_CONTENT_TYPE = 'application/json';
module.exports = {
buildRequestBodyValidation
buildRequestBodyValidation,
buildResponseBodyValidation,
buildHeadersValidation,
buildPathParameters
};
function buildRequestBodyValidation(dereferenced, originalSwagger, currentPath, currentMethod, { ajvConfigBody, formats, keywords }) {
if (!dereferenced.paths[currentPath][currentMethod].requestBody) {
return;
}
const bodySchemaV3 = dereferenced.paths[currentPath][currentMethod].requestBody.content['application/json'].schema;
function buildRequestBodyValidation(dereferenced, referenced, currentPath, currentMethod, options) {
const requestPath = `paths[${currentPath}][${currentMethod}].requestBody.content[${OAI3_RESPONSE_CONTENT_TYPE}].schema`;
let dereferencedBodySchema = get(dereferenced, requestPath);
let referencedBodySchema = get(referenced, requestPath);
return handleBodyValidation(dereferenced, referenced, currentPath, currentMethod,
dereferencedBodySchema, referencedBodySchema, options);
}
function buildResponseBodyValidation(dereferenced, referenced, currentPath, currentMethod, statusCode, options) {
const responsePath = `paths[${currentPath}][${currentMethod}].responses[${statusCode}].content[${OAI3_RESPONSE_CONTENT_TYPE}].schema`;
let dereferencedBodySchema = get(dereferenced, responsePath);
let referencedBodySchema = get(referenced, responsePath);
return handleBodyValidation(dereferenced, referenced, currentPath, currentMethod,
dereferencedBodySchema, referencedBodySchema, options);
}
function handleBodyValidation(dereferenced, referenced, currentPath, currentMethod,
dereferencedBodySchema, referencedBodySchema, { ajvConfigBody, formats, keywords }){
if (!dereferencedBodySchema || !referencedBodySchema) return;
const defaultAjvOptions = {
allErrors: true
};
const ajvOptions = Object.assign({}, defaultAjvOptions, ajvConfigBody);

@@ -26,15 +51,68 @@ let ajv = new Ajv(ajvOptions);

if (bodySchemaV3.discriminator) {
return buildV3Inheritance(dereferenced, originalSwagger, currentPath, currentMethod, ajv);
if (dereferencedBodySchema.discriminator) {
let referencedSchemas = referenced.components.schemas;
let dereferencedSchemas = dereferenced.components.schemas;
let referenceName = referencedBodySchema['$ref'];
return buildV3Inheritance(referencedSchemas, dereferencedSchemas, currentPath, currentMethod, ajv, referenceName);
} else {
return new Validators.SimpleValidator(ajv.compile(bodySchemaV3));
return new Validators.SimpleValidator(ajv.compile(dereferencedBodySchema));
}
}
function buildV3Inheritance(dereferencedDefinitions, swagger, currentPath, currentMethod, ajv) {
function buildPathParameters(parameters, pathParameters) {
let allParameters = [].concat(parameters, pathParameters);
let localParameters = allParameters.map(handleSchema);
return localParameters;
}
function handleSchema(data) {
let clonedData = cloneDeep(data);
let schema = data.schema;
if (schema) {
delete clonedData['schema'];
Object.keys(schema).forEach(key => {
clonedData[key] = schema[key];
});
}
return clonedData;
}
function buildHeadersValidation(responses, statusCode, { ajvConfigParams, formats, keywords, contentTypeValidation }) {
let headers = get(responses, `[${statusCode}].headers`);
if (!headers) return;
const defaultAjvOptions = {
allErrors: true,
coerceTypes: 'array'
};
const ajvOptions = Object.assign({}, defaultAjvOptions, ajvConfigParams);
let ajv = new Ajv(ajvOptions);
ajvUtils.addCustomKeyword(ajv, formats, keywords);
var ajvHeadersSchema = {
title: 'HTTP headers',
type: 'object',
properties: {},
required: [],
additionalProperties: true
};
Object.keys(headers).forEach(key => {
let headerObj = Object.assign({}, headers[key].schema);
const headerName = key.toLowerCase();
delete headerObj.name;
delete headerObj.required;
ajvHeadersSchema.properties[headerName] = headerObj;
});
ajvHeadersSchema.content = createContentTypeHeaders(contentTypeValidation, OAI3_RESPONSE_CONTENT_TYPE);
return new Validators.SimpleValidator(ajv.compile(ajvHeadersSchema));
}
function buildV3Inheritance(referencedSchemas, dereferencedSchemas, currentPath, currentMethod, ajv, referenceName) {
const RECURSIVE__MAX_DEPTH = 20;
const bodySchema = swagger.paths[currentPath][currentMethod].requestBody.content['application/json'];
const schemas = swagger.components.schemas;
const dereferencedSchemas = dereferencedDefinitions.components.schemas;
const rootKey = bodySchema.schema['$ref'].split('/components/schemas/')[1];
const rootKey = referenceName.split('/components/schemas/')[1];
const tree = new Node();

@@ -51,3 +129,3 @@ function getKeyFromRef(ref) {

const discriminator = dereferencedSchemas[refValue].discriminator,
currentSchema = schemas[refValue],
currentSchema = referencedSchemas[refValue],
currentDereferencedSchema = dereferencedSchemas[refValue];

@@ -54,0 +132,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc