UNPKG

@lincode/utils

Version:

Generated by ambients-cli

336 lines (335 loc) 10.9 kB
export { merge, omit, upperFirst, get, has, unset, range, invert, kebabCase } from "lodash"; export const forceGet = (map, obj, factory) => { if (!map.has(obj)) { const item = factory(); map.set(obj, item); return item; } return map.get(obj); }; export const forceGetInstance = (map, obj, ValClass, params = []) => { if (!map.has(obj)) { const item = new ValClass(...params); map.set(obj, item); return item; } return map.get(obj); }; export const assert = (condition, msg) => { if (!condition) throw new Error(msg); }; export const assertExhaustive = (x) => { throw new Error("unexpected value: " + x); }; export const isInstance = (target, ClassVar) => { //@ts-ignore return target != null && target.constructor === ClassVar; }; export const isNotNullish = (t) => !!t; export const tryParse = (val, typeGuard) => { if (typeof val !== "string") return; try { const result = JSON.parse(val); if (!typeGuard || typeGuard(result)) return result; } catch { } }; export const includes = (collection, value) => collection.has(value); export const filter = (obj, predicate) => { const result = {}; for (const [k, v] of Object.entries(obj)) predicate(v, k) && (result[k] = v); return result; }; export const omitDeep = (obj, keys) => { if (Array.isArray(obj)) { const newObj = new Array(obj.length); for (let i = 0; i < obj.length; ++i) newObj[i] = omitDeep(obj[i], keys); return newObj; } else if (obj && typeof obj === "object") { const newObj = {}; for (const [k, v] of Object.entries(obj)) !keys.includes(k) && (newObj[k] = omitDeep(v, keys)); return newObj; } return obj; }; export const set = (obj, path, value) => { var _a; var _b; let target = obj; const iMax = path.length - 1; for (let i = 0; i < iMax; ++i) target = (_a = target[_b = path[i]]) !== null && _a !== void 0 ? _a : (target[_b] = {}); target[path[iMax]] = value; }; export const traverse = (obj, cb, traversed = new WeakSet()) => { if (Array.isArray(obj)) { if (traversed.has(obj)) return; traversed.add(obj); for (let i = 0; i < obj.length; ++i) { const v = obj[i]; cb(i, v, obj); traverse(v, cb, traversed); } } else if (obj && typeof obj === "object") { if (traversed.has(obj)) return; traversed.add(obj); for (const [k, v] of Object.entries(obj)) { cb(k, v, obj); traverse(v, cb, traversed); } } }; export const everyAsFirst = (array, predicate) => { if (array.length === 0) return false; const firstItem = array[0]; const firstResult = predicate(firstItem, firstItem); return array.every((item) => predicate(item, firstItem) === firstResult); }; export const keepOne = (items) => (items === null || items === void 0 ? void 0 : items.length) ? [items[0]] : []; export const pull = (array, item) => { const index = array.indexOf(item); if (index === -1) return false; array.splice(index, 1); return true; }; export const insert = (array, item, index) => { array.splice(index, 0, item); }; export const dedupe = (array) => [...new Set(array)]; export const trim = (str, char) => { if (char === "]") char = "\\]"; if (char === "\\") char = "\\\\"; return str.replace(new RegExp("^[" + char + "]+|[" + char + "]+$", "g"), ""); }; export const between = (s, char0, char1) => { const i0 = s.indexOf(char0); if (i0 === -1) return ""; const indexStart = i0 + char0.length; const i1 = s.indexOf(char1, indexStart); if (i1 === -1) return ""; return s.substring(indexStart, i1); }; export const splitFileName = (fileName) => { const parts = fileName.split("."); if (parts.length === 1) return parts; const extension = parts.pop(); return [parts.join("."), extension]; }; export const random = (min, max) => { return Math.random() * (max - min) + min; }; export const throttle = (fn, timeout, edge) => { let result; let scheduled = false; let latestArgs; let resultResolve = undefined; let resultPromise = edge === "trailingPromise" ? new Promise((r) => (resultResolve = r)) : undefined; return (...args) => { latestArgs = args; if (scheduled) return resultPromise !== null && resultPromise !== void 0 ? resultPromise : result; scheduled = true; if (edge === "leading" || edge === "both") result = fn(...latestArgs); const cb = () => { if (edge === "trailing" || edge === "both" || edge === "trailingPromise") { result = fn(...latestArgs); resultResolve === null || resultResolve === void 0 ? void 0 : resultResolve(result); resultPromise = edge === "trailingPromise" ? new Promise((r) => (resultResolve = r)) : undefined; } scheduled = false; }; timeout > 0 ? setTimeout(cb, timeout) : queueMicrotask(cb); return resultPromise !== null && resultPromise !== void 0 ? resultPromise : result; }; }; export const throttleTrailing = (fn, timeout = 0) => { let scheduled = false; let latestArgs; return (...args) => { latestArgs = args; if (scheduled) return; scheduled = true; const cb = () => { scheduled = false; fn(...latestArgs); }; timeout === 0 ? queueMicrotask(cb) : setTimeout(cb, timeout); }; }; const cancellableMicrotask = (cb) => { let proceed = true; queueMicrotask(() => proceed && cb()); return () => { proceed = false; }; }; const cancellableTimeout = (cb, time) => { if (time === 0) return cancellableMicrotask(cb); const t = setTimeout(cb, time); return () => clearTimeout(t); }; export const debounce = (fn, timeout, edge) => { let cancelTimeout; let result; let args0; let resultResolve = undefined; let resultPromise = edge === "trailingPromise" ? new Promise((r) => (resultResolve = r)) : undefined; return (...args) => { args0 = args; if (cancelTimeout) cancelTimeout(); else if (edge === "leading" || edge === "both") result = fn(...args0); cancelTimeout = cancellableTimeout(() => { if (edge === "trailing" || edge === "both" || edge === "trailingPromise") { result = fn(...args0); resultResolve === null || resultResolve === void 0 ? void 0 : resultResolve(result); resultPromise = edge === "trailingPromise" ? new Promise((r) => (resultResolve = r)) : undefined; } cancelTimeout = undefined; }, timeout); return resultPromise !== null && resultPromise !== void 0 ? resultPromise : result; }; }; export const isAssignable = (SubClass, SuperClass) => { return SubClass === SuperClass || SubClass.prototype instanceof SuperClass; }; export const getMethods = (obj) => { const methods = new Set(); while (obj) { for (const key of Reflect.ownKeys(obj)) typeof key === "string" && methods.add(key); obj = Reflect.getPrototypeOf(obj); } return [...methods]; }; export const log = (val) => (console.log(val), val); const callerExtendedMap = new WeakMap(); const callerSet = new WeakSet(); const callerSetAdd = (fn) => { callerSet.add(fn); return fn; }; export const extendFunction = (fn, newFn) => { const isCaller = fn && callerSet.has(fn); const caller = isCaller ? fn : callerSetAdd((...args) => { let result; let first = true; for (const cb of existingCallbacks) { if (first) { result = cb(...args); first = false; } else cb(...args); } return result; }); const existingCallbacks = forceGetInstance(callerExtendedMap, caller, (Set)); fn && !isCaller && existingCallbacks.add(fn); existingCallbacks.add(newFn); return caller; }; export const omitFunction = (fn, newFn) => { var _a; (_a = callerExtendedMap.get(fn)) === null || _a === void 0 ? void 0 : _a.delete(newFn); return fn; }; const lazySet = new WeakSet(); export const isLazy = (val) => lazySet.has(val); export const lazy = (factory) => { let result; let has = false; const lazyFn = (...a) => { if (has) return result; has = true; return (result = factory(...a)); }; lazySet.add(lazyFn); return lazyFn; }; export const lazyWithInvalidate = (factory, invalidateWhenReturnValueChanges) => { let result; let has = false; let valOld = invalidateWhenReturnValueChanges(); const lazyFn = (...a) => { const val = invalidateWhenReturnValueChanges(); if (valOld !== val) has = false; valOld = val; if (has) return result; has = true; return (result = factory(...a)); }; lazySet.add(lazyFn); return lazyFn; }; export const applyMixins = (toClass, fromClasses) => { for (const fromClass of fromClasses) for (const name of Object.getOwnPropertyNames(fromClass.prototype)) !(name in toClass.prototype) && Object.defineProperty(toClass.prototype, name, Object.getOwnPropertyDescriptor(fromClass.prototype, name) || Object.create(null)); }; export const preventTreeShake = (obj) => obj; export const filterBoolean = (arg) => !!arg; // pending deprecation export const debounceInstance = (fn) => { const cancelTimeoutMap = new WeakMap(); const args0Map = new WeakMap(); return (instance, ...args) => { var _a; args0Map.set(instance, args); (_a = cancelTimeoutMap.get(instance)) === null || _a === void 0 ? void 0 : _a(); cancelTimeoutMap.set(instance, cancellableMicrotask(() => { fn(...args0Map.get(instance)); cancelTimeoutMap.delete(instance); })); }; }; export const last = (val, index = -1) => val[val.length + index]; export const replaceAll = (val, from, to) => { return val.split(from).join(to); }; export const type = (val) => val; const w = globalThis; "__LINCODE_UTILS__" in w && console.warn("multiple versions of @lincode/utils detected"); w.__LINCODE_UTILS__ = true;