@lincode/utils
Version:
Generated by ambients-cli
336 lines (335 loc) • 10.9 kB
JavaScript
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;