@dechamp/express-auto-route
Version:
An express auto route module which allows routes and middleware to be configured via config file.
77 lines (61 loc) • 1.84 kB
text/typescript
const path = require("path");
const joi = require("@hapi/joi");
const {sprintf} = require("sprintf-js");
import jsonSchemaValidator from "../../jsonSchema/jsonSchemaValidationService";
const MSG_SCHEMA_FAILED = "Failed json schema on %s, errors: %s";
const deref = require("json-schema-deref-sync");
export default class RouteResponseJsonSchemaValidator {
async callback(req, res, next) {
const {config: {route}} = req;
if (!route.hasOwnProperty("responseJsonSchema")) {
return next();
}
const origionalJson = res.json;
res.json = (data) => {
// We only needed to intercept the json data, now we can
// restore json back to the original for future calls.
res.json = origionalJson;
const error = this.validateData(route, data);
if (error) {
return next(error);
}
res.json(data);
};
next();
}
validateData(route, data) {
try {
joi.assert(
route,
joi.object().keys({
responseJsonSchema: joi.string().required(),
}).unknown(true),
);
const schema = this._buildResponseJsonSchema(
route.responseJsonSchema,
);
if (schema) {
const error = jsonSchemaValidator(schema, data);
if (error) {
return sprintf(MSG_SCHEMA_FAILED, "response", error)
.trim("\n");
}
}
}
catch (error) {
if (error.hasOwnProperty("details")) {
console.debug(
`Skipping route "${route.id}" due to ${error.details[0].message}`);
}
return error.message;
}
}
_buildResponseJsonSchema(responseJsonSchema) {
const querySchemaPath = path.join(
process.cwd(),
responseJsonSchema,
);
const schema = require(querySchemaPath);
return deref(schema);
}
}