UNPKG

deleight

Version:

A library with 9 modules for writing more expressive web applications with traditional HTML, CSS and JavaScript.

312 lines (311 loc) 9.84 kB
"use strict"; /** * Functions form manipulating multiple objects at once. * The functions let you perform object operations like `get`, `set`, * `call method` and `delete` in bulk. * * They all support nested operations so that complex reactivity patterns * can be implemented. * * Additionally, functions can be supplied in place of any objects (placed * inside the object arg) to perform more arbitrary operations. * * The functions are async so we can pass in an iterable or async iterable * (or a function that returns either) as values in the object arg. Awaiting * the promise returned will ensure all the operations complete before * calling code continues. * * @module */ Object.defineProperty(exports, "__esModule", { value: true }); exports.dels = exports.callsFor = exports.calls = exports.sets = exports.gets = exports.M = exports.Mapper = exports.I = void 0; const own_js_1 = require("../own/own.js"); exports.I = Symbol(); /** * Used to transform property keys and existing values to replacement * values in the {@link sets} function. */ class Mapper { constructor(value) { this.value = value; } } exports.Mapper = Mapper; /** * Returns a value that is interpreted as a mapper * (from the key, old value and object to the new value) in the * {@link sets} function. * * @example * import { set, M } from 'deleight/object/sharedmember' * let obj1 = { a: 20, b: 2, c: 20}, obj2 = { a: 1, b: 20, c: 3}; * const objects = { a: [obj1], b: [obj2], c: [obj1] }; * * set(objects, M((obj, key) => obj[key] * 2)); * console.log(obj1); // { a: 40, b: 2, c: 40} * console.log(obj2); // { a: 1, b: 40, c: 3} * * @param value * @returns */ function M(value) { return new Mapper(value); } exports.M = M; /** * Gets specified properties from different objects. * * The `map` argument maps property keys to iterables of objects (or functions that return such iterables). * * @example * import { get } from 'deleight/object/shared' * let obj1 = { a: 1, b: 2, c: 3 }, obj2 = { a: 1, b: 2, c: 3 }; * const objects = { a: [obj1], b: [obj2], c: [obj1] }; * const vals = get(objects); // { a: [1], b: [2], c: [3] } * * @param object */ async function* gets(object) { let targets, subKey, vals; for (let key of (0, own_js_1.ownKeys)(object)) { targets = object[key]; if (key === exports.I) { for await (let value of gets(targets)) yield value; continue; } if (targets instanceof Function) targets = targets(object, key); if (Reflect.has(targets, Symbol.iterator)) { for (let target of targets) { if (target instanceof Function) { yield [key, target(key)]; } else yield [key, target[key]]; } } else if (Reflect.has(targets, Symbol.asyncIterator)) { for await (let target of targets) { if (target instanceof Function) { yield [key, target(key)]; } else yield [key, target[key]]; } } else { for await (vals of gets(targets)) { yield [key, ...vals]; } } } } exports.gets = gets; /** * Sets specified properties in different objects. * * Both simple and complex values can be set to implement any form of * reactivity we want. * * * @example * import { set } from 'deleight/object/shared' * let obj1 = { a: 1, b: 2, c: 3 }, obj2 = { a: 1, b: 2, c: 3 }; * const objects = { a: [obj1], b: [obj2], c: [obj1] }; * set(objects, 20); * console.log(obj1); // { a: 20, b: 2, c: 20} * console.log(obj2); // { a: 1, b: 20, c: 3} * * @param object * @param value */ async function sets(object, value) { let target, targets, subKey; const promises = []; for (let key of (0, own_js_1.ownKeys)(object)) { targets = object[key]; if (key === exports.I) { promises.push(sets(targets, value)); continue; } if (targets instanceof Function) targets = targets(object, key, value); if (Reflect.has(targets, Symbol.iterator)) { for (target of targets) { if (target instanceof Function) { target(key, value); } else { if (value instanceof Mapper) target[key] = value.value(target, key); else target[key] = value; } } } else if (Reflect.has(targets, Symbol.asyncIterator)) { // async sets for await (let target of targets) { if (target instanceof Function) { target(key, value); } else { if (value instanceof Mapper) target[key] = value.value(target, key); else target[key] = value; } } } else { // nested `sets` promises.push(sets(targets, value[key])); } } await Promise.all(promises); } exports.sets = sets; /** * Calls specified methods in multiple objects. * * @example * import { call } from 'deleight/object/shared' * let arr1 = [1, 2, 3], arr2 = [1, 2, 3], arr3 = [1, 2, 3]; * const objects = { push: [arr1, arr3], unshift: [arr2] }; * call(objects, 20, 21); * console.log(arr1) // [1, 2, 3, 20, 21] * console.log(arr2) // [20, 21, 1, 2, 3] * console.log(arr3) // [1, 2, 3, 20, 21] * * @param object * @param args */ async function calls(object, ...args) { let targets, target, subKey; const promises = []; for (let key of (0, own_js_1.ownKeys)(object)) { targets = object[key]; if (key === exports.I) { promises.push(calls(targets, ...args)); continue; } if (targets instanceof Function) targets = targets(object, key, ...args); if (Reflect.has(targets, Symbol.iterator)) { for (target of targets) { if (target instanceof Function) target(...args); else target[key](...args); } } else if (Reflect.has(targets, Symbol.asyncIterator)) { for await (let target of targets) { if (target instanceof Function) target(...args); else target[key](...args); } } else { const subArgs = args.map(arg => arg[subKey]); promises.push(calls(targets, ...subArgs)); } } await Promise.all(promises); } exports.calls = calls; /** * Calls specified methods in multiple objects to return results. * Returns an async iterable of key-result pairs where each key * can be paired with multiple results, depending on the input map. * * Nested calls will have multiple keys before their results. * * @example * * @param object * @param args */ async function* callsFor(object, ...args) { let targets, subKey, vals; for (let key of (0, own_js_1.ownKeys)(object)) { targets = object[key]; if (key === exports.I) { for await (let value of callsFor(targets, ...args)) yield value; continue; } if (targets instanceof Function) targets = targets(object, key, ...args); if (Reflect.has(targets, Symbol.iterator)) { for (let target of targets) { if (target instanceof Function) yield [key, target(...args)]; else yield [key, target[key](...args)]; } } else if (Reflect.has(targets, Symbol.asyncIterator)) { for await (let target of targets) { if (target instanceof Function) yield [key, target(...args)]; else yield [key, target[key](...args)]; } } else { const subArgs = args.map(arg => arg[subKey]); for await (vals of callsFor(targets, ...subArgs)) { yield [key, ...vals]; } } } } exports.callsFor = callsFor; /** * Deletes specified properties from different objects. * * @example * import { del } from 'deleight/object/shared' * let obj1 = { a: 1, b: 2, c: 3 }, obj2 = { a: 1, b: 2, c: 3 }; * del({ a: [obj1], b: [obj2], c: [obj1] }); * console.log(obj1); // { b: 2 } * console.log(obj2); // { a: 1, c: 3} * * @param object */ async function dels(object) { let target, targets, subKey; const promises = []; for (let key of (0, own_js_1.ownKeys)(object)) { targets = object[key]; if (key === exports.I) { promises.push(dels(targets)); continue; } if (targets instanceof Function) targets = targets(object, key); if (Reflect.has(targets, Symbol.iterator)) { for (target of targets) { if (target instanceof Function) target(key); else delete target[key]; } } else if (Reflect.has(targets, Symbol.asyncIterator)) { for await (let target of targets) { if (target instanceof Function) target(key); else delete target[key]; } } else { promises.push(dels(targets)); } } await Promise.all(promises); } exports.dels = dels;