swagger-typed-express-docs
Version:
Simple express runtime parser and documentation swagger generator with 100% support of Typescript static types
373 lines (372 loc) • 17.2 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTSchemaValidator = exports.convertSchemaToYupValidationObject = exports.normalizeYupError = void 0;
var yup = __importStar(require("yup"));
var utils_1 = require("./utils");
var tSchemaDiscriminator_1 = require("./tSchemaDiscriminator");
var normalizeYupError = function (obj) {
var _a, _b, _c, _d, _e;
if (!obj)
return undefined;
var yErrObj = JSON.parse(JSON.stringify(obj));
var errorsList = ((_b = (_a = yErrObj.inner) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0
? (_c = yErrObj.inner) === null || _c === void 0 ? void 0 : _c.map(function (i) { return ({ path: i === null || i === void 0 ? void 0 : i.path, errors: i === null || i === void 0 ? void 0 : i.errors }); })
: (_d = yErrObj.errors) === null || _d === void 0 ? void 0 : _d.map(function (i) { return ({ path: '', errors: i }); });
var niceYErrObj = ((_e = errorsList === null || errorsList === void 0 ? void 0 : errorsList.length) !== null && _e !== void 0 ? _e : 0) > 0
?
errorsList
: [{ errors: [yErrObj], path: '' }];
return niceYErrObj;
};
exports.normalizeYupError = normalizeYupError;
var convertSchemaToYupValidationObject = function (schema, extra) {
var _a;
var transformTypeMode = (_a = extra === null || extra === void 0 ? void 0 : extra.transformTypeMode) !== null && _a !== void 0 ? _a : 'decode';
var yupValidator = yup;
if ((schema === null || schema === void 0 ? void 0 : schema.type) === 'array') {
yupValidator = yupValidator.array().of((0, exports.convertSchemaToYupValidationObject)(schema.items, extra));
}
else if ((schema === null || schema === void 0 ? void 0 : schema.type) === 'object') {
yupValidator = yupValidator
.object((0, utils_1.mapEntries)(function (_a) {
var _b = __read(_a, 2), k = _b[0], v = _b[1];
var yupValidator = (0, exports.convertSchemaToYupValidationObject)(v, extra);
if (v.required &&
yupValidator.required) {
yupValidator = yupValidator.required();
}
return [k, yupValidator];
}, schema.properties))
.default(undefined)
.test({
name: 'non-nullable-object',
message: function (d) {
return [
"".concat(d.path, " must be a non-nullable, "),
"but the final value was: `".concat(JSON.stringify(d.value), "`."),
].join('');
},
test: function (value) {
var isDefaultValueApplied = value === undefined;
if (isDefaultValueApplied && schema.required) {
return false;
}
return true;
},
});
}
else if ((schema === null || schema === void 0 ? void 0 : schema.type) === 'boolean') {
yupValidator = yup.mixed().test({
name: 'strict-custom-boolean',
message: function (d) {
return [
"".concat(d.path, " must be a `boolean` type, "),
"but the final value was: `".concat(JSON.stringify(d.value), "`."),
].join('');
},
test: function (value) {
if (schema.required === false && (value === null || value === undefined))
return true;
if (typeof value === 'boolean')
return true;
return false;
},
});
}
else if ((schema === null || schema === void 0 ? void 0 : schema.type) === 'number') {
yupValidator = yup
.mixed()
.test({
name: 'strict-custom-number',
message: function (d) {
return [
"".concat(d.path, " must be a `number` type, "),
"but the final value was: `".concat(JSON.stringify(d.value), "`."),
].join('');
},
test: function (value) {
if (schema.required === false && (value === null || value === undefined))
return true;
if (typeof value === 'number' && !isNaN(value))
return true;
return false;
},
});
}
else if ((schema === null || schema === void 0 ? void 0 : schema.type) === 'string') {
yupValidator = yup.mixed().test({
name: 'strict-custom-string',
message: function (d) {
return [
"".concat(d.path, " must be a `string` type, "),
"but the final value was: `".concat(JSON.stringify(d.value), "`."),
].join('');
},
test: function (value) {
if (schema.required === false && (value === null || value === undefined))
return true;
if (typeof value === 'string')
return true;
return false;
},
});
}
else if ((schema === null || schema === void 0 ? void 0 : schema.type) === 'transformType') {
yupValidator = yup.mixed();
yupValidator = yupValidator
.transform(function (value) {
if (schema.required === false && (value === null || value === undefined)) {
return value;
}
try {
if (transformTypeMode === 'decode' || transformTypeMode === 'keep-decoded') {
var transformedItem = (0, exports.convertSchemaToYupValidationObject)(schema.encodedTSchema, __assign({}, extra)).validateSync(value, { abortEarly: false });
if (transformTypeMode === 'keep-decoded')
return transformedItem;
var newValue = schema.syncDecoder(transformedItem);
(0, exports.convertSchemaToYupValidationObject)(schema.decodedTSchema, __assign(__assign({}, extra), { transformTypeMode: 'keep-encoded' })).validateSync(newValue, { abortEarly: false });
return newValue;
}
else if (transformTypeMode === 'encode' || transformTypeMode === 'keep-encoded') {
var transformedItem = (0, exports.convertSchemaToYupValidationObject)(schema.decodedTSchema, __assign({}, extra)).validateSync(value, { abortEarly: false });
if (transformTypeMode === 'keep-encoded')
return transformedItem;
var newValue = schema.syncEncoder(transformedItem);
(0, exports.convertSchemaToYupValidationObject)(schema.encodedTSchema, __assign(__assign({}, extra), { transformTypeMode: 'keep-decoded' })).validateSync(newValue, { abortEarly: false });
return newValue;
}
else {
throw new Error('invalid transformTypeMode');
}
}
catch (err) {
return err;
}
})
.test({
name: "custom-transform-type",
test: function (value) {
var _a;
if (value instanceof Error)
return this.createError({ path: this.path, message: (_a = value === null || value === void 0 ? void 0 : value.message) !== null && _a !== void 0 ? _a : '' });
return true;
},
});
}
else if ((schema === null || schema === void 0 ? void 0 : schema.type) === 'any') {
yupValidator = yupValidator.mixed();
}
else if ((schema === null || schema === void 0 ? void 0 : schema.type) === 'hashMap') {
yupValidator = yup;
var objValueValidator_1 = (0, exports.convertSchemaToYupValidationObject)(schema.property, extra);
if (schema.property.required &&
yupValidator.required) {
yupValidator = yupValidator.required();
}
yupValidator = yupValidator.lazy(function (v) {
if (schema.required === false && (v === null || v === undefined)) {
return yup.object({}).nullable();
}
if (v === null || v === undefined) {
return yup.object({}).required();
}
return yup.object((0, utils_1.mapEntries)(function (_a) {
var _b = __read(_a, 1), k = _b[0];
return [k, objValueValidator_1];
}, v));
});
}
else if ((schema === null || schema === void 0 ? void 0 : schema.type) === 'enum') {
yupValidator = yupValidator.mixed().test({
name: 'strict-custom-enum',
message: function (d) {
return [
"".concat(d.path, " must be one of ["),
schema.options.join(' | '),
"] type, but the final value was: `".concat(JSON.stringify(d.value), "`."),
].join('');
},
test: function (value) {
if (schema.required === false && (value === null || value === undefined))
return true;
if (schema.options.includes(value))
return true;
return false;
},
});
}
else if ((schema === null || schema === void 0 ? void 0 : schema.type) === 'oneOf') {
var extraNoAsyncValidation_1 = __assign({}, extra);
var validators_1 = schema.options.map(function (o) {
return (0, exports.convertSchemaToYupValidationObject)(o, extraNoAsyncValidation_1);
});
yupValidator = yupValidator
.mixed()
.transform(function (value, ogValue, context) {
if (schema.required === false && (value === null || value === undefined)) {
return value;
}
var maybeMatchedItem = (function () {
var _a;
var enumDiscriminatorKey = (0, tSchemaDiscriminator_1.getOneOfEnumDiscriminator)(schema);
if (enumDiscriminatorKey) {
if (value && typeof value === 'object' && enumDiscriminatorKey in value) {
var discriminatorValue_1 = value[enumDiscriminatorKey];
var matchingSchemaIndex = schema.options.findIndex(function (option) {
var _a;
return option.type === 'object' &&
((_a = option.properties[enumDiscriminatorKey]) === null || _a === void 0 ? void 0 : _a.type) === 'enum' &&
option.properties[enumDiscriminatorKey].options.includes(discriminatorValue_1);
});
var matchingValidator_1 = (_a = validators_1[matchingSchemaIndex]) !== null && _a !== void 0 ? _a : validators_1[0];
return (0, utils_1.validateUntilFirstSuccess)([
function () { return matchingValidator_1.validateSync(value, { abortEarly: false }); },
]);
}
}
return (0, utils_1.validateUntilFirstSuccess)(schema.options.map(function (_o, index) {
return function () {
return validators_1[index].validateSync(value, {
abortEarly: false,
});
};
}));
})();
if (maybeMatchedItem.status === 'rejected') {
try {
var allOptionSchemaErrors = maybeMatchedItem.reasons
.map(function (reason) { return (0, exports.normalizeYupError)(reason); })
.filter(utils_1.notNullable);
var errMsg = {
message: 'data does not match any of allowed schemas',
currentValue: value,
allOptionSchemaErrors: allOptionSchemaErrors,
};
var err = new Error('invalid one of');
err._data = errMsg;
return err;
}
catch (err) {
return err;
}
}
return maybeMatchedItem.data;
})
.test({
name: 'one-of-schema',
test: function (transformedValue, conf) {
var _a, _b;
if (transformedValue instanceof Error) {
return this.createError({
path: this.path,
message: (_b = (_a = transformedValue._data) !== null && _a !== void 0 ? _a : transformedValue.message) !== null && _b !== void 0 ? _b : '',
});
}
return true;
},
});
}
else if ((schema === null || schema === void 0 ? void 0 : schema.type) === 'lazy') {
yupValidator = yupValidator.lazy(function () {
return (0, exports.convertSchemaToYupValidationObject)(schema.getSchema(), extra);
});
}
else {
throw new Error("unsupported type ".concat(schema === null || schema === void 0 ? void 0 : schema.type));
}
if (schema.required === false && yupValidator.nullable) {
yupValidator = yupValidator.nullable();
}
if (schema.validator) {
yupValidator = yupValidator.test({
name: 'custom-validation',
test: function (value) {
var _a, _b;
if (schema.required === false && (value === null || value === undefined))
return true;
try {
if (value instanceof Error)
return false;
(_a = schema.validator) === null || _a === void 0 ? void 0 : _a.call(schema, value);
}
catch (err) {
return this.createError({ path: this.path, message: (_b = err === null || err === void 0 ? void 0 : err.message) !== null && _b !== void 0 ? _b : '' });
}
return true;
},
});
}
return yupValidator;
};
exports.convertSchemaToYupValidationObject = convertSchemaToYupValidationObject;
var getTSchemaValidator = function (tSchema, extra) {
var convertor = (0, exports.convertSchemaToYupValidationObject)(tSchema, extra);
var validate = function (value, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.stripUnknown, stripUnknown = _c === void 0 ? true : _c, _d = _b.abortEarly, abortEarly = _d === void 0 ? false : _d;
var transformedValue = convertor.validateSync(value, { abortEarly: abortEarly, stripUnknown: stripUnknown });
return transformedValue;
};
var isValid = function (value) {
try {
validate(value);
return true;
}
catch (err) {
return false;
}
};
var validateSync = validate;
var isValidSync = isValid;
return { validate: validate, validateSync: validateSync, isValid: isValid, isValidSync: isValidSync };
};
exports.getTSchemaValidator = getTSchemaValidator;