optix
Version:
Optix is a data manipulation library that provides optics-like capabilites with a simpler syntax. It features robust Typescript support with minimal type annotations and is smaller and faster than true optics libraries.
140 lines (133 loc) • 4.79 kB
JavaScript
const _get = (obj, path) => {
if (!path.length) {
return obj;
}
const slicedPath = path.slice(1);
const resolved = typeof path[0] === "function" ? path[0](obj) : path[0];
return Array.isArray(resolved)
? resolved.map((idx) => obj != null ? _get(obj[idx], slicedPath) : undefined)
: obj != null
? _get(obj[resolved], slicedPath)
: undefined;
};
const _update = (obj, path, updater) => {
if (!path.length) {
return updater(obj);
}
const slicedPath = path.slice(1);
const resolved = typeof path[0] === "function" ? path[0](obj) : path[0];
const keysToUpdate = typeof resolved === "string" || typeof resolved === "number"
? [resolved]
: Array.isArray(resolved)
? resolved
: [];
// check for invalid path
const typeofKey0 = typeof keysToUpdate[0];
if ((typeofKey0 !== "string" && typeofKey0 !== "number") ||
keysToUpdate[0] < 0) {
return obj;
}
const treatObjAsArray = typeofKey0 === "number";
const newObj = obj && typeof obj === "object"
? treatObjAsArray
? obj.slice(0)
: Object.assign({}, obj)
: treatObjAsArray
? []
: {};
for (let i = 0; i < keysToUpdate.length; i++) {
newObj[keysToUpdate[i]] = _update(newObj[keysToUpdate[i]], slicedPath, updater);
}
return newObj;
};
const _set = (object, path, value) => _update(object, path, () => value);
const _remove = (obj, path) => {
if (!path.length || !obj || typeof obj !== "object") {
return obj;
}
const resolved = typeof path[0] === "function" ? path[0](obj) : path[0];
const keysToRemove = typeof resolved === "string" || typeof resolved === "number"
? [resolved]
: Array.isArray(resolved)
? resolved
: [];
// check for invalid path
const typeofKey0 = typeof keysToRemove[0];
if ((typeofKey0 !== "string" && typeofKey0 !== "number") ||
keysToRemove[0] < 0) {
return obj;
}
if (path.length === 1) {
let newObj;
if (Array.isArray(obj)) {
const keySet = new Set(keysToRemove);
newObj = [];
for (let i = 0; i < obj.length; i++) {
if (!keySet.has(i)) {
newObj.push(obj[i]);
}
}
}
else {
newObj = Object.assign({}, obj);
for (let i = 0; i < keysToRemove.length; i++) {
delete newObj[keysToRemove[i]];
}
}
return newObj;
}
else {
const slicedPath = path.slice(1);
const newObj = Array.isArray(obj) ? obj.slice(0) : Object.assign({}, obj);
for (let i = 0; i < keysToRemove.length; i++) {
const keyToRemove = keysToRemove[i];
if ({}.hasOwnProperty.call(newObj, keyToRemove)) {
newObj[keyToRemove] = _remove(newObj[keyToRemove], slicedPath);
}
}
return newObj;
}
};
const last = (arr) => arr.length - 1;
const all = (arr) => arr.map((_, i) => i);
const keys = Object.keys;
const find = (predicate) => (arr) => {
for (let i = 0; i < arr.length; i++) {
if (predicate(arr[i]))
return i;
}
return -1;
};
const findByKey = (predicate) => (obj) => {
for (let i = 0, keys = Object.keys(obj); i < keys.length; i++) {
if (predicate(keys[i]))
return keys[i];
}
};
const findByVal = (predicate) => (obj) => findByKey(key => predicate(obj[key]))(obj);
const filter = (predicate) => (arr) => {
const filtered = [];
for (let i = 0; i < arr.length; i++) {
if (predicate(arr[i]))
filtered.push(i);
}
return filtered;
};
const filterByKey = (predicate) => (obj) => {
const filtered = [];
const keys = Object.keys(obj);
for (let i = 0; i < keys.length; i++) {
if (predicate(keys[i]))
filtered.push(keys[i]);
}
return filtered;
};
const filterByVal = (predicate) => (obj) => filterByKey(key => predicate(obj[key]))(obj);
const get = (...path) => (obj) => _get(obj, path);
const set = (...path) => (value) => (obj) => _set(obj, path, value);
const update = (...path) => (updater) => (obj) => _update(obj, path, updater);
const remove = (...path) => (obj) => _remove(obj, path);
const polySet = set;
const polyUpdate = update;
const polyRemove = remove;
export { _get, _remove, _set, _update, all, filter, filterByKey, filterByVal, find, findByKey, findByVal, get, keys, last, polyRemove, polySet, polyUpdate, remove, set, update };