chore: remove old vue-types
parent
95eaf941d7
commit
3c20fc9f69
|
@ -1,263 +0,0 @@
|
|||
import isPlainObject from 'lodash-es/isPlainObject';
|
||||
import { toType, getType, isFunction, validateType, isInteger, isArray, warn } from './utils';
|
||||
|
||||
const PropTypes = {
|
||||
get any() {
|
||||
return toType('any', {
|
||||
type: null,
|
||||
});
|
||||
},
|
||||
|
||||
get func() {
|
||||
return toType('function', {
|
||||
type: Function,
|
||||
}).def(currentDefaults.func);
|
||||
},
|
||||
|
||||
get bool() {
|
||||
return toType('boolean', {
|
||||
type: Boolean,
|
||||
}).def(currentDefaults.bool);
|
||||
},
|
||||
|
||||
get string() {
|
||||
return toType('string', {
|
||||
type: String,
|
||||
}).def(currentDefaults.string);
|
||||
},
|
||||
|
||||
get number() {
|
||||
return toType('number', {
|
||||
type: Number,
|
||||
}).def(currentDefaults.number);
|
||||
},
|
||||
|
||||
get array() {
|
||||
return toType('array', {
|
||||
type: Array,
|
||||
}).def(currentDefaults.array);
|
||||
},
|
||||
|
||||
get object() {
|
||||
return toType('object', {
|
||||
type: Object,
|
||||
}).def(currentDefaults.object);
|
||||
},
|
||||
|
||||
get integer() {
|
||||
return toType('integer', {
|
||||
type: Number,
|
||||
validator(value) {
|
||||
return isInteger(value);
|
||||
},
|
||||
}).def(currentDefaults.integer);
|
||||
},
|
||||
|
||||
get symbol() {
|
||||
return toType('symbol', {
|
||||
type: null,
|
||||
validator(value) {
|
||||
return typeof value === 'symbol';
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
custom(validatorFn, warnMsg = 'custom validation failed') {
|
||||
if (typeof validatorFn !== 'function') {
|
||||
throw new TypeError('[VueTypes error]: You must provide a function as argument');
|
||||
}
|
||||
|
||||
return toType(validatorFn.name || '<<anonymous function>>', {
|
||||
validator(...args) {
|
||||
const valid = validatorFn(...args);
|
||||
if (!valid) warn(`${this._vueTypes_name} - ${warnMsg}`);
|
||||
return valid;
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
oneOf(arr) {
|
||||
if (!isArray(arr)) {
|
||||
throw new TypeError('[VueTypes error]: You must provide an array as argument');
|
||||
}
|
||||
const msg = `oneOf - value should be one of "${arr.join('", "')}"`;
|
||||
const allowedTypes = arr.reduce((ret, v) => {
|
||||
if (v !== null && v !== undefined) {
|
||||
ret.indexOf(v.constructor) === -1 && ret.push(v.constructor);
|
||||
}
|
||||
return ret;
|
||||
}, []);
|
||||
|
||||
return toType('oneOf', {
|
||||
type: allowedTypes.length > 0 ? allowedTypes : null,
|
||||
validator(value) {
|
||||
const valid = arr.indexOf(value) !== -1;
|
||||
if (!valid) warn(msg);
|
||||
return valid;
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
instanceOf(instanceConstructor) {
|
||||
return toType('instanceOf', {
|
||||
type: instanceConstructor,
|
||||
});
|
||||
},
|
||||
|
||||
oneOfType(arr) {
|
||||
if (!isArray(arr)) {
|
||||
throw new TypeError('[VueTypes error]: You must provide an array as argument');
|
||||
}
|
||||
|
||||
let hasCustomValidators = false;
|
||||
|
||||
const nativeChecks = arr.reduce((ret, type) => {
|
||||
if (isPlainObject(type)) {
|
||||
if (type._vueTypes_name === 'oneOf') {
|
||||
return ret.concat(type.type || []);
|
||||
}
|
||||
if (type.type && !isFunction(type.validator)) {
|
||||
if (isArray(type.type)) return ret.concat(type.type);
|
||||
ret.push(type.type);
|
||||
} else if (isFunction(type.validator)) {
|
||||
hasCustomValidators = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
ret.push(type);
|
||||
return ret;
|
||||
}, []);
|
||||
|
||||
if (!hasCustomValidators) {
|
||||
// we got just native objects (ie: Array, Object)
|
||||
// delegate to Vue native prop check
|
||||
return toType('oneOfType', {
|
||||
type: nativeChecks,
|
||||
}).def(undefined);
|
||||
}
|
||||
|
||||
const typesStr = arr
|
||||
.map(type => {
|
||||
if (type && isArray(type.type)) {
|
||||
return type.type.map(getType);
|
||||
}
|
||||
return getType(type);
|
||||
})
|
||||
.reduce((ret, type) => ret.concat(isArray(type) ? type : [type]), [])
|
||||
.join('", "');
|
||||
|
||||
return this.custom(function oneOfType(value) {
|
||||
const valid = arr.some(type => {
|
||||
if (type._vueTypes_name === 'oneOf') {
|
||||
return type.type ? validateType(type.type, value, true) : true;
|
||||
}
|
||||
return validateType(type, value, true);
|
||||
});
|
||||
if (!valid) warn(`oneOfType - value type should be one of "${typesStr}"`);
|
||||
return valid;
|
||||
}).def(undefined);
|
||||
},
|
||||
|
||||
arrayOf(type) {
|
||||
return toType('arrayOf', {
|
||||
type: Array,
|
||||
validator(values) {
|
||||
const valid = values.every(value => validateType(type, value));
|
||||
if (!valid) warn(`arrayOf - value must be an array of "${getType(type)}"`);
|
||||
return valid;
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
objectOf(type) {
|
||||
return toType('objectOf', {
|
||||
type: Object,
|
||||
validator(obj) {
|
||||
const valid = Object.keys(obj).every(key => validateType(type, obj[key]));
|
||||
if (!valid) warn(`objectOf - value must be an object of "${getType(type)}"`);
|
||||
return valid;
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
shape(obj) {
|
||||
const keys = Object.keys(obj);
|
||||
const requiredKeys = keys.filter(key => obj[key] && obj[key].required === true);
|
||||
|
||||
const type = toType('shape', {
|
||||
type: Object,
|
||||
validator(value) {
|
||||
if (!isPlainObject(value)) {
|
||||
return false;
|
||||
}
|
||||
const valueKeys = Object.keys(value);
|
||||
|
||||
// check for required keys (if any)
|
||||
if (requiredKeys.length > 0 && requiredKeys.some(req => valueKeys.indexOf(req) === -1)) {
|
||||
warn(
|
||||
`shape - at least one of required properties "${requiredKeys.join(
|
||||
'", "',
|
||||
)}" is not present`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return valueKeys.every(key => {
|
||||
if (keys.indexOf(key) === -1) {
|
||||
if (this._vueTypes_isLoose === true) return true;
|
||||
warn(`shape - object is missing "${key}" property`);
|
||||
return false;
|
||||
}
|
||||
const type = obj[key];
|
||||
return validateType(type, value[key]);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(type, '_vueTypes_isLoose', {
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: false,
|
||||
});
|
||||
|
||||
Object.defineProperty(type, 'loose', {
|
||||
get() {
|
||||
this._vueTypes_isLoose = true;
|
||||
return this;
|
||||
},
|
||||
enumerable: false,
|
||||
});
|
||||
|
||||
return type;
|
||||
},
|
||||
};
|
||||
|
||||
const typeDefaults = () => ({
|
||||
func: undefined,
|
||||
bool: undefined,
|
||||
string: undefined,
|
||||
number: undefined,
|
||||
array: undefined,
|
||||
object: undefined,
|
||||
integer: undefined,
|
||||
});
|
||||
|
||||
let currentDefaults = typeDefaults();
|
||||
|
||||
Object.defineProperty(PropTypes, 'sensibleDefaults', {
|
||||
enumerable: false,
|
||||
set(value) {
|
||||
if (value === false) {
|
||||
currentDefaults = {};
|
||||
} else if (value === true) {
|
||||
currentDefaults = typeDefaults();
|
||||
} else if (isPlainObject(value)) {
|
||||
currentDefaults = value;
|
||||
}
|
||||
},
|
||||
get() {
|
||||
return currentDefaults;
|
||||
},
|
||||
});
|
||||
|
||||
export default PropTypes;
|
|
@ -1,222 +0,0 @@
|
|||
import { PropOptions } from '../type';
|
||||
import isPlainObject from 'lodash-es/isPlainObject';
|
||||
|
||||
const ObjProto = Object.prototype;
|
||||
const toString = ObjProto.toString;
|
||||
export const hasOwn = ObjProto.hasOwnProperty;
|
||||
|
||||
export type NativeType = string | boolean | number | null | undefined | Function;
|
||||
|
||||
export type DefaultFactory<T> = (() => T) | T;
|
||||
|
||||
export type InferType<T> = T extends NativeType ? T : DefaultFactory<T>;
|
||||
|
||||
export interface TypeDef<T = unknown, D = InferType<T>, U = T extends NativeType ? T : () => T>
|
||||
extends PropOptions<T> {
|
||||
_vueTypes_name: string;
|
||||
readonly def: (def?: D) => this & { default: U };
|
||||
readonly isRequired: this & { required: true };
|
||||
}
|
||||
|
||||
const FN_MATCH_REGEXP = /^\s*function (\w+)/;
|
||||
|
||||
// https://github.com/vuejs/vue/blob/dev/src/core/util/props.js#L159
|
||||
export const getType = fn => {
|
||||
const type = fn !== null && fn !== undefined ? (fn.type ? fn.type : fn) : null;
|
||||
const match = type && type.toString().match(FN_MATCH_REGEXP);
|
||||
return match && match[1];
|
||||
};
|
||||
|
||||
export const getNativeType = (value: any) => {
|
||||
if (value === null || value === undefined) return null;
|
||||
const match = value.constructor.toString().match(FN_MATCH_REGEXP);
|
||||
return match && match[1];
|
||||
};
|
||||
|
||||
/**
|
||||
* No-op function
|
||||
*/
|
||||
export const noop = () => {};
|
||||
|
||||
/**
|
||||
* Checks for a own property in an object
|
||||
*
|
||||
* @param {object} obj - Object
|
||||
* @param {string} prop - Property to check
|
||||
*/
|
||||
export const has = <T extends any, U extends keyof T>(obj: T, prop: U) => hasOwn.call(obj, prop);
|
||||
|
||||
/**
|
||||
* Determines whether the passed value is an integer. Uses `Number.isInteger` if available
|
||||
*
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
|
||||
* @param {*} value - The value to be tested for being an integer.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isInteger =
|
||||
Number.isInteger ||
|
||||
function(value: unknown): value is number {
|
||||
return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether the passed value is an Array.
|
||||
*
|
||||
* @param {*} value - The value to be tested for being an array.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isArray =
|
||||
Array.isArray ||
|
||||
function(value: unknown): value is any[] {
|
||||
return toString.call(value) === '[object Array]';
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a value is a function
|
||||
*
|
||||
* @param {any} value - Value to check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isFunction = (value: unknown): value is Function =>
|
||||
toString.call(value) === '[object Function]';
|
||||
|
||||
/**
|
||||
* Adds a `def` method to the object returning a new object with passed in argument as `default` property
|
||||
*
|
||||
* @param {object} type - Object to enhance
|
||||
*/
|
||||
export const withDefault = function<T>(type: T) {
|
||||
Object.defineProperty(type, 'def', {
|
||||
value(def: T) {
|
||||
if (def === undefined && this.default === undefined) {
|
||||
this.default = undefined;
|
||||
return this;
|
||||
}
|
||||
if (!isFunction(def) && !validateType(this, def)) {
|
||||
warn(`${this._vueTypes_name} - invalid default value: "${def}"`);
|
||||
return this;
|
||||
}
|
||||
this.default =
|
||||
isArray(def) || isPlainObject(def)
|
||||
? function() {
|
||||
return def;
|
||||
}
|
||||
: def;
|
||||
|
||||
return this;
|
||||
},
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a `isRequired` getter returning a new object with `required: true` key-value
|
||||
*
|
||||
* @param {object} type - Object to enhance
|
||||
*/
|
||||
export const withRequired = function<T>(type: T) {
|
||||
Object.defineProperty(type, 'isRequired', {
|
||||
get() {
|
||||
this.required = true;
|
||||
return this;
|
||||
},
|
||||
enumerable: false,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds `isRequired` and `def` modifiers to an object
|
||||
*
|
||||
* @param {string} name - Type internal name
|
||||
* @param {object} obj - Object to enhance
|
||||
* @returns {object}
|
||||
*/
|
||||
export const toType = <T extends any>(name: string, obj: PropOptions<T>): TypeDef<T> => {
|
||||
Object.defineProperty(obj, '_vueTypes_name', {
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
value: name,
|
||||
});
|
||||
withRequired(obj);
|
||||
withDefault(obj);
|
||||
|
||||
if (isFunction(obj.validator)) {
|
||||
obj.validator = obj.validator.bind(obj);
|
||||
}
|
||||
return obj as TypeDef<T>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates a given value against a prop type object
|
||||
*
|
||||
* @param {Object|*} type - Type to use for validation. Either a type object or a constructor
|
||||
* @param {*} value - Value to check
|
||||
* @param {boolean} silent - Silence warnings
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const validateType = (type, value, silent = false) => {
|
||||
let typeToCheck = type;
|
||||
let valid = true;
|
||||
let expectedType;
|
||||
if (!isPlainObject(type)) {
|
||||
typeToCheck = { type };
|
||||
}
|
||||
const namePrefix = typeToCheck._vueTypes_name ? typeToCheck._vueTypes_name + ' - ' : '';
|
||||
|
||||
if (hasOwn.call(typeToCheck, 'type') && typeToCheck.type !== null) {
|
||||
if (isArray(typeToCheck.type)) {
|
||||
valid = typeToCheck.type.some(type => validateType(type, value, true));
|
||||
expectedType = typeToCheck.type.map(type => getType(type)).join(' or ');
|
||||
} else {
|
||||
expectedType = getType(typeToCheck);
|
||||
|
||||
if (expectedType === 'Array') {
|
||||
valid = isArray(value);
|
||||
} else if (expectedType === 'Object') {
|
||||
valid = isPlainObject(value);
|
||||
} else if (
|
||||
expectedType === 'String' ||
|
||||
expectedType === 'Number' ||
|
||||
expectedType === 'Boolean' ||
|
||||
expectedType === 'Function'
|
||||
) {
|
||||
valid = getNativeType(value) === expectedType;
|
||||
} else {
|
||||
valid = value instanceof typeToCheck.type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
silent === false && warn(`${namePrefix}value "${value}" should be of type "${expectedType}"`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hasOwn.call(typeToCheck, 'validator') && isFunction(typeToCheck.validator)) {
|
||||
valid = typeToCheck.validator(value);
|
||||
if (!valid && silent === false) warn(`${namePrefix}custom validation failed`);
|
||||
return valid;
|
||||
}
|
||||
return valid;
|
||||
};
|
||||
|
||||
/**
|
||||
* A function that returns its first argument
|
||||
*
|
||||
* @param arg - Any argument
|
||||
*/
|
||||
export const identity = (arg: any) => arg;
|
||||
|
||||
let warn: (msg: string) => string | void = identity;
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
const hasConsole = typeof console !== 'undefined';
|
||||
warn = msg => {
|
||||
if (hasConsole) {
|
||||
console.warn(`[VueTypes warn]: ${msg}`);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export { warn };
|
Loading…
Reference in New Issue