1123 lines
50 KiB
JavaScript
1123 lines
50 KiB
JavaScript
/*!
|
||
* TSBuffer Validator v2.1.1
|
||
* -----------------------------------------
|
||
* MIT LICENSE
|
||
* KingWorks (C) Copyright 2022
|
||
* https://github.com/k8w/tsbuffer-validator
|
||
*/
|
||
'use strict';
|
||
|
||
Object.defineProperty(exports, '__esModule', { value: true });
|
||
|
||
require('k8w-extend-native');
|
||
var tslib = require('tslib');
|
||
var tsbufferSchema = require('tsbuffer-schema');
|
||
|
||
var ProtoHelper = /** @class */ (function () {
|
||
function ProtoHelper(proto) {
|
||
//this._schemaWithUuids = [];
|
||
this._uuidIndex = 1;
|
||
//this._unionPropertiesCache = {};
|
||
//this._flatInterfaceSchemaCache = {};
|
||
this.proto = proto;
|
||
}
|
||
/** 将ReferenceTypeSchema层层转换为它最终实际引用的类型 */
|
||
ProtoHelper.prototype.parseReference = function (schema) {
|
||
// Reference
|
||
if (schema.type === tsbufferSchema.SchemaType.Reference) {
|
||
var parsedSchema = this.proto[schema.target];
|
||
if (!parsedSchema) {
|
||
throw new Error("Cannot find reference target: ".concat(schema.target));
|
||
}
|
||
if (this.isTypeReference(parsedSchema)) {
|
||
return this.parseReference(parsedSchema);
|
||
}
|
||
else {
|
||
return parsedSchema;
|
||
}
|
||
}
|
||
// IndexedAccess
|
||
else if (schema.type === tsbufferSchema.SchemaType.IndexedAccess) {
|
||
if (!this.isInterface(schema.objectType)) {
|
||
throw new Error("Error objectType: ".concat(schema.objectType.type));
|
||
}
|
||
// find prop item
|
||
var flat = this.getFlatInterfaceSchema(schema.objectType);
|
||
var propItem = flat.properties.find(function (v) { return v.name === schema.index; });
|
||
var propType = void 0;
|
||
if (propItem) {
|
||
propType = propItem.type;
|
||
}
|
||
else {
|
||
if (flat.indexSignature) {
|
||
propType = flat.indexSignature.type;
|
||
}
|
||
else {
|
||
throw new Error("Error index: ".concat(schema.index));
|
||
}
|
||
}
|
||
// optional -> | undefined
|
||
if (propItem && propItem.optional && // 引用的字段是optional
|
||
(propItem.type.type !== tsbufferSchema.SchemaType.Union // 自身不为Union
|
||
// 或自身为Union,但没有undefined成员条件
|
||
|| propItem.type.members.findIndex(function (v) { return v.type.type === tsbufferSchema.SchemaType.Literal && v.type.literal === undefined; }) === -1)) {
|
||
propType = {
|
||
type: tsbufferSchema.SchemaType.Union,
|
||
members: [
|
||
{ id: 0, type: propType },
|
||
{
|
||
id: 1,
|
||
type: {
|
||
type: tsbufferSchema.SchemaType.Literal,
|
||
literal: undefined
|
||
}
|
||
}
|
||
]
|
||
};
|
||
}
|
||
return this.isTypeReference(propType) ? this.parseReference(propType) : propType;
|
||
}
|
||
else if (schema.type === tsbufferSchema.SchemaType.Keyof) {
|
||
var flatInterface = this.getFlatInterfaceSchema(schema.target);
|
||
return {
|
||
type: tsbufferSchema.SchemaType.Union,
|
||
members: flatInterface.properties.map(function (v, i) { return ({
|
||
id: i,
|
||
type: {
|
||
type: tsbufferSchema.SchemaType.Literal,
|
||
literal: v.name
|
||
}
|
||
}); })
|
||
};
|
||
}
|
||
else {
|
||
return schema;
|
||
}
|
||
};
|
||
ProtoHelper.prototype.isInterface = function (schema, excludeReference) {
|
||
if (excludeReference === void 0) { excludeReference = false; }
|
||
if (!excludeReference && this.isTypeReference(schema)) {
|
||
var parsed = this.parseReference(schema);
|
||
return this.isInterface(parsed, excludeReference);
|
||
}
|
||
else {
|
||
return schema.type === tsbufferSchema.SchemaType.Interface || this.isMappedType(schema) && this.parseMappedType(schema).type === tsbufferSchema.SchemaType.Interface;
|
||
}
|
||
};
|
||
ProtoHelper.prototype.isMappedType = function (schema) {
|
||
return schema.type === tsbufferSchema.SchemaType.Pick ||
|
||
schema.type === tsbufferSchema.SchemaType.Partial ||
|
||
schema.type === tsbufferSchema.SchemaType.Omit ||
|
||
schema.type === tsbufferSchema.SchemaType.Overwrite;
|
||
};
|
||
ProtoHelper.prototype.isTypeReference = function (schema) {
|
||
return schema.type === tsbufferSchema.SchemaType.Reference || schema.type === tsbufferSchema.SchemaType.IndexedAccess || schema.type === tsbufferSchema.SchemaType.Keyof;
|
||
};
|
||
ProtoHelper.prototype._getSchemaUuid = function (schema) {
|
||
var schemaWithUuid = schema;
|
||
if (!schemaWithUuid.uuid) {
|
||
//schemaWithUuid.uuid = this._schemaWithUuids.push(schemaWithUuid);
|
||
schemaWithUuid.uuid = this._uuidIndex;
|
||
this._uuidIndex++;
|
||
}
|
||
return schemaWithUuid.uuid;
|
||
};
|
||
ProtoHelper.prototype.getUnionProperties = function (schema) {
|
||
return this._addUnionProperties([], schema.members.map(function (v) { return v.type; }));;
|
||
|
||
// var uuid = this._getSchemaUuid(schema);
|
||
// if (!this._unionPropertiesCache[uuid]) {
|
||
// this._unionPropertiesCache[uuid] = this._addUnionProperties([], schema.members.map(function (v) { return v.type; }));
|
||
// }
|
||
// return this._unionPropertiesCache[uuid];
|
||
};
|
||
/**
|
||
* unionProperties: 在Union或Intersection类型中,出现在任意member中的字段
|
||
*/
|
||
ProtoHelper.prototype._addUnionProperties = function (unionProperties, schemas) {
|
||
for (var i = 0, len = schemas.length; i < len; ++i) {
|
||
var schema = this.parseReference(schemas[i]);
|
||
// Interface及其Ref 加入interfaces
|
||
if (this.isInterface(schema)) {
|
||
var flat = this.getFlatInterfaceSchema(schema);
|
||
flat.properties.forEach(function (v) {
|
||
unionProperties.binaryInsert(v.name, true);
|
||
});
|
||
if (flat.indexSignature) {
|
||
var key = "[[".concat(flat.indexSignature.keyType, "]]");
|
||
unionProperties.binaryInsert(key, true);
|
||
}
|
||
}
|
||
// Intersection/Union 递归合并unionProperties
|
||
else if (schema.type === tsbufferSchema.SchemaType.Intersection || schema.type === tsbufferSchema.SchemaType.Union) {
|
||
this._addUnionProperties(unionProperties, schema.members.map(function (v) { return v.type; }));
|
||
}
|
||
else if (this.isMappedType(schema)) {
|
||
this._addUnionProperties(unionProperties, [this.parseMappedType(schema)]);
|
||
}
|
||
}
|
||
return unionProperties;
|
||
};
|
||
/**
|
||
* 将unionProperties 扩展到 InterfaceTypeSchema中(optional的any类型)
|
||
* 以此来跳过对它们的检查(用于Intersection/Union)
|
||
*/
|
||
ProtoHelper.prototype.applyUnionProperties = function (schema, unionProperties) {
|
||
var newSchema = tslib.__assign(tslib.__assign({}, schema), { properties: schema.properties.slice() });
|
||
var _loop_1 = function (prop) {
|
||
if (prop === '[[String]]') {
|
||
newSchema.indexSignature = newSchema.indexSignature || {
|
||
keyType: tsbufferSchema.SchemaType.String,
|
||
type: { type: tsbufferSchema.SchemaType.Any }
|
||
};
|
||
}
|
||
else if (prop === '[[Number]]') {
|
||
newSchema.indexSignature = newSchema.indexSignature || {
|
||
keyType: tsbufferSchema.SchemaType.Number,
|
||
type: { type: tsbufferSchema.SchemaType.Any }
|
||
};
|
||
}
|
||
else if (!schema.properties.find(function (v) { return v.name === prop; })) {
|
||
newSchema.properties.push({
|
||
id: -1,
|
||
name: prop,
|
||
optional: true,
|
||
type: {
|
||
type: tsbufferSchema.SchemaType.Any
|
||
}
|
||
});
|
||
}
|
||
};
|
||
for (var _i = 0, unionProperties_1 = unionProperties; _i < unionProperties_1.length; _i++) {
|
||
var prop = unionProperties_1[_i];
|
||
_loop_1(prop);
|
||
}
|
||
return newSchema;
|
||
};
|
||
/**
|
||
* 将interface及其引用转换为展平的schema
|
||
*/
|
||
ProtoHelper.prototype.getFlatInterfaceSchema = function (schema) {
|
||
let res;
|
||
if (this.isTypeReference(schema)) {
|
||
var parsed = this.parseReference(schema);
|
||
if (parsed.type !== tsbufferSchema.SchemaType.Interface) {
|
||
throw new Error("Cannot flatten non interface type: ".concat(parsed.type));
|
||
}
|
||
res = this.getFlatInterfaceSchema(parsed);
|
||
}
|
||
else if (schema.type === tsbufferSchema.SchemaType.Interface) {
|
||
res = this._flattenInterface(schema);
|
||
}
|
||
else if (this.isMappedType(schema)) {
|
||
res = this._flattenMappedType(schema);
|
||
}
|
||
else {
|
||
// @ts-expect-error
|
||
throw new Error('Invalid interface type: ' + schema.type);
|
||
}
|
||
return res;
|
||
|
||
// var uuid = this._getSchemaUuid(schema);
|
||
// // from cache
|
||
// if (this._flatInterfaceSchemaCache[uuid]) {
|
||
// return this._flatInterfaceSchemaCache[uuid];
|
||
// }
|
||
// if (this.isTypeReference(schema)) {
|
||
// var parsed = this.parseReference(schema);
|
||
// if (parsed.type !== tsbufferSchema.SchemaType.Interface) {
|
||
// throw new Error("Cannot flatten non interface type: ".concat(parsed.type));
|
||
// }
|
||
// this._flatInterfaceSchemaCache[uuid] = this.getFlatInterfaceSchema(parsed);
|
||
// }
|
||
// else if (schema.type === tsbufferSchema.SchemaType.Interface) {
|
||
// this._flatInterfaceSchemaCache[uuid] = this._flattenInterface(schema);
|
||
// }
|
||
// else if (this.isMappedType(schema)) {
|
||
// this._flatInterfaceSchemaCache[uuid] = this._flattenMappedType(schema);
|
||
// }
|
||
// else {
|
||
// // @ts-expect-error
|
||
// throw new Error('Invalid interface type: ' + schema.type);
|
||
// }
|
||
// return this._flatInterfaceSchemaCache[uuid];
|
||
};
|
||
/**
|
||
* 展平interface
|
||
*/
|
||
ProtoHelper.prototype._flattenInterface = function (schema) {
|
||
var properties = {};
|
||
var indexSignature;
|
||
// 自身定义的properties和indexSignature优先级最高
|
||
if (schema.properties) {
|
||
for (var _i = 0, _a = schema.properties; _i < _a.length; _i++) {
|
||
var prop = _a[_i];
|
||
properties[prop.name] = {
|
||
optional: prop.optional,
|
||
type: prop.type
|
||
};
|
||
}
|
||
}
|
||
if (schema.indexSignature) {
|
||
indexSignature = schema.indexSignature;
|
||
}
|
||
// extends的优先级次之,补全没有定义的字段
|
||
if (schema.extends) {
|
||
for (var _b = 0, _c = schema.extends; _b < _c.length; _b++) {
|
||
var extend = _c[_b];
|
||
// 解引用
|
||
var parsedExtRef = this.parseReference(extend.type);
|
||
if (this.isMappedType(parsedExtRef)) {
|
||
parsedExtRef = this._flattenMappedType(parsedExtRef);
|
||
}
|
||
if (!this.isInterface(parsedExtRef)) {
|
||
throw new Error('SchemaError: extends must from interface but from ' + parsedExtRef.type);
|
||
}
|
||
// 递归展平extends
|
||
var flatenExtendsSchema = this.getFlatInterfaceSchema(parsedExtRef);
|
||
// properties
|
||
if (flatenExtendsSchema.properties) {
|
||
for (var _d = 0, _e = flatenExtendsSchema.properties; _d < _e.length; _d++) {
|
||
var prop = _e[_d];
|
||
if (!properties[prop.name]) {
|
||
properties[prop.name] = {
|
||
optional: prop.optional,
|
||
type: prop.type
|
||
};
|
||
}
|
||
}
|
||
}
|
||
// indexSignature
|
||
if (flatenExtendsSchema.indexSignature && !indexSignature) {
|
||
indexSignature = flatenExtendsSchema.indexSignature;
|
||
}
|
||
}
|
||
}
|
||
return {
|
||
type: tsbufferSchema.SchemaType.Interface,
|
||
properties: Object.entries(properties).map(function (v, i) { return ({
|
||
id: i,
|
||
name: v[0],
|
||
optional: v[1].optional,
|
||
type: v[1].type
|
||
}); }),
|
||
indexSignature: indexSignature
|
||
};
|
||
};
|
||
/** 将MappedTypeSchema转换为展平的Interface
|
||
*/
|
||
ProtoHelper.prototype._flattenMappedType = function (schema) {
|
||
// target 解引用
|
||
var target;
|
||
if (this.isTypeReference(schema.target)) {
|
||
var parsed = this.parseReference(schema.target);
|
||
target = parsed;
|
||
}
|
||
else {
|
||
target = schema.target;
|
||
}
|
||
var flatTarget;
|
||
// 内层仍然为MappedType 递归之
|
||
if (target.type === tsbufferSchema.SchemaType.Pick || target.type === tsbufferSchema.SchemaType.Partial || target.type === tsbufferSchema.SchemaType.Omit || target.type === tsbufferSchema.SchemaType.Overwrite) {
|
||
flatTarget = this._flattenMappedType(target);
|
||
}
|
||
else if (target.type === tsbufferSchema.SchemaType.Interface) {
|
||
flatTarget = this._flattenInterface(target);
|
||
}
|
||
else {
|
||
throw new Error("Invalid target.type: ".concat(target.type));
|
||
}
|
||
// 开始执行Mapped逻辑
|
||
if (schema.type === tsbufferSchema.SchemaType.Pick) {
|
||
var properties = [];
|
||
var _loop_2 = function (key) {
|
||
var propItem = flatTarget.properties.find(function (v) { return v.name === key; });
|
||
if (propItem) {
|
||
properties.push({
|
||
id: properties.length,
|
||
name: key,
|
||
optional: propItem.optional,
|
||
type: propItem.type
|
||
});
|
||
}
|
||
else if (flatTarget.indexSignature) {
|
||
properties.push({
|
||
id: properties.length,
|
||
name: key,
|
||
type: flatTarget.indexSignature.type
|
||
});
|
||
}
|
||
};
|
||
for (var _i = 0, _a = schema.keys; _i < _a.length; _i++) {
|
||
var key = _a[_i];
|
||
_loop_2(key);
|
||
}
|
||
return {
|
||
type: tsbufferSchema.SchemaType.Interface,
|
||
properties: properties
|
||
};
|
||
}
|
||
else if (schema.type === tsbufferSchema.SchemaType.Partial) {
|
||
for (var _b = 0, _c = flatTarget.properties; _b < _c.length; _b++) {
|
||
var v = _c[_b];
|
||
v.optional = true;
|
||
}
|
||
return flatTarget;
|
||
}
|
||
else if (schema.type === tsbufferSchema.SchemaType.Omit) {
|
||
var _loop_3 = function (key) {
|
||
flatTarget.properties.removeOne(function (v) { return v.name === key; });
|
||
};
|
||
for (var _d = 0, _e = schema.keys; _d < _e.length; _d++) {
|
||
var key = _e[_d];
|
||
_loop_3(key);
|
||
}
|
||
return flatTarget;
|
||
}
|
||
else if (schema.type === tsbufferSchema.SchemaType.Overwrite) {
|
||
var overwrite = this.getFlatInterfaceSchema(schema.overwrite);
|
||
if (overwrite.indexSignature) {
|
||
flatTarget.indexSignature = overwrite.indexSignature;
|
||
}
|
||
var _loop_4 = function (prop) {
|
||
flatTarget.properties.removeOne(function (v) { return v.name === prop.name; });
|
||
flatTarget.properties.push(prop);
|
||
};
|
||
for (var _f = 0, _g = overwrite.properties; _f < _g.length; _f++) {
|
||
var prop = _g[_f];
|
||
_loop_4(prop);
|
||
}
|
||
return flatTarget;
|
||
}
|
||
else {
|
||
throw new Error("Unknown type: ".concat(schema.type));
|
||
}
|
||
};
|
||
ProtoHelper.prototype.parseMappedType = function (schema) {
|
||
// 解嵌套,例如:Pick<Pick<Omit, XXX, 'a'|'b'>>>
|
||
var parents = [];
|
||
var child = schema;
|
||
do {
|
||
parents.push(child);
|
||
child = this.parseReference(child.target);
|
||
} while (this.isMappedType(child));
|
||
// 最内层是 interface,直接返回(validator 会验证 key 匹配)
|
||
if (child.type === tsbufferSchema.SchemaType.Interface) {
|
||
return child;
|
||
}
|
||
// PickOmit<A|B> === PickOmit<A> | PickOmit<B>
|
||
else if (child.type === tsbufferSchema.SchemaType.Union || child.type === tsbufferSchema.SchemaType.Intersection) {
|
||
var newSchema = {
|
||
type: child.type,
|
||
members: child.members.map(function (v) {
|
||
// 从里面往外装
|
||
var type = v.type;
|
||
for (var i = parents.length - 1; i > -1; --i) {
|
||
var parent_1 = parents[i];
|
||
type = tslib.__assign(tslib.__assign({}, parent_1), { target: type });
|
||
}
|
||
return {
|
||
id: v.id,
|
||
type: type
|
||
};
|
||
})
|
||
};
|
||
return newSchema;
|
||
}
|
||
else {
|
||
throw new Error("Unsupported pattern ".concat(schema.type, "<").concat(child.type, ">"));
|
||
}
|
||
};
|
||
return ProtoHelper;
|
||
}());
|
||
|
||
var _a;
|
||
/** @internal */
|
||
var ErrorType;
|
||
(function (ErrorType) {
|
||
ErrorType["TypeError"] = "TypeError";
|
||
ErrorType["InvalidScalarType"] = "InvalidScalarType";
|
||
ErrorType["TupleOverLength"] = "TupleOverLength";
|
||
ErrorType["InvalidEnumValue"] = "InvalidEnumValue";
|
||
ErrorType["InvalidLiteralValue"] = "InvalidLiteralValue";
|
||
ErrorType["MissingRequiredProperty"] = "MissingRequiredProperty";
|
||
ErrorType["ExcessProperty"] = "ExcessProperty";
|
||
ErrorType["InvalidNumberKey"] = "InvalidNumberKey";
|
||
ErrorType["UnionTypesNotMatch"] = "UnionTypesNotMatch";
|
||
ErrorType["UnionMembersNotMatch"] = "UnionMembersNotMatch";
|
||
ErrorType["CustomError"] = "CustomError";
|
||
})(ErrorType || (ErrorType = {}));
|
||
/** @internal */
|
||
var ErrorMsg = (_a = {},
|
||
_a[ErrorType.TypeError] = function (expect, actual) { return "Expected type to be `".concat(expect, "`, actually `").concat(actual, "`."); },
|
||
_a[ErrorType.InvalidScalarType] = function (value, scalarType) { return "`".concat(value, "` is not a valid `").concat(scalarType, "`."); },
|
||
_a[ErrorType.TupleOverLength] = function (valueLength, schemaLength) { return "Value has ".concat(valueLength, " elements but schema allows only ").concat(schemaLength, "."); },
|
||
_a[ErrorType.InvalidEnumValue] = function (value) { return "`".concat(value, "` is not a valid enum member."); },
|
||
_a[ErrorType.InvalidLiteralValue] = function (expected, actual) { return "Expected to equals `".concat(stringify(expected), "`, actually `").concat(stringify(actual), "`"); },
|
||
_a[ErrorType.MissingRequiredProperty] = function (propName) { return "Missing required property `".concat(propName, "`."); },
|
||
_a[ErrorType.ExcessProperty] = function (propName) { return "Excess property `".concat(propName, "` should not exists."); },
|
||
_a[ErrorType.InvalidNumberKey] = function (key) { return "`".concat(key, "` is not a valid key, the key here should be a `number`."); },
|
||
// Union
|
||
_a[ErrorType.UnionTypesNotMatch] = function (value, types) { return "`".concat(stringify(value), "` is not matched to `").concat(types.join(' | '), "`"); },
|
||
_a[ErrorType.UnionMembersNotMatch] = function (memberErrors) { return "No union member matched, detail:\n".concat(memberErrors.map(function (v, i) { return " <".concat(i, "> ").concat(v.errMsg); }).join('\n')); },
|
||
_a[ErrorType.CustomError] = function (errMsg) { return errMsg; },
|
||
_a);
|
||
/** @internal */
|
||
function stringify(value) {
|
||
if (typeof value === 'string') {
|
||
var output = JSON.stringify(value);
|
||
return "'" + output.substr(1, output.length - 2) + "'";
|
||
}
|
||
return JSON.stringify(value);
|
||
}
|
||
|
||
/** @internal */
|
||
var ValidateResultError = /** @class */ (function () {
|
||
function ValidateResultError(error) {
|
||
this.isSucc = false;
|
||
this.error = error;
|
||
}
|
||
Object.defineProperty(ValidateResultError.prototype, "errMsg", {
|
||
get: function () {
|
||
return ValidateResultError.getErrMsg(this.error);
|
||
},
|
||
enumerable: false,
|
||
configurable: true
|
||
});
|
||
ValidateResultError.getErrMsg = function (error) {
|
||
var _a;
|
||
var errMsg = ErrorMsg[error.type].apply(ErrorMsg, error.params);
|
||
if ((_a = error.inner) === null || _a === void 0 ? void 0 : _a.property.length) {
|
||
return "Property `".concat(error.inner.property.join('.'), "`: ").concat(errMsg);
|
||
}
|
||
else {
|
||
return errMsg;
|
||
}
|
||
};
|
||
return ValidateResultError;
|
||
}());
|
||
/** @internal */
|
||
var ValidateResultUtil = /** @class */ (function () {
|
||
function ValidateResultUtil() {
|
||
}
|
||
ValidateResultUtil.error = function (type) {
|
||
var params = [];
|
||
for (var _i = 1; _i < arguments.length; _i++) {
|
||
params[_i - 1] = arguments[_i];
|
||
}
|
||
return new ValidateResultError({
|
||
type: type,
|
||
params: params
|
||
});
|
||
};
|
||
ValidateResultUtil.innerError = function (property, value, schema, error) {
|
||
var _a;
|
||
if (error.error.inner) {
|
||
if (typeof property === 'string') {
|
||
error.error.inner.property.unshift(property);
|
||
}
|
||
else {
|
||
(_a = error.error.inner.property).unshift.apply(_a, property);
|
||
}
|
||
}
|
||
else {
|
||
error.error.inner = {
|
||
property: typeof property === 'string' ? [property] : property,
|
||
value: value,
|
||
schema: schema
|
||
};
|
||
}
|
||
return error;
|
||
};
|
||
ValidateResultUtil.succ = { isSucc: true };
|
||
return ValidateResultUtil;
|
||
}());
|
||
|
||
var typedArrays = {
|
||
Int8Array: Int8Array,
|
||
Int16Array: Int16Array,
|
||
Int32Array: Int32Array,
|
||
BigInt64Array: typeof BigInt64Array !== 'undefined' ? BigInt64Array : undefined,
|
||
Uint8Array: Uint8Array,
|
||
Uint16Array: Uint16Array,
|
||
Uint32Array: Uint32Array,
|
||
BigUint64Array: typeof BigUint64Array !== 'undefined' ? BigUint64Array : undefined,
|
||
Float32Array: Float32Array,
|
||
Float64Array: Float64Array
|
||
};
|
||
/**
|
||
* TSBuffer Schema Validator
|
||
* @public
|
||
*/
|
||
var TSBufferValidator = /** @class */ (function () {
|
||
function TSBufferValidator(proto, options) {
|
||
/**
|
||
* Default options
|
||
*/
|
||
this.options = {
|
||
excessPropertyChecks: true,
|
||
strictNullChecks: false,
|
||
cloneProto: true
|
||
};
|
||
if (options) {
|
||
this.options = tslib.__assign(tslib.__assign({}, this.options), options);
|
||
}
|
||
this.proto = this.options.cloneProto ? Object.merge({}, proto) : proto;
|
||
this.protoHelper = new ProtoHelper(this.proto);
|
||
}
|
||
/**
|
||
* Validate whether the value is valid to the schema
|
||
* @param value - Value to be validated.
|
||
* @param schemaId - Schema or schema ID.
|
||
* For example, the schema ID for type `Test` in `a/b.ts` may be `a/b/Test`.
|
||
*/
|
||
TSBufferValidator.prototype.validate = function (value, schemaOrId, options) {
|
||
var _a, _b;
|
||
var schema;
|
||
var schemaId;
|
||
// Get schema
|
||
if (typeof schemaOrId === 'string') {
|
||
schemaId = schemaOrId;
|
||
schema = this.proto[schemaId];
|
||
if (!schema) {
|
||
throw new Error("Cannot find schema: ".concat(schemaId));
|
||
}
|
||
}
|
||
else {
|
||
schema = schemaOrId;
|
||
}
|
||
// Merge default options
|
||
return this._validate(value, schema, tslib.__assign(tslib.__assign({}, options), { excessPropertyChecks: (_a = options === null || options === void 0 ? void 0 : options.excessPropertyChecks) !== null && _a !== void 0 ? _a : this.options.excessPropertyChecks, strictNullChecks: (_b = options === null || options === void 0 ? void 0 : options.strictNullChecks) !== null && _b !== void 0 ? _b : this.options.strictNullChecks }));
|
||
};
|
||
TSBufferValidator.prototype._validate = function (value, schema, options) {
|
||
var _a;
|
||
var vRes;
|
||
// Validate
|
||
switch (schema.type) {
|
||
case tsbufferSchema.SchemaType.Boolean:
|
||
vRes = this._validateBooleanType(value, schema);
|
||
break;
|
||
case tsbufferSchema.SchemaType.Number:
|
||
vRes = this._validateNumberType(value, schema);
|
||
break;
|
||
case tsbufferSchema.SchemaType.String:
|
||
vRes = this._validateStringType(value, schema);
|
||
break;
|
||
case tsbufferSchema.SchemaType.Array:
|
||
vRes = this._validateArrayType(value, schema, options);
|
||
break;
|
||
case tsbufferSchema.SchemaType.Tuple:
|
||
vRes = this._validateTupleType(value, schema, options);
|
||
break;
|
||
case tsbufferSchema.SchemaType.Enum:
|
||
vRes = this._validateEnumType(value, schema);
|
||
break;
|
||
case tsbufferSchema.SchemaType.Any:
|
||
vRes = this._validateAnyType(value);
|
||
break;
|
||
case tsbufferSchema.SchemaType.Literal:
|
||
vRes = this._validateLiteralType(value, schema, (_a = options === null || options === void 0 ? void 0 : options.strictNullChecks) !== null && _a !== void 0 ? _a : this.options.strictNullChecks);
|
||
break;
|
||
case tsbufferSchema.SchemaType.Object:
|
||
vRes = this._validateObjectType(value, schema);
|
||
break;
|
||
case tsbufferSchema.SchemaType.Interface:
|
||
vRes = this._validateInterfaceType(value, schema, options);
|
||
break;
|
||
case tsbufferSchema.SchemaType.Buffer:
|
||
vRes = this._validateBufferType(value, schema);
|
||
break;
|
||
case tsbufferSchema.SchemaType.IndexedAccess:
|
||
case tsbufferSchema.SchemaType.Reference:
|
||
case tsbufferSchema.SchemaType.Keyof:
|
||
vRes = this._validateReferenceType(value, schema, options);
|
||
break;
|
||
case tsbufferSchema.SchemaType.Union:
|
||
vRes = this._validateUnionType(value, schema, options);
|
||
break;
|
||
case tsbufferSchema.SchemaType.Intersection:
|
||
vRes = this._validateIntersectionType(value, schema, options);
|
||
break;
|
||
case tsbufferSchema.SchemaType.Pick:
|
||
case tsbufferSchema.SchemaType.Omit:
|
||
case tsbufferSchema.SchemaType.Partial:
|
||
case tsbufferSchema.SchemaType.Overwrite:
|
||
vRes = this._validateMappedType(value, schema, options);
|
||
break;
|
||
case tsbufferSchema.SchemaType.Date:
|
||
vRes = this._validateDateType(value);
|
||
break;
|
||
case tsbufferSchema.SchemaType.NonNullable:
|
||
vRes = this._validateNonNullableType(value, schema, options);
|
||
break;
|
||
case tsbufferSchema.SchemaType.Custom:
|
||
var res = schema.validate(value);
|
||
vRes = res.isSucc ? ValidateResultUtil.succ : ValidateResultUtil.error(ErrorType.CustomError, res.errMsg);
|
||
break;
|
||
// 错误的type
|
||
default:
|
||
// @ts-expect-error
|
||
throw new Error("Unsupported schema type: ".concat(schema.type));
|
||
}
|
||
//vRes = ValidateResultUtil.succ;
|
||
// prune
|
||
if (options === null || options === void 0 ? void 0 : options.prune) {
|
||
// don't need prune, return original value
|
||
if (options.prune.output === undefined) {
|
||
options.prune.output = value;
|
||
}
|
||
// output to parent
|
||
if (options.prune.parent) {
|
||
options.prune.parent.value[options.prune.parent.key] = options.prune.output;
|
||
}
|
||
}
|
||
return vRes;
|
||
};
|
||
/**
|
||
* 修剪 Object,移除 Schema 中未定义的 Key
|
||
* 需要确保 value 类型合法
|
||
* @param value - value to be validated
|
||
* @param schemaOrId -Schema or schema ID.
|
||
* @returns Validate result and pruned value. if validate failed, `pruneOutput` would be undefined.
|
||
*/
|
||
TSBufferValidator.prototype.prune = function (value, schemaOrId, options) {
|
||
var _a;
|
||
var schema = typeof schemaOrId === 'string' ? this.proto[schemaOrId] : schemaOrId;
|
||
if (!schema) {
|
||
throw new Error('Cannot find schema: ' + schemaOrId);
|
||
}
|
||
var prune = {};
|
||
var vRes = this._validate(value, schema, tslib.__assign(tslib.__assign({}, options), { prune: prune, excessPropertyChecks: false, strictNullChecks: (_a = options === null || options === void 0 ? void 0 : options.strictNullChecks) !== null && _a !== void 0 ? _a : this.options.strictNullChecks }));
|
||
if (vRes.isSucc) {
|
||
vRes.pruneOutput = prune.output;
|
||
}
|
||
return vRes;
|
||
};
|
||
TSBufferValidator.prototype._validateBooleanType = function (value, schema) {
|
||
var type = this._getTypeof(value);
|
||
if (type === 'boolean') {
|
||
return ValidateResultUtil.succ;
|
||
}
|
||
else {
|
||
return ValidateResultUtil.error(ErrorType.TypeError, 'boolean', type);
|
||
}
|
||
};
|
||
TSBufferValidator.prototype._validateNumberType = function (value, schema) {
|
||
// 默认为double
|
||
var scalarType = schema.scalarType || 'double';
|
||
// Wrong Type
|
||
var type = this._getTypeof(value);
|
||
var rightType = scalarType.indexOf('big') > -1 ? 'bigint' : 'number';
|
||
if (type !== rightType) {
|
||
return ValidateResultUtil.error(ErrorType.TypeError, rightType, type);
|
||
}
|
||
// scalarType类型检测
|
||
// 整形却为小数
|
||
if (scalarType !== 'double' && type === 'number' && !Number.isInteger(value)) {
|
||
return ValidateResultUtil.error(ErrorType.InvalidScalarType, value, scalarType);
|
||
}
|
||
// 无符号整形却为负数
|
||
if (scalarType.indexOf('uint') > -1 && value < 0) {
|
||
return ValidateResultUtil.error(ErrorType.InvalidScalarType, value, scalarType);
|
||
}
|
||
return ValidateResultUtil.succ;
|
||
};
|
||
TSBufferValidator.prototype._validateStringType = function (value, schema) {
|
||
var type = this._getTypeof(value);
|
||
return type === 'string' ? ValidateResultUtil.succ : ValidateResultUtil.error(ErrorType.TypeError, 'string', type);
|
||
};
|
||
TSBufferValidator.prototype._validateArrayType = function (value, schema, options) {
|
||
// is Array type
|
||
var type = this._getTypeof(value);
|
||
if (type !== tsbufferSchema.SchemaType.Array) {
|
||
return ValidateResultUtil.error(ErrorType.TypeError, tsbufferSchema.SchemaType.Array, type);
|
||
}
|
||
// prune output
|
||
var prune = options.prune;
|
||
if (prune) {
|
||
prune.output = Array.from({ length: value.length });
|
||
}
|
||
// validate elementType
|
||
for (var i = 0; i < value.length; ++i) {
|
||
var elemValidateResult = this._validate(value[i], schema.elementType, tslib.__assign(tslib.__assign({}, options), { prune: (prune === null || prune === void 0 ? void 0 : prune.output) ? {
|
||
parent: {
|
||
value: prune.output,
|
||
key: i
|
||
}
|
||
} : undefined }));
|
||
if (!elemValidateResult.isSucc) {
|
||
return ValidateResultUtil.innerError('' + i, value[i], schema.elementType, elemValidateResult);
|
||
}
|
||
}
|
||
return ValidateResultUtil.succ;
|
||
};
|
||
TSBufferValidator.prototype._validateTupleType = function (value, schema, options) {
|
||
// is Array type
|
||
var type = this._getTypeof(value);
|
||
if (type !== tsbufferSchema.SchemaType.Array) {
|
||
return ValidateResultUtil.error(ErrorType.TypeError, tsbufferSchema.SchemaType.Array, type);
|
||
}
|
||
var prune = options.prune;
|
||
// validate length
|
||
// excessPropertyChecks 与 prune互斥
|
||
if (!prune && options.excessPropertyChecks && value.length > schema.elementTypes.length) {
|
||
return ValidateResultUtil.error(ErrorType.TupleOverLength, value.length, schema.elementTypes.length);
|
||
}
|
||
// prune output
|
||
if (prune) {
|
||
prune.output = Array.from({ length: Math.min(value.length, schema.elementTypes.length) });
|
||
}
|
||
// validate elementType
|
||
for (var i = 0; i < schema.elementTypes.length; ++i) {
|
||
// MissingRequiredProperty: NotOptional && is undefined
|
||
if (value[i] === undefined || value[i] === null && !options.strictNullChecks) {
|
||
var canBeNull = this._canBeNull(schema.elementTypes[i]);
|
||
var canBeUndefined = schema.optionalStartIndex !== undefined && i >= schema.optionalStartIndex || this._canBeUndefined(schema.elementTypes[i]);
|
||
var isOptional = canBeUndefined || !options.strictNullChecks && canBeNull;
|
||
// skip undefined property
|
||
if (isOptional) {
|
||
// Prune null & undefined->null
|
||
if (prune === null || prune === void 0 ? void 0 : prune.output) {
|
||
if (value[i] === null && canBeNull
|
||
|| value[i] === undefined && !canBeUndefined && canBeNull) {
|
||
prune.output[i] = null;
|
||
}
|
||
}
|
||
continue;
|
||
}
|
||
else {
|
||
return ValidateResultUtil.error(ErrorType.MissingRequiredProperty, i);
|
||
}
|
||
}
|
||
// element type check
|
||
var elemValidateResult = this._validate(value[i], schema.elementTypes[i], {
|
||
prune: (prune === null || prune === void 0 ? void 0 : prune.output) ? {
|
||
parent: {
|
||
value: prune.output,
|
||
key: i
|
||
}
|
||
} : undefined,
|
||
strictNullChecks: options.strictNullChecks,
|
||
excessPropertyChecks: options.excessPropertyChecks
|
||
});
|
||
if (!elemValidateResult.isSucc) {
|
||
return ValidateResultUtil.innerError('' + i, value[i], schema.elementTypes[i], elemValidateResult);
|
||
}
|
||
}
|
||
return ValidateResultUtil.succ;
|
||
};
|
||
TSBufferValidator.prototype._canBeUndefined = function (schema) {
|
||
var _this = this;
|
||
if (schema.type === tsbufferSchema.SchemaType.Union) {
|
||
return schema.members.some(function (v) { return _this._canBeUndefined(v.type); });
|
||
}
|
||
if (schema.type === tsbufferSchema.SchemaType.Literal && schema.literal === undefined) {
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
TSBufferValidator.prototype._canBeNull = function (schema) {
|
||
var _this = this;
|
||
if (schema.type === tsbufferSchema.SchemaType.Union) {
|
||
return schema.members.some(function (v) { return _this._canBeNull(v.type); });
|
||
}
|
||
if (schema.type === tsbufferSchema.SchemaType.Literal && schema.literal === null) {
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
TSBufferValidator.prototype._validateEnumType = function (value, schema) {
|
||
// must be string or number
|
||
var type = this._getTypeof(value);
|
||
if (type !== 'string' && type !== 'number') {
|
||
return ValidateResultUtil.error(ErrorType.TypeError, 'string | number', type);
|
||
}
|
||
// 有值与预设相同
|
||
if (schema.members.some(function (v) { return v.value === value; })) {
|
||
return ValidateResultUtil.succ;
|
||
}
|
||
else {
|
||
return ValidateResultUtil.error(ErrorType.InvalidEnumValue, value);
|
||
}
|
||
};
|
||
TSBufferValidator.prototype._validateAnyType = function (value) {
|
||
return ValidateResultUtil.succ;
|
||
};
|
||
TSBufferValidator.prototype._validateLiteralType = function (value, schema, strictNullChecks) {
|
||
// 非strictNullChecks严格模式,null undefined同等对待
|
||
if (!strictNullChecks && (schema.literal === null || schema.literal === undefined)) {
|
||
return value === null || value === undefined ?
|
||
ValidateResultUtil.succ
|
||
: ValidateResultUtil.error(ErrorType.InvalidLiteralValue, schema.literal, value);
|
||
}
|
||
return value === schema.literal ?
|
||
ValidateResultUtil.succ
|
||
: ValidateResultUtil.error(ErrorType.InvalidLiteralValue, schema.literal, value);
|
||
};
|
||
TSBufferValidator.prototype._validateObjectType = function (value, schema) {
|
||
var type = this._getTypeof(value);
|
||
return type === 'Object' || type === 'Array' ? ValidateResultUtil.succ : ValidateResultUtil.error(ErrorType.TypeError, 'Object', type);
|
||
};
|
||
TSBufferValidator.prototype._validateInterfaceType = function (value, schema, options) {
|
||
var type = this._getTypeof(value);
|
||
if (type !== 'Object') {
|
||
return ValidateResultUtil.error(ErrorType.TypeError, 'Object', type);
|
||
}
|
||
// 先展平
|
||
var flatSchema = this.protoHelper.getFlatInterfaceSchema(schema);
|
||
// From union or intersecton type
|
||
if (options.unionProperties) {
|
||
flatSchema = this.protoHelper.applyUnionProperties(flatSchema, options.unionProperties);
|
||
}
|
||
return this._validateFlatInterface(value, flatSchema, options);
|
||
};
|
||
TSBufferValidator.prototype._validateMappedType = function (value, schema, options) {
|
||
var parsed = this.protoHelper.parseMappedType(schema);
|
||
if (parsed.type === tsbufferSchema.SchemaType.Interface) {
|
||
return this._validateInterfaceType(value, schema, options);
|
||
}
|
||
else if (parsed.type === tsbufferSchema.SchemaType.Union) {
|
||
return this._validateUnionType(value, parsed, options);
|
||
}
|
||
else if (parsed.type === tsbufferSchema.SchemaType.Intersection) {
|
||
return this._validateIntersectionType(value, parsed, options);
|
||
}
|
||
// @ts-expect-error
|
||
throw new Error("Invalid ".concat(schema.type, " target type: ").concat(parsed.type));
|
||
};
|
||
TSBufferValidator.prototype._validateFlatInterface = function (value, schema, options) {
|
||
// interfaceSignature强制了key必须是数字的情况
|
||
if (schema.indexSignature && schema.indexSignature.keyType === tsbufferSchema.SchemaType.Number) {
|
||
for (var key in value) {
|
||
if (!this._isNumberKey(key)) {
|
||
return ValidateResultUtil.error(ErrorType.InvalidNumberKey, key);
|
||
}
|
||
}
|
||
}
|
||
var prune = options.prune;
|
||
if (prune) {
|
||
prune.output = {};
|
||
}
|
||
// Excess property check (与prune互斥)
|
||
if (!prune && options.excessPropertyChecks && !schema.indexSignature) {
|
||
var validProperties_1 = schema.properties.map(function (v) { return v.name; });
|
||
var firstExcessProperty = Object.keys(value).find(function (v) { return validProperties_1.indexOf(v) === -1; });
|
||
if (firstExcessProperty) {
|
||
return ValidateResultUtil.error(ErrorType.ExcessProperty, firstExcessProperty);
|
||
}
|
||
}
|
||
// 校验properties
|
||
if (schema.properties) {
|
||
for (var _i = 0, _a = schema.properties; _i < _a.length; _i++) {
|
||
var property = _a[_i];
|
||
// MissingRequiredProperty: is undefined && !isOptional
|
||
if (value[property.name] === undefined || value[property.name] === null && !options.strictNullChecks) {
|
||
var canBeNull = this._canBeNull(property.type);
|
||
var canBeUndefined = property.optional || this._canBeUndefined(property.type);
|
||
var isOptional = canBeUndefined || !options.strictNullChecks && canBeNull;
|
||
// skip undefined optional property
|
||
if (isOptional) {
|
||
// Prune null & undefined->null
|
||
if (prune === null || prune === void 0 ? void 0 : prune.output) {
|
||
if (value[property.name] === null && canBeNull
|
||
|| value[property.name] === undefined && !canBeUndefined && canBeNull) {
|
||
prune.output[property.name] = null;
|
||
}
|
||
}
|
||
continue;
|
||
}
|
||
else {
|
||
return ValidateResultUtil.error(ErrorType.MissingRequiredProperty, property.name);
|
||
}
|
||
}
|
||
// property本身验证
|
||
var vRes = this._validate(value[property.name], property.type, {
|
||
prune: (prune === null || prune === void 0 ? void 0 : prune.output) && property.id > -1 ? {
|
||
parent: {
|
||
value: prune.output,
|
||
key: property.name
|
||
}
|
||
} : undefined,
|
||
strictNullChecks: options.strictNullChecks,
|
||
excessPropertyChecks: options.excessPropertyChecks
|
||
});
|
||
if (!vRes.isSucc) {
|
||
return ValidateResultUtil.innerError(property.name, value[property.name], property.type, vRes);
|
||
}
|
||
}
|
||
}
|
||
// 检测indexSignature
|
||
if (schema.indexSignature) {
|
||
for (var key in value) {
|
||
// only prune is (property is pruned already)
|
||
// let memberPrune: ValidatePruneOptions | undefined = schema.properties.some(v => v.name === key) ? undefined : {};
|
||
// validate each field
|
||
var vRes = this._validate(value[key], schema.indexSignature.type, {
|
||
prune: (prune === null || prune === void 0 ? void 0 : prune.output) ? {
|
||
parent: {
|
||
value: prune.output,
|
||
key: key
|
||
}
|
||
} : undefined,
|
||
strictNullChecks: options.strictNullChecks,
|
||
excessPropertyChecks: options.excessPropertyChecks
|
||
});
|
||
if (!vRes.isSucc) {
|
||
return ValidateResultUtil.innerError(key, value[key], schema.indexSignature.type, vRes);
|
||
}
|
||
}
|
||
}
|
||
return ValidateResultUtil.succ;
|
||
};
|
||
TSBufferValidator.prototype._validateBufferType = function (value, schema) {
|
||
var _a, _b;
|
||
var type = this._getTypeof(value);
|
||
if (type !== 'Object') {
|
||
return ValidateResultUtil.error(ErrorType.TypeError, schema.arrayType || 'ArrayBuffer', type);
|
||
}
|
||
else if (schema.arrayType) {
|
||
var typeArrayClass = typedArrays[schema.arrayType];
|
||
if (!typeArrayClass) {
|
||
throw new Error("Error TypedArray type: ".concat(schema.arrayType));
|
||
}
|
||
return value instanceof typeArrayClass ? ValidateResultUtil.succ : ValidateResultUtil.error(ErrorType.TypeError, schema.arrayType, (_a = value === null || value === void 0 ? void 0 : value.constructor) === null || _a === void 0 ? void 0 : _a.name);
|
||
}
|
||
else {
|
||
return value instanceof ArrayBuffer ? ValidateResultUtil.succ : ValidateResultUtil.error(ErrorType.TypeError, 'ArrayBuffer', (_b = value === null || value === void 0 ? void 0 : value.constructor) === null || _b === void 0 ? void 0 : _b.name);
|
||
}
|
||
};
|
||
TSBufferValidator.prototype._validateReferenceType = function (value, schema, options) {
|
||
return this._validate(value, this.protoHelper.parseReference(schema), options);
|
||
};
|
||
TSBufferValidator.prototype._validateUnionType = function (value, schema, options) {
|
||
var _this = this;
|
||
options.unionProperties = options.unionProperties || this.protoHelper.getUnionProperties(schema);
|
||
var isObjectPrune = false;
|
||
var prune = options.prune;
|
||
if (prune && value && Object.getPrototypeOf(value) === Object.prototype) {
|
||
isObjectPrune = true;
|
||
prune.output = {};
|
||
}
|
||
// 有一成功则成功
|
||
var isSomeSucc = false;
|
||
var memberErrors = [];
|
||
for (var i = 0; i < schema.members.length; ++i) {
|
||
var member = schema.members[i];
|
||
var memberType = this.protoHelper.isTypeReference(member.type) ? this.protoHelper.parseReference(member.type) : member.type;
|
||
var memberPrune = prune ? {} : undefined;
|
||
var vRes = this._validate(value, memberType, tslib.__assign(tslib.__assign({}, options), { prune: memberPrune }));
|
||
if (vRes.isSucc) {
|
||
isSomeSucc = true;
|
||
// if prune object: must prune all members
|
||
if (isObjectPrune) {
|
||
prune.output = tslib.__assign(tslib.__assign({}, prune.output), memberPrune.output);
|
||
}
|
||
// not prune object: stop checking after 1st member matched
|
||
else {
|
||
break;
|
||
}
|
||
}
|
||
else {
|
||
memberErrors.push(vRes);
|
||
}
|
||
}
|
||
// 有一成功则成功;
|
||
if (isSomeSucc) {
|
||
return ValidateResultUtil.succ;
|
||
}
|
||
// 全部失败,则失败
|
||
else {
|
||
// All member error is the same, return the first
|
||
var msg0_1 = memberErrors[0].errMsg;
|
||
if (memberErrors.every(function (v) { return v.errMsg === msg0_1; })) {
|
||
return memberErrors[0];
|
||
}
|
||
// mutual exclusion: return the only one
|
||
var nonLiteralErrors = memberErrors.filter(function (v) { return v.error.type !== ErrorType.InvalidLiteralValue; });
|
||
if (nonLiteralErrors.length === 1) {
|
||
return nonLiteralErrors[0];
|
||
}
|
||
// All member error without inner: show simple msg
|
||
if (memberErrors.every(function (v) { return !v.error.inner && (v.error.type === ErrorType.TypeError || v.error.type === ErrorType.InvalidLiteralValue); })) {
|
||
var valueType = this._getTypeof(value);
|
||
var expectedTypes = memberErrors.map(function (v) { return v.error.type === ErrorType.TypeError ? v.error.params[0] : _this._getTypeof(v.error.params[0]); }).distinct();
|
||
// Expected type A|B|C, actually type D
|
||
if (expectedTypes.indexOf(valueType) === -1) {
|
||
return ValidateResultUtil.error(ErrorType.TypeError, expectedTypes.join(' | '), this._getTypeof(value));
|
||
}
|
||
// `'D'` is not matched to `'A'|'B'|'C'`
|
||
if (valueType !== 'Object' && valueType !== tsbufferSchema.SchemaType.Array) {
|
||
var types = memberErrors.map(function (v) { return v.error.type === ErrorType.TypeError ? v.error.params[0] : stringify(v.error.params[0]); }).distinct();
|
||
return ValidateResultUtil.error(ErrorType.UnionTypesNotMatch, value, types);
|
||
}
|
||
}
|
||
// other errors
|
||
return ValidateResultUtil.error(ErrorType.UnionMembersNotMatch, memberErrors);
|
||
}
|
||
};
|
||
TSBufferValidator.prototype._validateIntersectionType = function (value, schema, options) {
|
||
options.unionProperties = options.unionProperties || this.protoHelper.getUnionProperties(schema);
|
||
var isObjectPrune = false;
|
||
var prune = options.prune;
|
||
if (prune && value && Object.getPrototypeOf(value) === Object.prototype) {
|
||
prune.output = {};
|
||
isObjectPrune = true;
|
||
}
|
||
// 有一失败则失败
|
||
for (var i = 0, len = schema.members.length; i < len; ++i) {
|
||
// 验证member
|
||
var memberType = schema.members[i].type;
|
||
memberType = this.protoHelper.isTypeReference(memberType) ? this.protoHelper.parseReference(memberType) : memberType;
|
||
var memberPrune = prune ? {} : undefined;
|
||
var vRes = this._validate(value, memberType, tslib.__assign(tslib.__assign({}, options), { prune: memberPrune }));
|
||
// 有一失败则失败
|
||
if (!vRes.isSucc) {
|
||
return vRes;
|
||
}
|
||
if (isObjectPrune) {
|
||
prune.output = tslib.__assign(tslib.__assign({}, prune.output), memberPrune.output);
|
||
}
|
||
}
|
||
// 全成功则成功
|
||
return ValidateResultUtil.succ;
|
||
};
|
||
TSBufferValidator.prototype._validateDateType = function (value) {
|
||
if (value instanceof Date) {
|
||
return ValidateResultUtil.succ;
|
||
}
|
||
else {
|
||
return ValidateResultUtil.error(ErrorType.TypeError, 'Date', this._getTypeof(value));
|
||
}
|
||
};
|
||
TSBufferValidator.prototype._validateNonNullableType = function (value, schema, options) {
|
||
var type = this._getTypeof(value);
|
||
if ((type === 'null' || type === 'undefined') && schema.target.type !== 'Any') {
|
||
return ValidateResultUtil.error(ErrorType.TypeError, 'NonNullable', type);
|
||
}
|
||
return this._validate(value, schema.target, options);
|
||
};
|
||
TSBufferValidator.prototype._isNumberKey = function (key) {
|
||
var int = parseInt(key);
|
||
return !(isNaN(int) || ('' + int) !== key);
|
||
};
|
||
TSBufferValidator.prototype._getTypeof = function (value) {
|
||
var type = typeof value;
|
||
if (type === 'object') {
|
||
if (value === null) {
|
||
return 'null';
|
||
}
|
||
else if (Array.isArray(value)) {
|
||
return tsbufferSchema.SchemaType.Array;
|
||
}
|
||
else {
|
||
return 'Object';
|
||
}
|
||
}
|
||
return type;
|
||
};
|
||
return TSBufferValidator;
|
||
}());
|
||
|
||
exports.ProtoHelper = ProtoHelper;
|
||
exports.TSBufferValidator = TSBufferValidator;
|