mono/packages/vfs/ref/fs/utils/validate.ts

120 lines
3.2 KiB
TypeScript

let prettyPrintTypes = function (types: string[]) {
const addArticle = (str: string) => {
let vowels = ['a', 'e', 'i', 'o', 'u'];
if (vowels.indexOf(str[0]) !== -1) {
return 'an ' + str;
}
return 'a ' + str;
};
return types.map(addArticle).join(' or ');
};
let isArrayOfNotation = function (typeDefinition: string) {
return /array of /.test(typeDefinition);
};
let extractTypeFromArrayOfNotation = function (typeDefinition: string) {
// The notation is e.g. 'array of string'
return typeDefinition.split(' of ')[1];
};
let isValidTypeDefinition = (typeStr: string): boolean => {
if (isArrayOfNotation(typeStr)) {
return isValidTypeDefinition(extractTypeFromArrayOfNotation(typeStr));
}
return [
'string',
'number',
'boolean',
'array',
'object',
'buffer',
'null',
'undefined',
'function'
].some(function (validType) {
return validType === typeStr;
});
};
const detectType = function (value: any | null): string {
if (value === null) {
return 'null';
}
if (Array.isArray(value)) {
return 'array';
}
if (Buffer.isBuffer(value)) {
return 'buffer';
}
return typeof value;
};
const onlyUniqueValuesInArrayFilter = function (value: string, index: number, self: any) {
return self.indexOf(value) === index;
};
let detectTypeDeep = function (value: any) {
let type = detectType(value);
let typesInArray;
if (type === 'array') {
typesInArray = value
.map((element: any): string => {
return detectType(element);
})
.filter(onlyUniqueValuesInArrayFilter);
type += ' of ' + typesInArray.join(', ');
}
return type;
};
let validateArray = function (argumentValue: any, typeToCheck: string): boolean {
let allowedTypeInArray = extractTypeFromArrayOfNotation(typeToCheck);
if (detectType(argumentValue) !== 'array') {
return false;
}
return argumentValue.every(function (element: any) {
return detectType(element) === allowedTypeInArray;
});
};
export function validateArgument(methodName: string, argumentName: string, argumentValue: string|any, argumentMustBe: any): boolean {
let isOneOfAllowedTypes = argumentMustBe.some(function (type: any) {
if (!isValidTypeDefinition(type)) {
throw new Error('Unknown type "' + type + '"');
}
if (isArrayOfNotation(type)) {
return validateArray(argumentValue, type);
}
return type === detectType(argumentValue);
});
if (!isOneOfAllowedTypes) {
throw new Error('Argument "' + argumentName + '" passed to ' + methodName + ' must be '
+ prettyPrintTypes(argumentMustBe) + '. Received ' + detectTypeDeep(argumentValue));
}
return false;
};
export function validateOptions(methodName: string, optionsObjName: string, obj: any, allowedOptions: any) {
if (obj !== undefined) {
validateArgument(methodName, optionsObjName, obj, ['object']);
Object.keys(obj).forEach(function (key) {
let argName = optionsObjName + '.' + key;
if (allowedOptions.hasOwnProperty(key)) {
validateArgument(methodName, argName, obj[key], allowedOptions[key]);
} else {
throw new Error('Unknown argument "' + argName + '" passed to ' + methodName);
}
});
}
};