nativemodels
Advanced tools
| const defaultOptions = require('./lib/defaultOptions'); | ||
| const defaultRecord = require('./lib/defaultRecord'); | ||
| const mapRecord = require('./lib/mapRecord'); | ||
| const parseRecord = require('./lib/parseRecord'); | ||
| const proxyHandler = require('./lib/proxyHandler'); | ||
| const recaseKeys = require('./lib/recaseKeys'); | ||
| const requireAllKeys = require('./lib/requireAllKeys'); | ||
| const requiredCheck = require('./lib/requiredCheck'); | ||
| const stripUndefinedKeys = require('./lib/stripUndefinedKeys'); | ||
| const transformRecord = require('./lib/transformRecord'); | ||
| const buildRecord = (schema, record, options) => { | ||
| const mappedRecord = mapRecord(schema, record, options.caseSensitive); | ||
| const transformedRecord = transformRecord(schema, mappedRecord); | ||
| const stripedRecord = options.stripUndefined ? stripUndefinedKeys(schema, transformedRecord) : transformedRecord; | ||
| const casedRecord = options.caseSensitive ? stripedRecord : recaseKeys(schema, stripedRecord); | ||
| const defaultedRecord = defaultRecord(schema, casedRecord); | ||
| return defaultedRecord; | ||
| }; | ||
| const createModel = (schema, modelOptions = {}, context = {}) => (record = {}) => { | ||
| const options = { ...defaultOptions, ...modelOptions }; | ||
| const builtRecord = buildRecord(schema, record, options); | ||
| if (options.strict) { | ||
| requireAllKeys(schema, builtRecord); | ||
| } | ||
| requiredCheck(schema, builtRecord); | ||
| const proxyTarget = parseRecord(schema, builtRecord, options); | ||
| return new Proxy(proxyTarget, proxyHandler(schema, options, context)); | ||
| }; | ||
| module.exports = createModel; |
| const base = require('./datatypes/base'); | ||
| const createType = (overrides, extended = base()) => ({ | ||
| ...extended, | ||
| ...overrides, | ||
| }); | ||
| module.exports = createType; |
| /* eslint max-len: off, no-control-regex: off */ | ||
| const regex = require('./regex'); | ||
| const email = () => | ||
| regex( | ||
| /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/iu, | ||
| 'email', | ||
| ); | ||
| module.exports = email; |
| const createType = require('./../createType'); | ||
| const enumerable = (enumerableValues) => | ||
| createType({ | ||
| name: 'enumerable', | ||
| validCheck: (key, value) => { | ||
| if (enumerableValues.indexOf(value) > -1) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not in the list of enumerable values`); | ||
| }, | ||
| }); | ||
| module.exports = enumerable; |
| const createType = require('./../createType'); | ||
| const guid = () => | ||
| createType({ | ||
| name: 'guid', | ||
| parse: (key, value) => value.toUpperCase(), | ||
| validCheck: (key, value) => { | ||
| if (value === '00000000-0000-0000-0000-000000000000') { | ||
| return true; | ||
| } else if (/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(value)) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not a GUID`); | ||
| }, | ||
| }); | ||
| module.exports = guid; |
| const email = require('./email'); | ||
| const enumerable = require('./enumerable'); | ||
| const guid = require('./guid'); | ||
| const phone = require('./phone'); | ||
| const regex = require('./regex'); | ||
| const url = require('./url'); | ||
| module.exports = { | ||
| email, | ||
| enumerable, | ||
| guid, | ||
| phone, | ||
| regex, | ||
| url, | ||
| }; |
| const regex = require('./regex'); | ||
| const phone = () => regex(/^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/iu, 'phone'); | ||
| module.exports = phone; |
| const createType = require('./../createType'); | ||
| const { isRegex } = require('./../lib/checks/types'); | ||
| const regex = (expression, typeName) => | ||
| createType({ | ||
| name: typeName, | ||
| validCheck: (key, value) => { | ||
| if (isRegex(expression) && expression.test(value)) { | ||
| return true; | ||
| } | ||
| if (!isRegex(expression)) { | ||
| throw new Error(`NativeModels - Regex expression provided isn't a valid regex`); | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} (${value}) is not a/an ${typeName}`); | ||
| }, | ||
| }); | ||
| module.exports = regex; |
| const regex = require('./regex'); | ||
| const url = () => regex(/^(https?|ftp):\/\/(-\.)?([^\s/?.#]+\.?)+(\/[^\s]*)?$/iu, 'url'); | ||
| module.exports = url; |
| const createType = require('./../createType'); | ||
| const any = () => createType({ name: 'any' }); | ||
| module.exports = any; |
| const createType = require('./../createType'); | ||
| const parseValue = require('./../lib/parseValue'); | ||
| const { isArray } = require('./../lib/checks/types'); | ||
| const array = (type) => | ||
| createType({ | ||
| name: 'array', | ||
| parse: (key, values, parentOptions) => values.map((value) => parseValue(type, key, value, parentOptions)), | ||
| validCheck: (key, value) => { | ||
| if (isArray(value)) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not an array`); | ||
| }, | ||
| }); | ||
| module.exports = array; |
| const overrides = { | ||
| name: 'base', | ||
| parse: (key, value) => value, | ||
| requiredCheck: (key, value) => { | ||
| if (value) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property: '${key}' is required`); | ||
| }, | ||
| strictCheck: () => true, | ||
| validCheck: () => true, | ||
| }; | ||
| const chainable = { | ||
| default(value) { | ||
| this.hasDefault = true; | ||
| this.defaultValue = value; | ||
| return this; | ||
| }, | ||
| from(key, options = {}) { | ||
| this.fromKeys = Array.isArray(key) ? key : [key]; | ||
| this.fromOptions = options; | ||
| return this; | ||
| }, | ||
| nullable() { | ||
| this.allowNull = true; | ||
| return this; | ||
| }, | ||
| required() { | ||
| this.isRequired = true; | ||
| return this; | ||
| }, | ||
| strict() { | ||
| this.requireStrict = true; | ||
| return this; | ||
| }, | ||
| transform(fn, type = 'post') { | ||
| this.transforms = this.transforms || {}; | ||
| this.transforms[type] = fn; | ||
| return this; | ||
| }, | ||
| }; | ||
| const base = () => ({ | ||
| ...overrides, | ||
| ...chainable, | ||
| }); | ||
| module.exports = base; |
| const createType = require('./../createType'); | ||
| const { isBoolean, isUndefined } = require('./../lib/checks/types'); | ||
| const boolean = () => | ||
| createType({ | ||
| name: 'boolean', | ||
| parse: (key, value) => Boolean(value), | ||
| requiredCheck: (key, value) => { | ||
| if (isUndefined(value) || value === '' || value === null) { | ||
| throw new Error(`NativeModels - Property: '${key}' is required`); | ||
| } | ||
| return true; | ||
| }, | ||
| strictCheck: (key, value) => { | ||
| if (isBoolean(value)) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not a boolean`); | ||
| }, | ||
| }); | ||
| module.exports = boolean; |
| const createType = require('./../createType'); | ||
| const { isBuffer } = require('./../lib/checks/types'); | ||
| const bufferCheck = (key, value, strict) => { | ||
| if (isBuffer(value)) { | ||
| return true; | ||
| } | ||
| if (!strict && isBuffer(Buffer.from(value))) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not a buffer`); | ||
| }; | ||
| const buffer = () => | ||
| createType({ | ||
| name: 'buffer', | ||
| parse: (key, value) => Buffer.from(value), | ||
| strictCheck: (key, value) => bufferCheck(key, value, true), | ||
| validCheck: (key, value) => bufferCheck(key, value), | ||
| }); | ||
| module.exports = buffer; |
| const createType = require('./../createType'); | ||
| const createModel = require('./../createModel'); | ||
| const parseValue = (type, key, value) => createModel({ [key]: type })({ [key]: value })[key]; | ||
| const getOverridedValue = (type, key, record) => (type ? parseValue(type, key, record[key]) : record[key]); | ||
| const isAsync = (fn) => fn && (fn.then || fn.constructor.name === 'AsyncFunction'); | ||
| const resolve = (response, type, key) => Promise.resolve(response).then((value) => parseValue(type, key, value)); | ||
| const computeWithType = (userFn, type, { context, key, record }) => { | ||
| if (isAsync(userFn)) { | ||
| return resolve(userFn(record, key), type, key, context); | ||
| } | ||
| const response = userFn(record, key, context); | ||
| return isAsync(response) ? resolve(response, type, key) : parseValue(type, key, response); | ||
| }; | ||
| const computed = (userFn, type, options = { allowOverride: false }) => | ||
| createType({ | ||
| fn: (record, key, context) => { | ||
| if (options.allowOverride && record[key]) { | ||
| return getOverridedValue(type, key, record); | ||
| } else if (type) { | ||
| return computeWithType(userFn, type, { context, key, record }); | ||
| } | ||
| return userFn(record, key, context); | ||
| }, | ||
| name: 'computed', | ||
| type: options.allowOverride ? type : undefined, | ||
| }); | ||
| module.exports = computed; |
| const createType = require('./../createType'); | ||
| const { isDate } = require('./../lib/checks/types'); | ||
| const isValidDate = (key, value, strict = false) => { | ||
| if (isDate(value)) { | ||
| return true; | ||
| } | ||
| if (!strict) { | ||
| const test = new Date(value); | ||
| if (value && test instanceof Date && !isNaN(test)) { | ||
| return true; | ||
| } | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not a date`); | ||
| }; | ||
| const date = () => | ||
| createType({ | ||
| name: 'date', | ||
| parse: (key, value) => (value instanceof Date ? value : new Date(value)), | ||
| strictCheck: (key, value) => isValidDate(key, value, true), | ||
| validCheck: (key, value) => isValidDate(key, value), | ||
| }); | ||
| module.exports = date; |
| const createType = require('./../createType'); | ||
| const { isNumber } = require('./../lib/checks/types'); | ||
| const int = require('./int'); | ||
| const isValidFloat = (key, value, strict = false) => { | ||
| if (isNumber(value)) { | ||
| return true; | ||
| } | ||
| if (!strict) { | ||
| if (!isNaN(parseFloat(value)) && value !== true && value !== false && value !== '') { | ||
| return true; | ||
| } | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not a float`); | ||
| }; | ||
| const float = () => | ||
| createType( | ||
| { | ||
| name: 'float', | ||
| parse: (key, value) => parseFloat(value), | ||
| strictCheck: (key, value) => isValidFloat(key, value, true), | ||
| validCheck: (key, value) => isValidFloat(key, value), | ||
| }, | ||
| int(), | ||
| ); | ||
| module.exports = float; |
| const any = require('./any'); | ||
| const array = require('./array'); | ||
| const base = require('./base'); | ||
| const boolean = require('./boolean'); | ||
| const buffer = require('./buffer'); | ||
| const computed = require('./computed'); | ||
| const date = require('./date'); | ||
| const float = require('./float'); | ||
| const int = require('./int'); | ||
| const object = require('./object'); | ||
| const string = require('./string'); | ||
| module.exports = { | ||
| any, | ||
| array, | ||
| base, | ||
| boolean, | ||
| buffer, | ||
| computed, | ||
| date, | ||
| float, | ||
| int, | ||
| object, | ||
| string, | ||
| }; |
| const createType = require('./../createType'); | ||
| const isValidInt = (key, value, strict = false) => { | ||
| if (Number.isInteger(value)) { | ||
| return true; | ||
| } | ||
| if (!strict && Number.isInteger(parseInt(value)) && parseInt(value) === parseFloat(value)) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not an int`); | ||
| }; | ||
| const int = () => | ||
| createType({ | ||
| name: 'int', | ||
| parse: (key, value) => parseInt(value), | ||
| requiredCheck: (key, value) => { | ||
| if (value || value === 0) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property: '${key}' is required`); | ||
| }, | ||
| strictCheck: (key, value) => isValidInt(key, value, true), | ||
| validCheck: (key, value) => isValidInt(key, value), | ||
| }); | ||
| module.exports = int; |
| const createType = require('./../createType'); | ||
| const createModel = require('./../createModel'); | ||
| const { isObject } = require('./../lib/checks/types'); | ||
| const object = (schema, options) => | ||
| createType({ | ||
| name: 'object', | ||
| parse: (key, value, parentOptions) => | ||
| schema ? createModel(schema, { ...parentOptions, ...options })(value) : value, | ||
| validCheck: (key, value) => { | ||
| if (isObject(value)) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not an object`); | ||
| }, | ||
| }); | ||
| module.exports = object; |
| const createType = require('./../createType'); | ||
| const { isString } = require('./../lib/checks/types'); | ||
| const strictCheck = (key, value, options) => { | ||
| if (isString(value)) { | ||
| if (options.length && value.length > options.length) { | ||
| throw new Error(`NativeModels - Property ${key} is longer than ${options.length}`); | ||
| } | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not a string`); | ||
| }; | ||
| const validCheck = (key, value) => { | ||
| if (value === null) { | ||
| throw new Error(`NativeModels - Property ${key} is not a string`); | ||
| } | ||
| return true; | ||
| }; | ||
| const string = (options = {}) => | ||
| createType({ | ||
| name: 'string', | ||
| parse: (key, value) => { | ||
| if (options.length) { | ||
| return `${value}`.slice(0, options.length); | ||
| } | ||
| return `${value}`; | ||
| }, | ||
| strictCheck: (key, value) => strictCheck(key, value, options), | ||
| validCheck, | ||
| }); | ||
| module.exports = string; |
| const customtypes = require('./customtypes'); | ||
| const datatypes = require('./datatypes'); | ||
| const generateType = require('./lib/type/generate'); | ||
| module.exports = (schema, usertypes = {}, fns = {}) => { | ||
| const obj = typeof schema === 'string' ? JSON.parse(schema) : schema; | ||
| const types = { ...datatypes, ...customtypes, ...usertypes }; | ||
| return Object.keys(obj).reduce((result, key) => ({ ...result, [key]: generateType(obj[key], types, fns) }), {}); | ||
| }; |
+20
| const createModel = require('./createModel'); | ||
| const createType = require('./createType'); | ||
| const customtypes = require('./customtypes'); | ||
| const datatypes = require('./datatypes'); | ||
| const generateSchema = require('./generateSchema'); | ||
| const resolve = require('./resolve'); | ||
| /* istanbul ignore next */ | ||
| const resolver = (data, schema) => | ||
| console.warn('DEPRECATION NOTICE: Please use resolve() instead of resolver()') || resolve(data, schema); | ||
| module.exports = { | ||
| createModel, | ||
| createType, | ||
| customtypes, | ||
| datatypes, | ||
| generateSchema, | ||
| resolve, | ||
| resolver, | ||
| }; |
| const invalidTypeCheck = (type, key) => { | ||
| if (!type.validCheck || !type.parse) { | ||
| console.log(`Schema Key: '${key}' is not a valid datatype or customtype`); | ||
| return true; | ||
| } | ||
| return false; | ||
| }; | ||
| module.exports = invalidTypeCheck; |
| const requiredCheck = (type, key, value) => (type.isRequired ? type.requiredCheck(key, value) : true); | ||
| module.exports = requiredCheck; |
| const strictCheck = (type, key, value) => | ||
| type.requireStrict && type.strictCheck ? type.strictCheck(key, value) : true; | ||
| module.exports = strictCheck; |
| // Pre ES5 => value && typeof value === 'object' && value.constructor === Array; | ||
| const isArray = (value) => Array.isArray(value); | ||
| const isBoolean = (value) => typeof value === 'boolean'; | ||
| const isBuffer = (value) => Buffer.isBuffer(value); | ||
| const isDate = (value) => value instanceof Date; | ||
| // const isError = (value) => value instanceof Error && typeof value.message !== 'undefined'; | ||
| // const isFunction = (value) => typeof value === 'function'; | ||
| const isNull = (value) => value === null; | ||
| const isNumber = (value) => typeof value === 'number' && isFinite(value); | ||
| const isObject = (value) => value && typeof value === 'object' && value.constructor === Object; | ||
| const isRegex = (value) => value && typeof value === 'object' && value.constructor === RegExp; | ||
| const isString = (value) => typeof value === 'string' || value instanceof String; | ||
| // const isSymbol = (value) => typeof value === 'symbol'; | ||
| const isUndefined = (value) => typeof value === 'undefined'; | ||
| module.exports = { | ||
| isArray, | ||
| isBoolean, | ||
| isBuffer, | ||
| isDate, | ||
| // isError, | ||
| // isFunction, | ||
| isNull, | ||
| isNumber, | ||
| isObject, | ||
| isRegex, | ||
| isString, | ||
| // isSymbol, | ||
| isUndefined, | ||
| }; |
| const validCheck = (type, key, value) => type.validCheck(key, value); | ||
| module.exports = validCheck; |
| const defaultOptions = { | ||
| // Allow nulls on all columns | ||
| allowNulls: false, | ||
| // Ignores case when initializing object from model | ||
| caseSensitive: true, | ||
| // Pass options to all children | ||
| passOptions: false, | ||
| // Throws an error if key is not in schema | ||
| strict: false, | ||
| // Strip undefined values passed in | ||
| stripUndefined: true, | ||
| }; | ||
| module.exports = defaultOptions; |
| const defaultValue = require('./defaultValue'); | ||
| const defaultRecord = (schema, record) => ({ | ||
| ...record, | ||
| ...Object.keys(schema).reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| ...(schema[key].hasDefault ? { [key]: record[key] || defaultValue(schema[key].defaultValue) } : {}), | ||
| }), | ||
| {}, | ||
| ), | ||
| }); | ||
| module.exports = defaultRecord; |
| const defaultValue = (value) => (typeof value === 'function' ? value() : value); | ||
| module.exports = defaultValue; |
| const recaseRecord = (record) => | ||
| Object.keys(record).reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| [key.toLowerCase()]: record[key], | ||
| }), | ||
| {}, | ||
| ); | ||
| const getFromKeyValue = (schema, record, { caseSensitive, key }) => { | ||
| const { | ||
| fromOptions: { caseSensitive: fromOptionsCaseSensitive }, | ||
| } = schema[key]; | ||
| const lowerCase = typeof fromOptionsCaseSensitive === 'undefined' ? !caseSensitive : !fromOptionsCaseSensitive; | ||
| const fromKeys = [key, ...schema[key].fromKeys].map((key) => (lowerCase ? key.toLowerCase() : key)); | ||
| const recasedRecord = lowerCase ? recaseRecord(record) : record; | ||
| const value = fromKeys.find((fromKey) => typeof recasedRecord[fromKey] !== 'undefined'); | ||
| return recasedRecord[value]; | ||
| }; | ||
| const mapRecord = (schema, record, caseSensitive) => ({ | ||
| ...record, | ||
| ...Object.keys(schema) | ||
| .filter((key) => schema[key].fromKeys) | ||
| .reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| ...{ [key]: getFromKeyValue(schema, record, { caseSensitive, key }) }, | ||
| }), | ||
| {}, | ||
| ), | ||
| }); | ||
| module.exports = mapRecord; |
| const parseValue = require('./parseValue'); | ||
| const parseRecord = (schema, record, options) => | ||
| Object.keys(record).reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| ...(schema[key] ? { [key]: parseValue(schema[key], key, record[key], options) } : {}), | ||
| }), | ||
| {}, | ||
| ); | ||
| module.exports = parseRecord; |
| /* eslint-disable max-params */ | ||
| const invalidTypeCheck = require('./checks/invalidType'); | ||
| const { isNull } = require('./checks/types'); | ||
| const transformValue = require('./transformValue'); | ||
| const checks = { | ||
| required: require('./checks/required'), | ||
| strict: require('./checks/strict'), | ||
| valid: require('./checks/valid'), | ||
| }; | ||
| const runChecks = (type, key, value) => { | ||
| Object.keys(checks).forEach((name) => { | ||
| if (!checks[name](type, key, value)) { | ||
| throw new Error(`NativeModels - Failed ${name} check. Key: ${key} | Value: ${value}`); | ||
| } | ||
| }); | ||
| }; | ||
| const parseValue = (type, key, value, options) => { | ||
| if ((type.allowNull || (options && options.allowNulls)) && isNull(value)) { | ||
| return null; | ||
| } else if (invalidTypeCheck(type, key, value)) { | ||
| return value; | ||
| } | ||
| runChecks(type, key, value); | ||
| const parsedValue = type.parse(key, value, options && options.passOptions ? options : {}); | ||
| return transformValue(type, parsedValue, 'post'); | ||
| }; | ||
| module.exports = parseValue; |
| /* eslint max-params: off */ | ||
| const parseValue = require('./parseValue'); | ||
| const get = (schema, target, property, context) => { | ||
| if (schema[property]) { | ||
| return schema[property].fn ? schema[property].fn(target, property, context) : target[property]; | ||
| } | ||
| return undefined; | ||
| }; | ||
| const getOwnPropertyDescriptor = (schema, target, property) => | ||
| schema[property] | ||
| ? { | ||
| configurable: true, | ||
| enumerable: true, | ||
| value: schema[property].fn ? '[computedValue]' : target[property], | ||
| writable: true, | ||
| } | ||
| : undefined; | ||
| const ownKeys = (schema, target) => { | ||
| const allKeys = [...Object.keys(target), ...Object.keys(schema).filter((key) => schema[key].fn)]; | ||
| return [...new Set(allKeys)]; | ||
| }; | ||
| const set = (schema, target, property, value, options) => { | ||
| if (!schema[property]) { | ||
| throw new Error(`NativeModels - ${property} is not a property of model`); | ||
| } | ||
| const type = schema[property].fn && schema[property].type ? schema[property].type : schema[property]; | ||
| target[property] = parseValue(type, property, value, options); | ||
| return true; | ||
| }; | ||
| const proxyHandler = (schema, options, context) => ({ | ||
| get: (target, property) => get(schema, target, property, context), | ||
| getOwnPropertyDescriptor: (target, property) => getOwnPropertyDescriptor(schema, target, property), | ||
| ownKeys: (target) => ownKeys(schema, target), | ||
| set: (target, property, value) => set(schema, target, property, value, options), | ||
| }); | ||
| module.exports = proxyHandler; |
| const recaseKeys = (schema, record) => { | ||
| const keyMap = Object.keys(schema).reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| [key.toLowerCase()]: key, | ||
| }), | ||
| {}, | ||
| ); | ||
| return Object.keys(record).reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| [keyMap[key.toLowerCase()] || key]: record[key], | ||
| }), | ||
| {}, | ||
| ); | ||
| }; | ||
| module.exports = recaseKeys; |
| const strictCheck = (schema, record) => | ||
| Object.keys(record).forEach((key) => { | ||
| if (!schema[key]) { | ||
| throw new Error(`NativeModels - Property: '${key}' is not defined in the schema`); | ||
| } | ||
| }); | ||
| module.exports = strictCheck; |
| const required = require('./checks/required'); | ||
| const requiredCheck = (schema, record) => | ||
| Object.keys(schema).forEach((key) => { | ||
| required(schema[key], key, record[key]); | ||
| }); | ||
| module.exports = requiredCheck; |
| const stripUndefinedKeys = (schema, record) => | ||
| Object.keys(record).reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| ...(typeof record[key] === 'undefined' ? {} : { [key]: record[key] }), | ||
| }), | ||
| {}, | ||
| ); | ||
| module.exports = stripUndefinedKeys; |
| const transformValue = require('./transformValue'); | ||
| const transformRecord = (schema, record) => | ||
| Object.keys(record).reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| [key]: schema[key] ? transformValue(schema[key], record[key], 'pre') : record[key], | ||
| }), | ||
| {}, | ||
| ); | ||
| module.exports = transformRecord; |
| const transformValue = (type, value, key) => | ||
| type.transforms && type.transforms[key] ? type.transforms[key](value) : value; | ||
| module.exports = transformValue; |
| module.exports = (value, types, fns) => { | ||
| if (value.type === 'computed') { | ||
| return types[value.type](fns[value.fn]); | ||
| } else if (value.type === 'object') { | ||
| return types[value.type](require('./../../generateSchema')(value.schema, types, fns)); | ||
| } else if (value.type === 'array') { | ||
| return types[value.type](require('./generate')(value.item, types, fns)); | ||
| } | ||
| return types[value.type](); | ||
| }; |
| module.exports = (value, type, fns) => { | ||
| value.default && type.default(value.default); | ||
| value.nullable && type.nullable(); | ||
| value.required && type.required(); | ||
| value.strict && type.strict(); | ||
| value.transform && type.transform(fns[value.transform]); | ||
| return type; | ||
| }; |
| const buildType = require('./build'); | ||
| const extendType = require('./extend'); | ||
| module.exports = (value, types, fns) => { | ||
| if (typeof value === 'string') { | ||
| if (types[value]) { | ||
| return types[value](); | ||
| } | ||
| throw new Error(`NativeModels - ${value} is not a valid type`); | ||
| } else if (types[value.type]) { | ||
| const type = buildType(value, types, fns); | ||
| return extendType(value, type, fns); | ||
| } | ||
| throw new Error(`NativeModels - ${value} is not a valid type`); | ||
| }; |
| /* eslint-disable no-use-before-define */ | ||
| const { isArray, isObject } = require('./lib/checks/types'); | ||
| const createModel = require('./createModel'); | ||
| const cascadeResolve = (value) => { | ||
| if (isArray(value)) { | ||
| return Promise.all(value.map(cascadeResolve)); | ||
| } else if (isObject(value) && !value.then) { | ||
| return resolve(value); | ||
| } | ||
| return value; | ||
| }; | ||
| const resolved = (keys, values, schema) => { | ||
| const data = keys.reduce((result, key, index) => ({ ...result, [key]: values[index] }), {}); | ||
| return schema ? createModel(schema)(data) : data; | ||
| }; | ||
| const resolve = (data, schema) => { | ||
| const keys = Object.keys(data); | ||
| return Promise.all(keys.map((key) => cascadeResolve(data[key]))).then((values) => resolved(keys, values, schema)); | ||
| }; | ||
| module.exports = resolve; |
+12
-15
@@ -9,15 +9,12 @@ { | ||
| "devDependencies": { | ||
| "codecov": "^3.5.0", | ||
| "eslint": "^6.1.0", | ||
| "eslint-config-prettier": "^6.0.0", | ||
| "eslint-plugin-jest": "^22.14.0", | ||
| "eslint-plugin-react": "^7.14.3", | ||
| "gh-pages": "^2.0.1", | ||
| "husky": "^3.0.1", | ||
| "jest": "^24.8.0", | ||
| "jest-junit": "^7.0.0", | ||
| "js-yaml": "^3.13.1", | ||
| "lint-staged": "^9.2.1", | ||
| "lodash.isequal": "^4.5.0", | ||
| "prettier": "^1.18.2" | ||
| "eslint": "6.7.2", | ||
| "eslint-config-prettier": "6.7.0", | ||
| "eslint-plugin-jest": "23.1.1", | ||
| "gh-pages": "2.1.1", | ||
| "husky": "3.1.0", | ||
| "jest": "24.9.0", | ||
| "js-yaml": "3.13.1", | ||
| "lint-staged": "9.5.0", | ||
| "lodash.isequal": "4.5.0", | ||
| "prettier": "1.19.1" | ||
| }, | ||
@@ -56,5 +53,5 @@ "engines": { | ||
| "staged": "lint-staged", | ||
| "test": "jest --coverage" | ||
| "test": "./node_modules/.bin/jest" | ||
| }, | ||
| "version": "2.8.0" | ||
| "version": "2.8.1" | ||
| } |
+9
-41
@@ -10,44 +10,12 @@ <h1 align="center"> | ||
| <!-- NPM --> | ||
| [](https://npmjs.org/package/nativemodels) | ||
| [](https://npmjs.org/package/nativemodels) | ||
| [](https://npmjs.org/package/nativemodels) | ||
| [](https://npmjs.org/package/nativemodels) | ||
| [](https://github.com/Prefinem/nativemodels/actions) [](https://codeclimate.com/github/Prefinem/nativemodels/maintainability) [](https://codecov.io/gh/Prefinem/nativemodels) | ||
| <!-- GitHub --> | ||
|  | ||
| [](https://github.com/Prefinem/nativemodels) | ||
| [](https://github.com/Prefinem/nativemodels) | ||
| [](https://github.com/Prefinem/nativemodels) | ||
|   | ||
| <!-- Dependencies --> | ||
|   | ||
| [](https://david-dm.org/Prefinem/nativemodels) | ||
| [](https://david-dm.org/Prefinem/nativemodels?type=dev) | ||
| [](https://david-dm.org/Prefinem/nativemodels?type=peer) | ||
| <!-- PackagePhobia --> | ||
| [](https://packagephobia.now.sh/result?p=nativemodels) | ||
| [](https://packagephobia.now.sh/result?p=nativemodels) | ||
| <!-- Travis --> | ||
| [](https://travis-ci.com/Prefinem/nativemodels) | ||
| <!-- CircleCI --> | ||
| [](https://circleci.com/gh/Prefinem/nativemodels) | ||
| <!-- CodeCov --> | ||
| [](https://codecov.io/gh/Prefinem/nativemodels) | ||
| <!-- CodeClimate --> | ||
| [](https://codeclimate.com/github/Prefinem/nativemodels) | ||
| [](https://codeclimate.com/github/Prefinem/nativemodels) | ||
| [](https://codeclimate.com/github/Prefinem/nativemodels) | ||
| [](https://codeclimate.com/github/Prefinem/nativemodels) | ||
| Native Models provides a way to map objects in a clean and typed way. The main goal is to ensure runtime type checking and consistent models for APIs. | ||
@@ -57,6 +25,6 @@ | ||
| * [Yup](https://www.npmjs.com/package/yup) | ||
| * [Joi](https://www.npmjs.com/package/joi) | ||
| * [Schema Object](https://www.npmjs.com/package/schema-object) | ||
| * [ObjectModel](https://www.npmjs.com/package/objectmodel) | ||
| - [Yup](https://www.npmjs.com/package/yup) | ||
| - [Joi](https://www.npmjs.com/package/joi) | ||
| - [Schema Object](https://www.npmjs.com/package/schema-object) | ||
| - [ObjectModel](https://www.npmjs.com/package/objectmodel) | ||
@@ -63,0 +31,0 @@ ## Getting Started |
| const defaultOptions = require('./lib/defaultOptions'); | ||
| const defaultRecord = require('./lib/defaultRecord'); | ||
| const mapRecord = require('./lib/mapRecord'); | ||
| const parseRecord = require('./lib/parseRecord'); | ||
| const proxyHandler = require('./lib/proxyHandler'); | ||
| const recaseKeys = require('./lib/recaseKeys'); | ||
| const requireAllKeys = require('./lib/requireAllKeys'); | ||
| const requiredCheck = require('./lib/requiredCheck'); | ||
| const stripUndefinedKeys = require('./lib/stripUndefinedKeys'); | ||
| const transformRecord = require('./lib/transformRecord'); | ||
| const buildRecord = (schema, record, options) => { | ||
| const mappedRecord = mapRecord(schema, record, options.caseSensitive); | ||
| const transformedRecord = transformRecord(schema, mappedRecord); | ||
| const stripedRecord = options.stripUndefined ? stripUndefinedKeys(schema, transformedRecord) : transformedRecord; | ||
| const casedRecord = options.caseSensitive ? stripedRecord : recaseKeys(schema, stripedRecord); | ||
| const defaultedRecord = defaultRecord(schema, casedRecord); | ||
| return defaultedRecord; | ||
| }; | ||
| const createModel = (schema, modelOptions = {}, context = {}) => (record = {}) => { | ||
| const options = { ...defaultOptions, ...modelOptions }; | ||
| const builtRecord = buildRecord(schema, record, options); | ||
| if (options.strict) { | ||
| requireAllKeys(schema, builtRecord); | ||
| } | ||
| requiredCheck(schema, builtRecord); | ||
| const proxyTarget = parseRecord(schema, builtRecord, options); | ||
| return new Proxy(proxyTarget, proxyHandler(schema, options, context)); | ||
| }; | ||
| module.exports = createModel; |
| const base = require('./datatypes/base'); | ||
| const createType = (overrides, extended = base()) => ({ | ||
| ...extended, | ||
| ...overrides, | ||
| }); | ||
| module.exports = createType; |
| /* eslint max-len: off, no-control-regex: off */ | ||
| const regex = require('./regex'); | ||
| const email = () => | ||
| regex( | ||
| /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/iu, | ||
| 'email', | ||
| ); | ||
| module.exports = email; |
| const createType = require('./../createType'); | ||
| const enumerable = (enumerableValues) => | ||
| createType({ | ||
| name: 'enumerable', | ||
| validCheck: (key, value) => { | ||
| if (enumerableValues.indexOf(value) > -1) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not in the list of enumerable values`); | ||
| }, | ||
| }); | ||
| module.exports = enumerable; |
| const createType = require('./../createType'); | ||
| const guid = () => | ||
| createType({ | ||
| name: 'guid', | ||
| parse: (key, value) => value.toUpperCase(), | ||
| validCheck: (key, value) => { | ||
| if (value === '00000000-0000-0000-0000-000000000000') { | ||
| return true; | ||
| } else if (/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(value)) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not a GUID`); | ||
| }, | ||
| }); | ||
| module.exports = guid; |
| const email = require('./email'); | ||
| const enumerable = require('./enumerable'); | ||
| const guid = require('./guid'); | ||
| const phone = require('./phone'); | ||
| const regex = require('./regex'); | ||
| const url = require('./url'); | ||
| module.exports = { | ||
| email, | ||
| enumerable, | ||
| guid, | ||
| phone, | ||
| regex, | ||
| url, | ||
| }; |
| const regex = require('./regex'); | ||
| const phone = () => regex(/^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/iu, 'phone'); | ||
| module.exports = phone; |
| const createType = require('./../createType'); | ||
| const { isRegex } = require('./../lib/checks/types'); | ||
| const regex = (expression, typeName) => | ||
| createType({ | ||
| name: typeName, | ||
| validCheck: (key, value) => { | ||
| if (isRegex(expression) && expression.test(value)) { | ||
| return true; | ||
| } | ||
| if (!isRegex(expression)) { | ||
| throw new Error(`NativeModels - Regex expression provided isn't a valid regex`); | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} (${value}) is not a/an ${typeName}`); | ||
| }, | ||
| }); | ||
| module.exports = regex; |
| const regex = require('./regex'); | ||
| const url = () => regex(/^(https?|ftp):\/\/(-\.)?([^\s/?.#]+\.?)+(\/[^\s]*)?$/iu, 'url'); | ||
| module.exports = url; |
| const createType = require('./../createType'); | ||
| const any = () => createType({ name: 'any' }); | ||
| module.exports = any; |
| const createType = require('./../createType'); | ||
| const parseValue = require('./../lib/parseValue'); | ||
| const { isArray } = require('./../lib/checks/types'); | ||
| const array = (type) => | ||
| createType({ | ||
| name: 'array', | ||
| parse: (key, values, parentOptions) => values.map((value) => parseValue(type, key, value, parentOptions)), | ||
| validCheck: (key, value) => { | ||
| if (isArray(value)) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not an array`); | ||
| }, | ||
| }); | ||
| module.exports = array; |
| const overrides = { | ||
| name: 'base', | ||
| parse: (key, value) => value, | ||
| requiredCheck: (key, value) => { | ||
| if (value) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property: '${key}' is required`); | ||
| }, | ||
| strictCheck: () => true, | ||
| validCheck: () => true, | ||
| }; | ||
| const chainable = { | ||
| default(value) { | ||
| this.hasDefault = true; | ||
| this.defaultValue = value; | ||
| return this; | ||
| }, | ||
| from(key, options = {}) { | ||
| this.fromKeys = Array.isArray(key) ? key : [key]; | ||
| this.fromOptions = options; | ||
| return this; | ||
| }, | ||
| nullable() { | ||
| this.allowNull = true; | ||
| return this; | ||
| }, | ||
| required() { | ||
| this.isRequired = true; | ||
| return this; | ||
| }, | ||
| strict() { | ||
| this.requireStrict = true; | ||
| return this; | ||
| }, | ||
| transform(fn, type = 'post') { | ||
| this.transforms = this.transforms || {}; | ||
| this.transforms[type] = fn; | ||
| return this; | ||
| }, | ||
| }; | ||
| const base = () => ({ | ||
| ...overrides, | ||
| ...chainable, | ||
| }); | ||
| module.exports = base; |
| const createType = require('./../createType'); | ||
| const { isBoolean, isUndefined } = require('./../lib/checks/types'); | ||
| const boolean = () => | ||
| createType({ | ||
| name: 'boolean', | ||
| parse: (key, value) => Boolean(value), | ||
| requiredCheck: (key, value) => { | ||
| if (isUndefined(value) || value === '' || value === null) { | ||
| throw new Error(`NativeModels - Property: '${key}' is required`); | ||
| } | ||
| return true; | ||
| }, | ||
| strictCheck: (key, value) => { | ||
| if (isBoolean(value)) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not a boolean`); | ||
| }, | ||
| }); | ||
| module.exports = boolean; |
| const createType = require('./../createType'); | ||
| const { isBuffer } = require('./../lib/checks/types'); | ||
| const bufferCheck = (key, value, strict) => { | ||
| if (isBuffer(value)) { | ||
| return true; | ||
| } | ||
| if (!strict && isBuffer(Buffer.from(value))) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not a buffer`); | ||
| }; | ||
| const buffer = () => | ||
| createType({ | ||
| name: 'buffer', | ||
| parse: (key, value) => Buffer.from(value), | ||
| strictCheck: (key, value) => bufferCheck(key, value, true), | ||
| validCheck: (key, value) => bufferCheck(key, value), | ||
| }); | ||
| module.exports = buffer; |
| const createType = require('./../createType'); | ||
| const createModel = require('./../createModel'); | ||
| const parseValue = (type, key, value) => createModel({ [key]: type })({ [key]: value })[key]; | ||
| const getOverridedValue = (type, key, record) => (type ? parseValue(type, key, record[key]) : record[key]); | ||
| const isAsync = (fn) => fn && (fn.then || fn.constructor.name === 'AsyncFunction'); | ||
| const resolve = (response, type, key) => Promise.resolve(response).then((value) => parseValue(type, key, value)); | ||
| const computeWithType = (userFn, type, { context, key, record }) => { | ||
| if (isAsync(userFn)) { | ||
| return resolve(userFn(record, key), type, key, context); | ||
| } | ||
| const response = userFn(record, key, context); | ||
| return isAsync(response) ? resolve(response, type, key) : parseValue(type, key, response); | ||
| }; | ||
| const computed = (userFn, type, options = { allowOverride: false }) => | ||
| createType({ | ||
| fn: (record, key, context) => { | ||
| if (options.allowOverride && record[key]) { | ||
| return getOverridedValue(type, key, record); | ||
| } else if (type) { | ||
| return computeWithType(userFn, type, { context, key, record }); | ||
| } | ||
| return userFn(record, key, context); | ||
| }, | ||
| name: 'computed', | ||
| type: options.allowOverride ? type : undefined, | ||
| }); | ||
| module.exports = computed; |
| const createType = require('./../createType'); | ||
| const { isDate } = require('./../lib/checks/types'); | ||
| const isValidDate = (key, value, strict = false) => { | ||
| if (isDate(value)) { | ||
| return true; | ||
| } | ||
| if (!strict) { | ||
| const test = new Date(value); | ||
| if (value && test instanceof Date && !isNaN(test)) { | ||
| return true; | ||
| } | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not a date`); | ||
| }; | ||
| const date = () => | ||
| createType({ | ||
| name: 'date', | ||
| parse: (key, value) => (value instanceof Date ? value : new Date(value)), | ||
| strictCheck: (key, value) => isValidDate(key, value, true), | ||
| validCheck: (key, value) => isValidDate(key, value), | ||
| }); | ||
| module.exports = date; |
| const createType = require('./../createType'); | ||
| const { isNumber } = require('./../lib/checks/types'); | ||
| const int = require('./int'); | ||
| const isValidFloat = (key, value, strict = false) => { | ||
| if (isNumber(value)) { | ||
| return true; | ||
| } | ||
| if (!strict) { | ||
| if (!isNaN(parseFloat(value)) && value !== true && value !== false && value !== '') { | ||
| return true; | ||
| } | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not a float`); | ||
| }; | ||
| const float = () => | ||
| createType( | ||
| { | ||
| name: 'float', | ||
| parse: (key, value) => parseFloat(value), | ||
| strictCheck: (key, value) => isValidFloat(key, value, true), | ||
| validCheck: (key, value) => isValidFloat(key, value), | ||
| }, | ||
| int(), | ||
| ); | ||
| module.exports = float; |
| const any = require('./any'); | ||
| const array = require('./array'); | ||
| const base = require('./base'); | ||
| const boolean = require('./boolean'); | ||
| const buffer = require('./buffer'); | ||
| const computed = require('./computed'); | ||
| const date = require('./date'); | ||
| const float = require('./float'); | ||
| const int = require('./int'); | ||
| const object = require('./object'); | ||
| const string = require('./string'); | ||
| module.exports = { | ||
| any, | ||
| array, | ||
| base, | ||
| boolean, | ||
| buffer, | ||
| computed, | ||
| date, | ||
| float, | ||
| int, | ||
| object, | ||
| string, | ||
| }; |
| const createType = require('./../createType'); | ||
| const isValidInt = (key, value, strict = false) => { | ||
| if (Number.isInteger(value)) { | ||
| return true; | ||
| } | ||
| if (!strict && Number.isInteger(parseInt(value)) && parseInt(value) === parseFloat(value)) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not an int`); | ||
| }; | ||
| const int = () => | ||
| createType({ | ||
| name: 'int', | ||
| parse: (key, value) => parseInt(value), | ||
| requiredCheck: (key, value) => { | ||
| if (value || value === 0) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property: '${key}' is required`); | ||
| }, | ||
| strictCheck: (key, value) => isValidInt(key, value, true), | ||
| validCheck: (key, value) => isValidInt(key, value), | ||
| }); | ||
| module.exports = int; |
| const createType = require('./../createType'); | ||
| const createModel = require('./../createModel'); | ||
| const { isObject } = require('./../lib/checks/types'); | ||
| const object = (schema, options) => | ||
| createType({ | ||
| name: 'object', | ||
| parse: (key, value, parentOptions) => | ||
| schema ? createModel(schema, { ...parentOptions, ...options })(value) : value, | ||
| validCheck: (key, value) => { | ||
| if (isObject(value)) { | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not an object`); | ||
| }, | ||
| }); | ||
| module.exports = object; |
| const createType = require('./../createType'); | ||
| const { isString } = require('./../lib/checks/types'); | ||
| const strictCheck = (key, value, options) => { | ||
| if (isString(value)) { | ||
| if (options.length && value.length > options.length) { | ||
| throw new Error(`NativeModels - Property ${key} is longer than ${options.length}`); | ||
| } | ||
| return true; | ||
| } | ||
| throw new Error(`NativeModels - Property ${key} is not a string`); | ||
| }; | ||
| const validCheck = (key, value) => { | ||
| if (value === null) { | ||
| throw new Error(`NativeModels - Property ${key} is not a string`); | ||
| } | ||
| return true; | ||
| }; | ||
| const string = (options = {}) => | ||
| createType({ | ||
| name: 'string', | ||
| parse: (key, value) => { | ||
| if (options.length) { | ||
| return `${value}`.slice(0, options.length); | ||
| } | ||
| return `${value}`; | ||
| }, | ||
| strictCheck: (key, value) => strictCheck(key, value, options), | ||
| validCheck, | ||
| }); | ||
| module.exports = string; |
| const customtypes = require('./customtypes'); | ||
| const datatypes = require('./datatypes'); | ||
| const generateType = require('./lib/type/generate'); | ||
| module.exports = (schema, usertypes = {}, fns = {}) => { | ||
| const obj = typeof schema === 'string' ? JSON.parse(schema) : schema; | ||
| const types = { ...datatypes, ...customtypes, ...usertypes }; | ||
| return Object.keys(obj).reduce((result, key) => ({ ...result, [key]: generateType(obj[key], types, fns) }), {}); | ||
| }; |
-20
| const createModel = require('./createModel'); | ||
| const createType = require('./createType'); | ||
| const customtypes = require('./customtypes'); | ||
| const datatypes = require('./datatypes'); | ||
| const generateSchema = require('./generateSchema'); | ||
| const resolve = require('./resolve'); | ||
| /* istanbul ignore next */ | ||
| const resolver = (data, schema) => | ||
| console.warn('DEPRECATION NOTICE: Please use resolve() instead of resolver()') || resolve(data, schema); | ||
| module.exports = { | ||
| createModel, | ||
| createType, | ||
| customtypes, | ||
| datatypes, | ||
| generateSchema, | ||
| resolve, | ||
| resolver, | ||
| }; |
| const invalidTypeCheck = (type, key) => { | ||
| if (!type.validCheck || !type.parse) { | ||
| console.log(`Schema Key: '${key}' is not a valid datatype or customtype`); | ||
| return true; | ||
| } | ||
| return false; | ||
| }; | ||
| module.exports = invalidTypeCheck; |
| const requiredCheck = (type, key, value) => (type.isRequired ? type.requiredCheck(key, value) : true); | ||
| module.exports = requiredCheck; |
| const strictCheck = (type, key, value) => | ||
| type.requireStrict && type.strictCheck ? type.strictCheck(key, value) : true; | ||
| module.exports = strictCheck; |
| // Pre ES5 => value && typeof value === 'object' && value.constructor === Array; | ||
| const isArray = (value) => Array.isArray(value); | ||
| const isBoolean = (value) => typeof value === 'boolean'; | ||
| const isBuffer = (value) => Buffer.isBuffer(value); | ||
| const isDate = (value) => value instanceof Date; | ||
| // const isError = (value) => value instanceof Error && typeof value.message !== 'undefined'; | ||
| // const isFunction = (value) => typeof value === 'function'; | ||
| const isNull = (value) => value === null; | ||
| const isNumber = (value) => typeof value === 'number' && isFinite(value); | ||
| const isObject = (value) => value && typeof value === 'object' && value.constructor === Object; | ||
| const isRegex = (value) => value && typeof value === 'object' && value.constructor === RegExp; | ||
| const isString = (value) => typeof value === 'string' || value instanceof String; | ||
| // const isSymbol = (value) => typeof value === 'symbol'; | ||
| const isUndefined = (value) => typeof value === 'undefined'; | ||
| module.exports = { | ||
| isArray, | ||
| isBoolean, | ||
| isBuffer, | ||
| isDate, | ||
| // isError, | ||
| // isFunction, | ||
| isNull, | ||
| isNumber, | ||
| isObject, | ||
| isRegex, | ||
| isString, | ||
| // isSymbol, | ||
| isUndefined, | ||
| }; |
| const validCheck = (type, key, value) => type.validCheck(key, value); | ||
| module.exports = validCheck; |
| const defaultOptions = { | ||
| // Allow nulls on all columns | ||
| allowNulls: false, | ||
| // Ignores case when initializing object from model | ||
| caseSensitive: true, | ||
| // Pass options to all children | ||
| passOptions: false, | ||
| // Throws an error if key is not in schema | ||
| strict: false, | ||
| // Strip undefined values passed in | ||
| stripUndefined: true, | ||
| }; | ||
| module.exports = defaultOptions; |
| const defaultValue = require('./defaultValue'); | ||
| const defaultRecord = (schema, record) => ({ | ||
| ...record, | ||
| ...Object.keys(schema).reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| ...(schema[key].hasDefault ? { [key]: record[key] || defaultValue(schema[key].defaultValue) } : {}), | ||
| }), | ||
| {}, | ||
| ), | ||
| }); | ||
| module.exports = defaultRecord; |
| const defaultValue = (value) => (typeof value === 'function' ? value() : value); | ||
| module.exports = defaultValue; |
| const recaseRecord = (record) => | ||
| Object.keys(record).reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| [key.toLowerCase()]: record[key], | ||
| }), | ||
| {}, | ||
| ); | ||
| const getFromKeyValue = (schema, record, { caseSensitive, key }) => { | ||
| const { | ||
| fromOptions: { caseSensitive: fromOptionsCaseSensitive }, | ||
| } = schema[key]; | ||
| const lowerCase = typeof fromOptionsCaseSensitive === 'undefined' ? !caseSensitive : !fromOptionsCaseSensitive; | ||
| const fromKeys = [key, ...schema[key].fromKeys].map((key) => (lowerCase ? key.toLowerCase() : key)); | ||
| const recasedRecord = lowerCase ? recaseRecord(record) : record; | ||
| const value = fromKeys.find((fromKey) => typeof recasedRecord[fromKey] !== 'undefined'); | ||
| return recasedRecord[value]; | ||
| }; | ||
| const mapRecord = (schema, record, caseSensitive) => ({ | ||
| ...record, | ||
| ...Object.keys(schema) | ||
| .filter((key) => schema[key].fromKeys) | ||
| .reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| ...{ [key]: getFromKeyValue(schema, record, { caseSensitive, key }) }, | ||
| }), | ||
| {}, | ||
| ), | ||
| }); | ||
| module.exports = mapRecord; |
| const parseValue = require('./parseValue'); | ||
| const parseRecord = (schema, record, options) => | ||
| Object.keys(record).reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| ...(schema[key] ? { [key]: parseValue(schema[key], key, record[key], options) } : {}), | ||
| }), | ||
| {}, | ||
| ); | ||
| module.exports = parseRecord; |
| /* eslint-disable max-params */ | ||
| const invalidTypeCheck = require('./checks/invalidType'); | ||
| const { isNull } = require('./checks/types'); | ||
| const transformValue = require('./transformValue'); | ||
| const checks = { | ||
| required: require('./checks/required'), | ||
| strict: require('./checks/strict'), | ||
| valid: require('./checks/valid'), | ||
| }; | ||
| const runChecks = (type, key, value) => { | ||
| Object.keys(checks).forEach((name) => { | ||
| if (!checks[name](type, key, value)) { | ||
| throw new Error(`NativeModels - Failed ${name} check. Key: ${key} | Value: ${value}`); | ||
| } | ||
| }); | ||
| }; | ||
| const parseValue = (type, key, value, options) => { | ||
| if ((type.allowNull || (options && options.allowNulls)) && isNull(value)) { | ||
| return null; | ||
| } else if (invalidTypeCheck(type, key, value)) { | ||
| return value; | ||
| } | ||
| runChecks(type, key, value); | ||
| const parsedValue = type.parse(key, value, options && options.passOptions ? options : {}); | ||
| return transformValue(type, parsedValue, 'post'); | ||
| }; | ||
| module.exports = parseValue; |
| /* eslint max-params: off */ | ||
| const parseValue = require('./parseValue'); | ||
| const get = (schema, target, property, context) => { | ||
| if (schema[property]) { | ||
| return schema[property].fn ? schema[property].fn(target, property, context) : target[property]; | ||
| } | ||
| return undefined; | ||
| }; | ||
| const getOwnPropertyDescriptor = (schema, target, property) => | ||
| schema[property] | ||
| ? { | ||
| configurable: true, | ||
| enumerable: true, | ||
| value: schema[property].fn ? '[computedValue]' : target[property], | ||
| writable: true, | ||
| } | ||
| : undefined; | ||
| const ownKeys = (schema, target) => { | ||
| const allKeys = [...Object.keys(target), ...Object.keys(schema).filter((key) => schema[key].fn)]; | ||
| return [...new Set(allKeys)]; | ||
| }; | ||
| const set = (schema, target, property, value, options) => { | ||
| if (!schema[property]) { | ||
| throw new Error(`NativeModels - ${property} is not a property of model`); | ||
| } | ||
| const type = schema[property].fn && schema[property].type ? schema[property].type : schema[property]; | ||
| target[property] = parseValue(type, property, value, options); | ||
| return true; | ||
| }; | ||
| const proxyHandler = (schema, options, context) => ({ | ||
| get: (target, property) => get(schema, target, property, context), | ||
| getOwnPropertyDescriptor: (target, property) => getOwnPropertyDescriptor(schema, target, property), | ||
| ownKeys: (target) => ownKeys(schema, target), | ||
| set: (target, property, value) => set(schema, target, property, value, options), | ||
| }); | ||
| module.exports = proxyHandler; |
| const recaseKeys = (schema, record) => { | ||
| const keyMap = Object.keys(schema).reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| [key.toLowerCase()]: key, | ||
| }), | ||
| {}, | ||
| ); | ||
| return Object.keys(record).reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| [keyMap[key.toLowerCase()] || key]: record[key], | ||
| }), | ||
| {}, | ||
| ); | ||
| }; | ||
| module.exports = recaseKeys; |
| const strictCheck = (schema, record) => | ||
| Object.keys(record).forEach((key) => { | ||
| if (!schema[key]) { | ||
| throw new Error(`NativeModels - Property: '${key}' is not defined in the schema`); | ||
| } | ||
| }); | ||
| module.exports = strictCheck; |
| const required = require('./checks/required'); | ||
| const requiredCheck = (schema, record) => | ||
| Object.keys(schema).forEach((key) => { | ||
| required(schema[key], key, record[key]); | ||
| }); | ||
| module.exports = requiredCheck; |
| const stripUndefinedKeys = (schema, record) => | ||
| Object.keys(record).reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| ...(typeof record[key] === 'undefined' ? {} : { [key]: record[key] }), | ||
| }), | ||
| {}, | ||
| ); | ||
| module.exports = stripUndefinedKeys; |
| const transformValue = require('./transformValue'); | ||
| const transformRecord = (schema, record) => | ||
| Object.keys(record).reduce( | ||
| (result, key) => ({ | ||
| ...result, | ||
| [key]: schema[key] ? transformValue(schema[key], record[key], 'pre') : record[key], | ||
| }), | ||
| {}, | ||
| ); | ||
| module.exports = transformRecord; |
| const transformValue = (type, value, key) => | ||
| type.transforms && type.transforms[key] ? type.transforms[key](value) : value; | ||
| module.exports = transformValue; |
| module.exports = (value, types, fns) => { | ||
| if (value.type === 'computed') { | ||
| return types[value.type](fns[value.fn]); | ||
| } else if (value.type === 'object') { | ||
| return types[value.type](require('./../../generateSchema')(value.schema, types, fns)); | ||
| } else if (value.type === 'array') { | ||
| return types[value.type](require('./generate')(value.item, types, fns)); | ||
| } | ||
| return types[value.type](); | ||
| }; |
| module.exports = (value, type, fns) => { | ||
| value.default && type.default(value.default); | ||
| value.nullable && type.nullable(); | ||
| value.required && type.required(); | ||
| value.strict && type.strict(); | ||
| value.transform && type.transform(fns[value.transform]); | ||
| return type; | ||
| }; |
| const buildType = require('./build'); | ||
| const extendType = require('./extend'); | ||
| module.exports = (value, types, fns) => { | ||
| if (typeof value === 'string') { | ||
| if (types[value]) { | ||
| return types[value](); | ||
| } | ||
| throw new Error(`NativeModels - ${value} is not a valid type`); | ||
| } else if (types[value.type]) { | ||
| const type = buildType(value, types, fns); | ||
| return extendType(value, type, fns); | ||
| } | ||
| throw new Error(`NativeModels - ${value} is not a valid type`); | ||
| }; |
-27
| /* eslint-disable no-use-before-define */ | ||
| const { isArray, isObject } = require('./lib/checks/types'); | ||
| const createModel = require('./createModel'); | ||
| const cascadeResolve = (value) => { | ||
| if (isArray(value)) { | ||
| return Promise.all(value.map(cascadeResolve)); | ||
| } else if (isObject(value) && !value.then) { | ||
| return resolve(value); | ||
| } | ||
| return value; | ||
| }; | ||
| const resolved = (keys, values, schema) => { | ||
| const data = keys.reduce((result, key, index) => ({ ...result, [key]: values[index] }), {}); | ||
| return schema ? createModel(schema)(data) : data; | ||
| }; | ||
| const resolve = (data, schema) => { | ||
| const keys = Object.keys(data); | ||
| return Promise.all(keys.map((key) => cascadeResolve(data[key]))).then((values) => resolved(keys, values, schema)); | ||
| }; | ||
| module.exports = resolve; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
10
-23.08%40960
-3.34%632
-4.82%1
Infinity%