swagger-generator-koa
Version:
Generate automatic swagger using joi validation.
112 lines (111 loc) • 4.56 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = __importDefault(require("lodash"));
const joi_1 = __importDefault(require("@hapi/joi"));
const validation_error_1 = __importDefault(require("./validation-error"));
const defaultOptions = {
contextRequest: false,
allowUnknownHeaders: true,
allowUnknownBody: true,
allowUnknownQuery: true,
allowUnknownParams: true,
allowUnknownCookies: true,
status: 400,
statusText: 'Bad Request'
};
let globalOptions = {};
// maps the corresponding request object to an `express-validation` option
const unknownMap = {
headers: 'allowUnknownHeaders',
body: 'allowUnknownBody',
query: 'allowUnknownQuery',
params: 'allowUnknownParams',
cookies: 'allowUnknownCookies'
};
class Validation {
validate(schema = {}, opt = {}) {
return (ctx, next) => __awaiter(this, void 0, void 0, function* () {
const errors = [];
const options = lodash_1.default.defaults({}, schema.options || {}, globalOptions, defaultOptions);
const requestInputType = ['headers', 'body', 'query', 'params', 'cookies'];
// tslint:disable-next-line:prefer-for-of
for (let index = 0; index < requestInputType.length; index++) {
const key = requestInputType[index];
const allowUnknown = options[unknownMap[key]];
const entireContext = options.contextRequest ? ctx.request : null;
if (schema[key]) {
const toValidateObj = key === 'body' ? ctx.request.body : ctx[key];
yield validate(errors, toValidateObj, schema[key], key, allowUnknown, entireContext);
}
}
if (errors.length !== 0) {
throw new validation_error_1.default(errors, options);
}
yield next();
});
}
}
/**
* validate checks the current `Request` for validations
* NOTE: mutates `request` in case the object is valid.
*/
function validate(errObj, request, schema, location, allowUnknown, context) {
return __awaiter(this, void 0, void 0, function* () {
if (!request || !schema) {
return;
}
const joiOptions = {
context: context || request,
allowUnknown,
abortEarly: false
};
const { error, value } = yield joi_1.default.object(schema).validate(request, joiOptions);
const errors = error;
if (!errors || errors.details.length === 0) {
lodash_1.default.assignIn(request, value); // joi responses are parsed into JSON
return;
}
// tslint:disable-next-line:no-shadowed-variable
errors.details.forEach((error) => {
const errorExists = lodash_1.default.find(errObj, (item) => {
if (item && item.field === error.path && item.location === location) {
item.messages.push(error.message);
item.types.push(error.type);
return item;
}
return;
});
if (!errorExists) {
errObj.push({
field: error.path,
location,
messages: [error.message],
types: [error.type]
});
}
});
return errObj;
});
}
exports.options = (opts) => {
if (!opts) {
globalOptions = {};
return;
}
globalOptions = lodash_1.default.defaults({}, globalOptions, opts);
};
const defaultValidation = new Validation();
module.exports = defaultValidation.validate.bind(defaultValidation);
module.exports.ValidationError = validation_error_1.default;
exports.default = Validation;