mirror of
https://github.com/datahub-project/datahub.git
synced 2025-10-29 17:59:24 +00:00
Merge pull request #1213 from theseyi/moar-propagate
throws more errors on failed schema validation
This commit is contained in:
commit
d5dfb38a84
@ -99,7 +99,16 @@ const complianceMetadataTaxonomy: Array<IMetadataType> = [
|
|||||||
* @param {string | Array<string>} expectedType the pattern string to match against
|
* @param {string | Array<string>} expectedType the pattern string to match against
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
const valueEquiv = (value: any, expectedType: string | Array<string>): boolean => expectedType.includes(typeOf(value));
|
const isValueEquiv = (value: any, expectedType: string | Array<string>): true => {
|
||||||
|
const valueType = typeOf(value);
|
||||||
|
const isValueOfExpectedType = expectedType.includes(valueType);
|
||||||
|
|
||||||
|
if (!isValueOfExpectedType) {
|
||||||
|
throw new Error(`Expected ${value} to be of type(s) ${expectedType}, got ${valueType}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isValueOfExpectedType;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the type key and the pattern string from the string mapping into a tuple pair
|
* Extracts the type key and the pattern string from the string mapping into a tuple pair
|
||||||
@ -119,27 +128,35 @@ const typePatternMap = (metadataType: IMetadataType): [string, string | Array<st
|
|||||||
const keyValueHasMatch = (object: IObject<any>) => (metadataType: IMetadataType): boolean => {
|
const keyValueHasMatch = (object: IObject<any>) => (metadataType: IMetadataType): boolean => {
|
||||||
const [name, type] = typePatternMap(metadataType);
|
const [name, type] = typePatternMap(metadataType);
|
||||||
const value = object[name];
|
const value = object[name];
|
||||||
const rootValueEquiv = object.hasOwnProperty(name) && valueEquiv(value, type);
|
const isRootValueEquiv = object.hasOwnProperty(name) && isValueEquiv(value, type);
|
||||||
const innerType = metadataType['@props'];
|
const innerType = metadataType['@props'];
|
||||||
|
|
||||||
|
if (!isRootValueEquiv) {
|
||||||
|
throw new Error(`Expected "${name}" to be a key on object`);
|
||||||
|
}
|
||||||
|
|
||||||
if (type.includes('object') && isObject(value)) {
|
if (type.includes('object') && isObject(value)) {
|
||||||
// recurse on object properties
|
// recurse on object properties
|
||||||
return rootValueEquiv && keysEquiv(value, innerType!);
|
return isRootValueEquiv && keysEquiv(value, innerType!);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.includes('array') && Array.isArray(value)) {
|
if (type.includes('array') && Array.isArray(value)) {
|
||||||
const { length } = value;
|
const { length } = value;
|
||||||
|
|
||||||
|
if (!length) {
|
||||||
|
throw new Error(`Expected array for ${name} to not be empty`);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// recursively reduce on array elements
|
// recursively reduce on array elements
|
||||||
// ensure the array contains at least on element
|
// ensure the array contains at least on element
|
||||||
rootValueEquiv &&
|
isRootValueEquiv &&
|
||||||
length > 0 &&
|
length > 0 &&
|
||||||
arrayReduce((isEquiv: boolean, value: any) => isEquiv && keysEquiv(value, innerType!), rootValueEquiv)(value)
|
arrayReduce((isEquiv: boolean, value: any) => isEquiv && keysEquiv(value, innerType!), isRootValueEquiv)(value)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rootValueEquiv;
|
return isRootValueEquiv;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,7 +166,7 @@ const keyValueHasMatch = (object: IObject<any>) => (metadataType: IMetadataType)
|
|||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
* @throws {Error} if object keys do not match type @names
|
* @throws {Error} if object keys do not match type @names
|
||||||
*/
|
*/
|
||||||
const keysMatchNames = (object: IObject<any>, typeMaps: Array<IMetadataType>): boolean => {
|
const keysMatchNames = (object: IObject<any>, typeMaps: Array<IMetadataType>): true => {
|
||||||
const objectKeys = Object.keys(object).sort();
|
const objectKeys = Object.keys(object).sort();
|
||||||
const typeKeys = arrayMap((typeMap: IMetadataType) => typeMap['@name'])(typeMaps).sort();
|
const typeKeys = arrayMap((typeMap: IMetadataType) => typeMap['@name'])(typeMaps).sort();
|
||||||
const objectKeysSerialized = objectKeys.toString();
|
const objectKeysSerialized = objectKeys.toString();
|
||||||
@ -157,7 +174,12 @@ const keysMatchNames = (object: IObject<any>, typeMaps: Array<IMetadataType>): b
|
|||||||
const match = objectKeysSerialized === typeKeysSerialized;
|
const match = objectKeysSerialized === typeKeysSerialized;
|
||||||
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
throw new Error(`Extra attributes found: ${difference(objectKeys, typeKeys).join(', ')}`);
|
throw new Error(
|
||||||
|
`Expected attributes ${typeKeys.join(', ')} on object. Found additional attributes ${difference(
|
||||||
|
objectKeys,
|
||||||
|
typeKeys
|
||||||
|
).join(', ')}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return match;
|
return match;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user