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

@oas-tools/core

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@oas-tools/core - npm Package Compare versions

Comparing version 3.0.1 to 3.0.2

2

package.json
{
"name": "@oas-tools/core",
"version": "3.0.1",
"version": "3.0.2",
"description": "OAS Tools core library",

@@ -5,0 +5,0 @@ "type": "module",

import _ from "lodash";
import { schema } from "../../utils/index.js";
import { OASBase, logger } from "@oas-tools/commons";

@@ -12,9 +13,15 @@

return new OASParams(oasFile, (req, res, next) => {
const methodParams = oasFile.paths[req.route.path]?.[req.method.toLowerCase()]?.parameters;
const oasRequest = oasFile.paths[req.route.path]?.[req.method.toLowerCase()];
const pathParams = oasFile.paths[req.route.path]?.parameters;
const methodParams = oasRequest?.parameters;
const params = _.merge(pathParams, methodParams);
const paramsObj = {};
let body = req.body;
if (oasRequest.requestBody) {
const contentType = Object.keys(oasRequest.requestBody.content)[0];
body = schema.parseBody(body, oasRequest.requestBody.content[contentType].schema);
}
Object.values(params).forEach((param) => paramsObj[param.name] = _getParameterValue(req, param));
res.defaultSend = res.send; // save original send for error handling
res.locals.oas = { params: paramsObj, body: req.body };
res.locals.oas = { params: paramsObj, body: body };
if(req.file || req.files && req.files.length > 0) res.locals.oas.files = [req.files, req.file].flat().filter((file) => file !== undefined);

@@ -21,0 +28,0 @@ next()

import { OASBase, errors, logger, validator } from "@oas-tools/commons";
import { commons } from "../../utils/index.js";
import { commons, schema as schemaUtils } from "../../utils/index.js";
import MIMEtype from "whatwg-mimetype";

@@ -23,5 +23,5 @@

const contentType = Object.keys(oasRequest.requestBody.content)[0];
const schema = oasRequest.requestBody.content[contentType].schema;
const schema = schemaUtils.parseSchema(oasRequest.requestBody.content[contentType].schema, "request");
const body = res.locals.oas.body;
/* On multipart requests insert files in body for validation */

@@ -52,7 +52,14 @@ if (contentType.toLocaleLowerCase() === 'multipart/form-data' && res.locals.oas.files) {

/* Check parameters */
const commonParams = oasFile.paths[req.route.path].parameters;
const methodParams = oasRequest.parameters ?? commonParams;
const parameters = commonParams ? [...new Set([...methodParams, ...commonParams])] : methodParams;
// Check for extraneous query params
const missingParams = Object.keys(req.query ?? {}).filter((qp) => !parameters?.filter((p) => p.in === "query").map((p) => p.name).includes(qp));
if (missingParams.length > 0) {
commons.handle(RequestValidationError, "Extraneous parameter found in request query:\n" + missingParams.map((p) => ` - Missing declaration for "${p}"`).join("\n"), config.strict);
}
// Validate against schema
if (res.locals.oas.params && Object.keys(res.locals.oas.params).length > 0) {
const commonParams = oasFile.paths[req.route.path].parameters;
const methodParams = oasRequest.parameters ?? commonParams;
const parameters = commonParams ? [...new Set([...methodParams, ...commonParams])] : methodParams;
parameters.forEach((param) => {

@@ -118,4 +125,5 @@ const value = res.locals.oas.params[param.name];

const schemaContentType = Object.keys(expectedResponse.content)[0];
const schema = expectedResponse.content[schemaContentType].schema;
const {validate, valid} = validator.validate(data, schema, oasFile.openapi);
const schema = schemaUtils.parseSchema(expectedResponse.content[schemaContentType].schema, "response");
const parsedData = schemaUtils.parseBody(data, schema);
const {validate, valid} = validator.validate(parsedData, schema, oasFile.openapi);

@@ -125,8 +133,7 @@ if (!valid) {

}
oldSend.call(res, contentType.essence === "application/json" ? JSON.stringify(data) : data);
}
} else {
logger.debug("Response content is not defined in the OAS Document for this response");
oldSend.call(res, contentType.essence === "application/json" ? JSON.stringify(data) : data);
}
oldSend.call(res, contentType.essence === "application/json" ? JSON.stringify(data) : data);
}

@@ -133,0 +140,0 @@ next();

@@ -17,2 +17,67 @@ import _ from 'lodash';

/**
* Parse the request body taking defaults into account
* @param {string} body - Request body.
* @param {string} schema - OAS schema declaration for request body.
*/
export function parseBody(body, schema) {
const bodyType = Array.isArray(body) ? 'array' : typeof body;
if (bodyType === 'array' && schema.type === "array") {
const newBody = body ?? [];
return newBody.map((item) => parseBody(item, schema.items));
} else if ((bodyType === 'object' || bodyType === "undefined") && schema.type === "object") {
const newBody = body ?? {};
// Parse properties
Object.keys(schema.properties ?? {}).map((field) =>
newBody[field] = parseBody(newBody[field], schema.properties[field])
);
// Parse additionalProperties
if (schema.additionalProperties) {
Object.keys(newBody)
.filter((field) => !Object.keys(schema.properties ?? {}).includes(field))
.map((field) => newBody[field] = parseBody(newBody[field], schema.additionalProperties));
}
return _.omitBy(newBody, _.isUndefined);
} else if (_.isUndefined(body)) {
return body ?? schema.default;
} else {
return body ?? (schema.default ?? null);
}
}
/**
* Parse schemas depending on the scope
* @param {string} schema - OAS Schema declaration.
* @param {string} scope - Scope, can be `request` or `response`.
*/
export function parseSchema(schema, scope) {
const newSchema = JSON.parse(JSON.stringify(schema));
if (schema.oneOf || schema.anyOf || schema.allOf) {
const keyword = Object.keys(schema)[0];
newSchema[keyword] = schema[keyword].map((sch) => parseSchema(sch, scope));
} else if (schema.not) {
newSchema.not = parseSchema(schema.not, scope);
} else if (schema.type === "array") {
newSchema.items = parseSchema(schema.items, scope);
} else if (schema.type === "object") {
Object.keys(schema.properties ?? {}).forEach((prop) => {
const requiredIdx = schema.required?.indexOf(prop);
if (scope === "request" && requiredIdx > -1 && schema.properties[prop].readOnly) {
newSchema.required.splice(requiredIdx, 1);
} else if (scope === "response" && requiredIdx > -1 && schema.properties[prop].writeOnly) {
newSchema.required.splice(requiredIdx, 1);
}
newSchema.properties[prop] = parseSchema(newSchema.properties[prop], scope);
});
}
return _.omitBy(newSchema, (i) => Array.isArray(i) && i.length === 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