UNPKG

@deepkit/core

Version:
775 lines 24.1 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getObjectKeysSize = exports.humanBytes = exports.deletePathValue = exports.setPathValue = exports.getPathValue = exports.time = exports.collectForMicrotask = exports.mergeStack = exports.createStack = exports.mergePromiseStack = exports.asyncOperation = exports.appendObject = exports.prependObjectKeys = exports.average = exports.last = exports.first = exports.lastKey = exports.firstKey = exports.size = exports.empty = exports.copy = exports.sleep = exports.indexOf = exports.isString = exports.isInteger = exports.isNumeric = exports.isNumber = exports.isSet = exports.isUndefined = exports.isNull = exports.isArray = exports.isObject = exports.isClass = exports.isPromise = exports.isAsyncFunction = exports.isFunction = exports.prettyPrintObject = exports.changeClass = exports.stringifyValueWithType = exports.isClassInstance = exports.getClassTypeFromInstance = exports.isPlainObject = exports.identifyType = exports.applyDefaults = exports.getClassPropertyName = exports.getClassName = exports.__ΩExtractClassType = exports.__ΩAbstractClassType = exports.__ΩClassType = exports.CustomError = void 0; exports.getCurrentFileName = exports.isIterable = exports.createDynamicClass = exports.inDebugMode = exports.getParentClass = exports.isPrototypeOfBase = exports.isConstructable = void 0; function __assignType(fn, args) { fn.__type = args; return fn; } const __ΩPropertyKey = ['P&\'+J']; const __ΩObject = ['', 'constructor', 'toString', 'toLocaleString', 0, 'valueOf', () => __ΩPropertyKey, 'v', 'hasOwnProperty', 0, 'isPrototypeOf', () => __ΩPropertyKey, 'propertyIsEnumerable', 'PP"/!4"P&1#P&1$Pn%1&Pn\'2()1)Pn*2()1+Pn,2()1-M']; const __ΩError = ['name', 'message', 'stack', 'P&4!&4"&4#8M']; /* * Deepkit Framework * Copyright (C) 2021 Deepkit UG, Marc J. Schmidt * * This program is free software: you can redistribute it and/or modify * it under the terms of the MIT License. * * You should have received a copy of the MIT License along with this program. */ const dot_prop_1 = __importDefault(require("dot-prop")); const iterators_js_1 = require("./iterators.js"); /** * Makes sure the error once printed using console.log contains the actual class name. * * @example * ``` * class MyApiError extends CustomerError {} * * throw MyApiError() // prints MyApiError instead of simply "Error". * ``` * * @public */ class CustomError extends Error { constructor(message = '') { super(message); this.message = message; this.name = this.constructor.name; } } exports.CustomError = CustomError; CustomError.__type = [() => Error, 'name', 'stack', 'message', () => "", 'constructor', 'P7!&3"&3#8P&2$:>%"0&5']; const __ΩClassType = ['T', 'args', 'new', '"c!PP"@2"e#!1#M']; exports.__ΩClassType = __ΩClassType; const __ΩAbstractClassType = ['T', 'args', 'new', '"c!P"@2"e"!/#']; exports.__ΩAbstractClassType = __ΩAbstractClassType; const __ΩExtractClassType = ['T', () => __ΩAbstractClassType, 'l:e"!R!RPde#!h!!o""qk#\'QRb!Pde"!p)']; exports.__ΩExtractClassType = __ΩExtractClassType; /** * Returns the class name either of the class definition or of the class of an instance. * * Note when code is minimized/uglified this output will change. You should disable in your compile the * className modification. * * @example * ```typescript * class User {} * * expect(getClassName(User)).toBe('User'); * expect(getClassName(new User())).toBe('User'); * ``` * * @public */ function getClassName(classTypeOrInstance) { if (!classTypeOrInstance) return 'undefined'; const proto = classTypeOrInstance['prototype'] ? classTypeOrInstance['prototype'] : classTypeOrInstance; return proto.constructor.name || 'anonymous class'; } exports.getClassName = getClassName; getClassName.__type = [() => __ΩClassType, () => __ΩObject, 'classTypeOrInstance', 'getClassName', 'PP"o!"n"J2#&/$']; /** * Same as getClassName but appends the propertyName. * @public */ function getClassPropertyName(classType, propertyName) { const name = getClassName(classType); return `${name}.${propertyName}`; } exports.getClassPropertyName = getClassPropertyName; getClassPropertyName.__type = [() => __ΩClassType, () => __ΩObject, 'classType', 'propertyName', 'getClassPropertyName', 'PP"o!"n"J2#&2$&/%']; /** * @public */ function applyDefaults(classType, target) { const classInstance = new classType(); for (const [i, v] of (0, iterators_js_1.eachPair)(target)) { classInstance[i] = v; } return classInstance; } exports.applyDefaults = applyDefaults; applyDefaults.__type = [() => __ΩClassType, 'classType', 'target', 'applyDefaults', 'P"o!"2"P&"LM2#"/$']; /** * Tries to identify the object by normalised result of Object.toString(obj). */ function identifyType(obj) { return ((({}).toString.call(obj).match(/\s([a-zA-Z]+)/) || [])[1] || '').toLowerCase(); } exports.identifyType = identifyType; identifyType.__type = ['obj', 'identifyType', 'P"2!"/"']; /** * Returns true if the given obj is a plain object, and no class instance. * * isPlainObject(\{\}) === true * isPlainObject(new ClassXY) === false * * @public */ function isPlainObject(obj) { return Boolean(obj && typeof obj === 'object' && obj.constructor instanceof obj.constructor); } exports.isPlainObject = isPlainObject; isPlainObject.__type = ['obj', 'isPlainObject', 'P"2!!/"']; /** * Returns the ClassType for a given instance. */ function getClassTypeFromInstance(target) { if (!isClassInstance(target)) { throw new Error(`Value is not a class instance. Got ${stringifyValueWithType(target)}`); } return target['constructor']; } exports.getClassTypeFromInstance = getClassTypeFromInstance; getClassTypeFromInstance.__type = ['target', () => __ΩClassType, 'getClassTypeFromInstance', 'P"2!"o""/#']; /** * Returns true when target is a class instance. */ function isClassInstance(target) { return target !== undefined && target !== null && target['constructor'] && Object.getPrototypeOf(target) === target['constructor'].prototype && !isPlainObject(target) && isObject(target); } exports.isClassInstance = isClassInstance; isClassInstance.__type = ['target', 'isClassInstance', 'P"2!)/"']; /** * Returns a human readable string representation from the given value. */ function stringifyValueWithType(value) { if ('string' === typeof value) return `string(${value})`; if ('number' === typeof value) return `number(${value})`; if ('boolean' === typeof value) return `boolean(${value})`; if ('bigint' === typeof value) return `bigint(${value})`; if (isPlainObject(value)) return `object ${prettyPrintObject(value)}`; if (isArray(value)) return `Array`; if (isClass(value)) return `${getClassName(value)}`; if (isObject(value)) return `${getClassName(getClassTypeFromInstance(value))} ${prettyPrintObject(value)}`; if ('function' === typeof value) return `function ${value.name}`; if (null === value) return `null`; return 'undefined'; } exports.stringifyValueWithType = stringifyValueWithType; stringifyValueWithType.__type = ['value', 'stringifyValueWithType', 'P"2!&/"']; /** * Changes the class of a given instance and returns the new object. * * @example * ```typescript * * class Model1 { * id: number = 0; * } * * class Model2 { * id: number = 0; * } * * const model1 = new Model1(); * const model2 = changeClass(model1, Model2); * model2 instanceof Model2; //true * ``` */ function changeClass(value, newClass) { return Object.assign(Object.create(newClass.prototype), value); } exports.changeClass = changeClass; changeClass.__type = ['value', () => __ΩClassType, 'newClass', 'changeClass', 'P%2!"o""2#"/$']; function prettyPrintObject(object) { let res = []; for (const i in object) { res.push(i + ': ' + stringifyValueWithType(object[i])); } return '{' + res.join(',') + '}'; } exports.prettyPrintObject = prettyPrintObject; prettyPrintObject.__type = ['object', 'prettyPrintObject', 'P%2!&/"']; /** * Returns true if given obj is a function. * * @public */ function isFunction(obj) { if ('function' === typeof obj) { return !obj.toString().startsWith('class ') && !obj.toString().startsWith('class{'); } return false; } exports.isFunction = isFunction; isFunction.__type = ['obj', 'isFunction', 'P"2!!/"']; const AsyncFunction = (async () => { }).constructor; /** * Returns true if given obj is a async function. * * @public */ function isAsyncFunction(obj) { return obj instanceof AsyncFunction; } exports.isAsyncFunction = isAsyncFunction; isAsyncFunction.__type = ['obj', 'isAsyncFunction', 'P"2!!/"']; /** * Returns true if given obj is a promise like object. * * Note: There's not way to check if it's actually a Promise using instanceof since * there are a lot of different implementations around. * * @public */ function isPromise(obj) { return obj !== null && typeof obj === 'object' && typeof obj.then === 'function' && typeof obj.catch === 'function' && typeof obj.finally === 'function'; } exports.isPromise = isPromise; isPromise.__type = ['obj', 'isPromise', 'PP""`J2!!/"']; /** * Returns true if given obj is a ES6 class (ES5 fake classes are not supported). * * @public */ function isClass(obj) { if ('function' === typeof obj) { return obj.toString().startsWith('class ') || obj.toString().startsWith('class{'); } return false; } exports.isClass = isClass; isClass.__type = ['obj', 'isClass', 'P"2!!/"']; /** * Returns true for real objects: object literals ({}) or class instances (new MyClass). * * @public */ function isObject(obj) { if (obj === null) { return false; } return (typeof obj === 'object' && !isArray(obj)); } exports.isObject = isObject; isObject.__type = ['obj', 'isObject', 'P"2!!/"']; /** * @public */ function isArray(obj) { return Array.isArray(obj); } exports.isArray = isArray; isArray.__type = ['obj', 'isArray', 'P"2!!/"']; /** * @public */ function isNull(obj) { return null === obj; } exports.isNull = isNull; isNull.__type = ['obj', 'isNull', 'P"2!!/"']; /** * @public */ function isUndefined(obj) { return undefined === obj; } exports.isUndefined = isUndefined; isUndefined.__type = ['obj', 'isUndefined', 'P"2!!/"']; /** * Checks if obj is not null and not undefined. * * @public */ function isSet(obj) { return !isNull(obj) && !isUndefined(obj); } exports.isSet = isSet; isSet.__type = ['obj', 'isSet', 'P"2!)/"']; /** * @public */ function isNumber(obj) { return 'number' === identifyType(obj); } exports.isNumber = isNumber; isNumber.__type = ['obj', 'isNumber', 'P"2!!/"']; /** * Returns true if given value is strictly a numeric string value (or a number). * * ```typescript * isNumeric(12); //true * isNumeric('12'); //true * isNumeric('12.3'); //true * isNumeric('12.3 '); //false * isNumeric('12px'); //false * ``` * @public */ function isNumeric(s) { if ('number' === typeof s) return true; let points = 0; for (let i = s.length - 1; i >= 0; i--) { const d = s.charCodeAt(i); if (d === 46) { //46 = . if (points++ > 0) return false; continue; } if (d < 48 || d > 57) return false; } return true; } exports.isNumeric = isNumeric; isNumeric.__type = ['s', 'isNumeric', 'PP&\'J2!)/"']; exports.isInteger = Number.isInteger || __assignType(function (obj) { return (obj % 1) === 0; }, ['obj', '', 'P"2!"/"']); /** * @public */ function isString(obj) { return 'string' === identifyType(obj); } exports.isString = isString; isString.__type = ['obj', 'isString', 'P"2!!/"']; /** * @public */ function indexOf(array, item) { if (!array) { return -1; } return array.indexOf(item); } exports.indexOf = indexOf; indexOf.__type = ['array', 'item', 'indexOf', 'P"F2!"2"\'/#']; /** * @public */ async function sleep(seconds) { return new Promise(__assignType(resolve => setTimeout(resolve, seconds * 1000), ['resolve', '', 'P"2!"/"'])); } exports.sleep = sleep; sleep.__type = ['seconds', 'sleep', 'P\'2!$`/"']; /** * Creates a shallow copy of given array. * * @public */ function copy(v) { if (isArray(v)) { return v.slice(0); } return v; } exports.copy = copy; copy.__type = ['v', 'copy', 'P"F2!"F/"']; /** * Checks whether given array or object is empty (no keys). If given object is falsy, returns false. * * @public */ function empty(value) { if (!value) return true; if (isArray(value)) { return value.length === 0; } else { for (const i in value) if (value.hasOwnProperty(i)) return false; return true; } } exports.empty = empty; empty.__type = ['value', 'empty', 'PP"F%PMJ2!8)/"']; /** * Returns the size of given array or object. * * @public */ function size(array) { if (!array) { return 0; } if (isArray(array)) { return array.length; } else { return getObjectKeysSize(array); } } exports.size = size; size.__type = ['array', 'size', 'PP"FP&"LMJ2!\'/"']; /** * Returns the first key of a given object. * * @public */ function firstKey(v) { return Object.keys(v)[0]; } exports.firstKey = firstKey; firstKey.__type = ['v', 'firstKey', 'PPP&"LM%J2!P&-J/"']; /** * Returns the last key of a given object. * * @public */ function lastKey(v) { const keys = Object.keys(v); if (keys.length) { return; } return keys[keys.length - 1]; } exports.lastKey = lastKey; lastKey.__type = ['v', 'lastKey', 'PPP&"LM%J2!P&-J/"']; /** * Returns the first value of given array or object. * * @public */ function first(v) { if (isArray(v)) { return v[0]; } const key = firstKey(v); if (key) { return v[key]; } return; } exports.first = first; first.__type = ['v', 'first', 'PPP&"LM"FJ2!P"-J/"']; /** * Returns the last value of given array or object. * * @public */ function last(v) { if (isArray(v)) { if (v.length > 0) { return v[v.length - 1]; } return; } const key = firstKey(v); if (key) { return v[key]; } return; } exports.last = last; last.__type = ['v', 'last', 'PPP&"LM"FJ2!P"-J/"']; /** * Returns the average of a number array. * * @public */ function average(array) { let sum = 0; for (const n of array) { sum += n; } return sum / array.length; } exports.average = average; average.__type = ['array', 'average', 'P\'F2!\'/"']; /** * @public */ function prependObjectKeys(o, prependText) { const converted = {}; for (const i in o) { if (!o.hasOwnProperty(i)) continue; converted[prependText + i] = o[i]; } return converted; } exports.prependObjectKeys = prependObjectKeys; prependObjectKeys.__type = ['o', 'prependText', 'prependObjectKeys', 'PP&"LM2!&2"P&"LM/#']; /** * @public */ function appendObject(origin, extend, prependKeyName = '') { const no = prependObjectKeys(extend, prependKeyName); for (const [i, v] of (0, iterators_js_1.eachPair)(no)) { origin[i] = v; } } exports.appendObject = appendObject; appendObject.__type = ['origin', 'extend', 'prependKeyName', () => "", 'appendObject', 'PP&"LM2!P&"LM2"&2#>$"/%']; /** * A better alternative to "new Promise()" that supports error handling and maintains the stack trace for Error.stack. * * When you use `new Promise()` you need to wrap your code inside a try-catch to call `reject` on error. * asyncOperation() does this automatically. * * When you use `new Promise()` you will lose the stack trace when `reject(new Error())` is called. * asyncOperation() makes sure the error stack trace is the correct one. * * @example * ```typescript * await asyncOperation(async (resolve, reject) => { * await doSomething(); //if this fails, reject() will automatically be called * stream.on('data', (data) => { * resolve(data); //at some point you MUST call resolve(data) * }); * }); * ``` * * @public */ async function asyncOperation(executor) { try { return await new Promise(__assignType(async (resolve, reject) => { try { await executor(resolve, reject); } catch (e) { reject(e); } }, ['resolve', 'reject', '', 'P"2!"2""/#'])); } catch (error) { mergeStack(error, createStack()); throw error; } } exports.asyncOperation = asyncOperation; asyncOperation.__type = ['value', '', 'resolve', 'error', 'reject', 'executor', 'asyncOperation', 'PPP"2!$/"2#P"2$$/"2%P$$`J/"2&"`/\'']; /** * @public */ function mergePromiseStack(promise, stack) { stack = stack || createStack(); promise.then(() => { }, __assignType((error) => { mergeStack(error, stack || ''); }, ['error', '', 'P"2!"/"'])); return promise; } exports.mergePromiseStack = mergePromiseStack; mergePromiseStack.__type = ['promise', 'stack', 'mergePromiseStack', 'P"`2!&2"8"`/#']; /** * @beta */ function createStack(removeCallee = true) { if (Error.stackTraceLimit === 10) Error.stackTraceLimit = 100; let stack = new Error().stack || ''; /* at createStack (/file/path) at promiseToObservable (/file/path) at userLandCode1 (/file/path) at userLandCode2 (/file/path) */ //remove "at createStack" stack = stack.slice(stack.indexOf(' at ') + 6); stack = stack.slice(stack.indexOf(' at ') - 1); if (removeCallee) { //remove callee stack = stack.slice(stack.indexOf(' at ') + 6); stack = stack.slice(stack.indexOf(' at ') - 1); } return stack; } exports.createStack = createStack; createStack.__type = ['removeCallee', () => true, 'createStack', 'P)2!>"&/#']; /** * @beta */ function mergeStack(error, stack) { if (error instanceof Error && error.stack) { error.stack += '\n' + stack; } } exports.mergeStack = mergeStack; mergeStack.__type = [() => __ΩError, 'error', 'stack', 'mergeStack', 'Pn!2"&2#"/$']; function collectForMicrotask(callback) { let items = []; let taskScheduled = false; return __assignType((arg) => { items.push(arg); if (!taskScheduled) { taskScheduled = true; queueMicrotask(() => { taskScheduled = false; callback(items); items.length = 0; }); } }, [() => callback, 'args', '', 'arg', 'PPdi!Ph"!F2"$/#qe!!!j2$"/#']); } exports.collectForMicrotask = collectForMicrotask; collectForMicrotask.__type = ['args', '', 'callback', 'arg', 'collectForMicrotask', 'PP"F2!$/"2#P"2$$/"/%']; /** * Returns the current time as seconds. * * @public */ function time() { return Date.now() / 1000; } exports.time = time; time.__type = ['time', 'P\'/!']; /** * @public */ function getPathValue(bag, parameterPath, defaultValue) { if (isSet(bag[parameterPath])) { return bag[parameterPath]; } const result = dot_prop_1.default.get(bag, parameterPath); return isSet(result) ? result : defaultValue; } exports.getPathValue = getPathValue; getPathValue.__type = ['bag', 'parameterPath', 'defaultValue', 'getPathValue', 'PP&"LM2!&2""2#8"/$']; /** * @public */ function setPathValue(bag, parameterPath, value) { dot_prop_1.default.set(bag, parameterPath, value); } exports.setPathValue = setPathValue; setPathValue.__type = ['bag', 'parameterPath', 'value', 'setPathValue', 'P%2!&2""2#"/$']; /** * @public */ function deletePathValue(bag, parameterPath) { dot_prop_1.default.delete(bag, parameterPath); } exports.deletePathValue = deletePathValue; deletePathValue.__type = ['bag', 'parameterPath', 'deletePathValue', 'P%2!&2""/#']; /** * Returns the human-readable byte representation. * * @public */ function humanBytes(bytes, si = false) { const thresh = si ? 1000 : 1024; if (Math.abs(bytes) < thresh) { return bytes + ' B'; } const units = si ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']; let u = -1; do { bytes /= thresh; ++u; } while (Math.abs(bytes) >= thresh && u < units.length - 1); return bytes.toFixed(2) + ' ' + units[u]; } exports.humanBytes = humanBytes; humanBytes.__type = ['bytes', 'si', () => false, 'humanBytes', 'P\'2!)2">#&/$']; /** * Returns the number of properties on `obj`. This is 20x faster than Object.keys(obj).length. */ function getObjectKeysSize(obj) { let size = 0; for (let i in obj) if (obj.hasOwnProperty(i)) size++; return size; } exports.getObjectKeysSize = getObjectKeysSize; getObjectKeysSize.__type = ['obj', 'getObjectKeysSize', 'P%2!\'/"']; function isConstructable(fn) { try { new new Proxy(fn, { construct: () => ({}) }); return true; } catch (err) { return false; } } exports.isConstructable = isConstructable; isConstructable.__type = ['fn', 'isConstructable', 'P"2!)/"']; function isPrototypeOfBase(prototype, base) { if (!prototype) return false; if (prototype === base) return true; let currentProto = Object.getPrototypeOf(prototype); while (currentProto && currentProto !== Object.prototype) { if (currentProto === base) return true; currentProto = Object.getPrototypeOf(currentProto); } return false; } exports.isPrototypeOfBase = isPrototypeOfBase; isPrototypeOfBase.__type = [() => __ΩAbstractClassType, 'prototype', () => __ΩClassType, 'base', 'isPrototypeOfBase', 'PPn!-J2"n#2$)/%']; function getParentClass(classType) { const parent = Object.getPrototypeOf(classType); if (parent === Object.prototype || Object.getPrototypeOf(parent) === Object.prototype) return; return parent; } exports.getParentClass = getParentClass; getParentClass.__type = [() => __ΩClassType, 'classType', () => __ΩClassType, 'getParentClass', 'Pn!2"Pn#-J/$']; function inDebugMode() { return typeof v8debug === 'object' || /--debug|--inspect/.test(process.execArgv.join(' ')); } exports.inDebugMode = inDebugMode; inDebugMode.__type = ['inDebugMode', 'P"/!']; /** * Create a new class with the given name. * This is currently the only know way to make it workable in browsers too. */ function createDynamicClass(name, base) { if (base) { let baseName = getClassName(base); if (baseName === name) baseName += 'Base'; return new Function(baseName, `return class ${name} extends ${baseName} {}`)(base); } return new Function(`return class ${name} {}`)(); } exports.createDynamicClass = createDynamicClass; createDynamicClass.__type = ['name', () => __ΩClassType, 'base', () => __ΩClassType, 'createDynamicClass', 'P&2!n"2#8n$/%']; function isIterable(value) { return isArray(value) || value instanceof Set || value instanceof Map; } exports.isIterable = isIterable; isIterable.__type = ['value', 'isIterable', 'P"2!)/"']; /** * Returns __filename, works in both cjs and esm. */ function getCurrentFileName() { const e = new Error; const initiator = e.stack.split('\n').slice(2, 3)[0]; let path = /(?<path>[^(\s]+):[0-9]+:[0-9]+/.exec(initiator).groups.path; if (path.indexOf('file') >= 0) { path = new URL(path).pathname; } if (path[0] === '/' && process.platform === 'win32') { path = path.slice(1); } return path; } exports.getCurrentFileName = getCurrentFileName; getCurrentFileName.__type = ['getCurrentFileName', 'P&/!']; //# sourceMappingURL=core.js.map