UNPKG

@cch137/format-utils

Version:

A collection of utility modules for formatting and processing data

180 lines (179 loc) 5.79 kB
const findObj = (objs, p) => objs.find((o) => p in o) || objs[0]; const Merged = Symbol("Merged"); export function merge(...objs) { objs.unshift({ [Symbol.for("nodejs.util.inspect.custom")]() { const obj = {}; for (const o of objs) for (const k in o) obj[k] = o[k]; return obj; }, }); objs = Object.freeze(objs .map((i) => (Merged in i ? i[Merged].slice(1) : i)) .flat()); return new Proxy(objs[0], { has: (t, p) => objs.some((o) => p in o), get: (t, p) => (p === Merged ? objs : findObj(objs, p)[p]), set: (t, p, v) => Reflect.set(findObj(objs, p), p, v), deleteProperty: (t, p) => Reflect.deleteProperty(findObj(objs, p), p), ownKeys: (t) => objs.reduce((p, c) => p.concat(Reflect.ownKeys(c).filter((i) => !p.includes(i))), Reflect.ownKeys(t)), defineProperty: (t, p, a) => Reflect.defineProperty(findObj(objs, p), p, a), getOwnPropertyDescriptor: (t, p) => Reflect.getOwnPropertyDescriptor(findObj(objs, p), p), }); } export const nullPrototype = Reflect.getPrototypeOf({}); export function getPrototypesOf(obj) { const chain = [obj]; while (true) { const prototype = Reflect.getPrototypeOf(obj); if (prototype === nullPrototype) return chain; chain.push(prototype); obj = prototype; } } export function getAllKeys(obj) { const prototypes = getPrototypesOf(obj); if (prototypes.length === 1) return Reflect.ownKeys(obj); return prototypes.reduce((prev, curr) => { Reflect.ownKeys(curr).forEach((k) => { if (!prev.includes(k) && k !== "constructor") prev.push(k); }); return prev; }, []); } export function getAllDescriptors(obj) { const prototypes = getPrototypesOf(obj); const descriptors = prototypes .reverse() .reduceRight((prev, curr) => Object.assign(prev, Object.getOwnPropertyDescriptors(curr)), {}); if (prototypes.length > 1) Reflect.deleteProperty(descriptors, "constructor"); return descriptors; } export const isObject = (value) => typeof value === "object" && value !== null; export function decircular(obj, level = 0, objectLevels = [], objectIds = new Map(), encodedObjects = new Map()) { if (objectIds.has(obj)) return objectIds.get(obj); const objectId = { o: -1 }; const encodedObject = {}; (objectLevels[level] || (objectLevels[level] = [])).push(obj); objectIds.set(obj, objectId); encodedObjects.set(obj, encodedObject); const descriptors = getAllDescriptors(obj); for (const key in descriptors) { const descriptor = descriptors[key]; if (descriptor.get) continue; const { value } = descriptor; encodedObject[key] = isObject(value) ? decircular(value, level + 1, objectLevels, objectIds, encodedObjects) : value; } if (level === 0) { const sortedObjects = []; let index = 0; objectLevels.forEach((level) => { level.forEach((o) => { sortedObjects.push(o); objectIds.get(o).o = `${index++}`; }); }); return sortedObjects.map((o) => encodedObjects.get(o)); } return objectId; } export function encircular(series) { const root = series[0]; for (const obj of series) { for (const k in obj) { const v = obj[k]; if (isObject(v)) obj[k] = series[v.o]; } } return root; } export function pick(obj, keys) { return new Proxy(obj, { get(t, p) { if (keys.includes(p)) return Reflect.get(t, p); return undefined; }, set(t, p, v) { if (keys.includes(p)) return Reflect.set(t, p, v); return false; }, has(t, p) { if (keys.includes(p)) return Reflect.has(t, p); return false; }, ownKeys(t) { return Reflect.ownKeys(t).filter((i) => keys.includes(i)); }, deleteProperty(t, p) { if (keys.includes(p)) return Reflect.deleteProperty(t, p); return false; }, }); } export function omit(obj, keys) { return new Proxy(obj, { get(t, p) { if (keys.includes(p)) return undefined; return Reflect.get(t, p); }, set(t, p, v) { if (keys.includes(p)) return false; return Reflect.set(t, p, v); }, has(t, p) { if (keys.includes(p)) return false; return Reflect.has(t, p); }, ownKeys(t) { return Reflect.ownKeys(t).filter((i) => !keys.includes(i)); }, deleteProperty(t, p) { if (keys.includes(p)) return false; return Reflect.deleteProperty(t, p); }, }); } export function readOnly(obj, _keys) { const keys = _keys || null; return new Proxy(obj, { set(t, p, v) { if (!keys || keys.includes(p)) return false; return Reflect.set(t, p, v); }, deleteProperty(t, p) { if (!keys || keys.includes(p)) return false; return Reflect.deleteProperty(t, p); }, }); } export function writeOnly(obj, _keys) { const keys = _keys || null; return new Proxy(obj, { get(t, p) { if (!keys || keys.includes(p)) return undefined; return Reflect.get(t, p); }, }); }