validata
Version:
Type safe data validation and sanitization
102 lines • 4.54 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.maybeAsObject = exports.asObject = exports.maybeObject = exports.isObject = void 0;
const common_1 = require("./common");
const types_1 = require("./types");
class Generic {
constructor() {
this.check = (value) => {
return typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date);
};
this.convert = (options) => (value) => {
if (typeof value === 'string' && value[0] === '{' && value[value.length - 1] === '}') {
try {
return JSON.parse(value, options === null || options === void 0 ? void 0 : options.reviver);
}
catch (_a) {
return undefined;
}
}
return undefined;
};
this.process = (contract, target, path) => {
const issues = [];
Object.keys(target).forEach((key) => {
if (!(key in contract)) {
issues.push(types_1.Issue.forPath([...path, key], target[key], 'unexpected-property'));
}
});
const output = {};
const keys = Object.keys(contract);
keys.forEach((key) => {
const check = contract[key];
const value = target[key];
const childResult = check.process(value, [...path, key]);
if ((0, types_1.isIssue)(childResult)) {
issues.push(...childResult.issues);
return;
}
if (childResult.value === undefined && !(key in target))
return;
if (childResult) {
output[key] = childResult.value;
}
else {
output[key] = value;
}
});
return issues.length ? { issues } : { value: output };
};
this.coerce = (options) => (next) => (value, path) => {
if (!options)
return next(value, path);
let coerced = Object.assign({}, value);
if (!options.contract)
return next(coerced, path);
const ignoredProperties = {};
if (options.stripExtraProperties || options.ignoreExtraProperties) {
const allowedProperties = new Set(Object.keys(options.contract));
Object.keys(coerced).forEach((key) => {
if (allowedProperties.has(key))
return;
ignoredProperties[key] = coerced[key];
delete coerced[key];
});
}
const result = this.process(options.contract, coerced, path);
if ((0, types_1.isIssue)(result))
return result;
if (result) {
coerced = result.value;
if (options.ignoreExtraProperties) {
Object.keys(ignoredProperties).forEach((key) => {
coerced[key] = ignoredProperties[key];
});
}
}
return next(coerced, path);
};
this.validate = (value, path, options) => (0, common_1.basicValidation)(value, path, options);
}
}
const isObject = (contract, options) => {
const generic = new Generic();
return (0, common_1.createIsCheck)('object', generic.check, generic.coerce, generic.validate)(Object.assign(Object.assign({}, options), { contract }));
};
exports.isObject = isObject;
const maybeObject = (contract, options) => {
const generic = new Generic();
return (0, common_1.createMaybeCheck)('object', generic.check, generic.coerce, generic.validate)(Object.assign(Object.assign({}, options), { contract }));
};
exports.maybeObject = maybeObject;
const asObject = (contract, options) => {
const generic = new Generic();
return (0, common_1.createAsCheck)('object', generic.check, generic.convert(options), generic.coerce, generic.validate)(Object.assign(Object.assign({}, options), { contract }));
};
exports.asObject = asObject;
const maybeAsObject = (contract, options) => {
const generic = new Generic();
return (0, common_1.createMaybeAsCheck)('object', generic.check, generic.convert(options), generic.coerce, generic.validate)(Object.assign(Object.assign({}, options), { contract }));
};
exports.maybeAsObject = maybeAsObject;
//# sourceMappingURL=object.js.map
;