dbl-utils
Version:
Utilities for dbl, adba and others projects
125 lines (124 loc) • 4.85 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const object_mutation_1 = require("./object-mutation");
const flat_1 = require("./flat");
/**
* Processes rules to determine tasks for each item.
* @param {string} key - The key to process rules for.
* @param {any} schema - The schema to resolve data against.
* @param {Options} opts - Configuration options including rules and extra tasks.
* @returns {*} The processed data or undefined.
*/
const processRules = (key, schema, opts) => {
if (!opts.rules || !opts.rules[key])
return undefined;
const tasks = Object.assign({ iterate: (keyData, itemName) => {
const data = loop(keyData, schema, opts);
if (!Array.isArray(data))
return [];
const itemFound = key.substring(1).split(opts.delimiter)
.reduce((obj, k) => obj[k], schema);
const builded = data.map((item) => {
schema[itemName] = item;
return loop(itemFound, schema, opts);
});
delete schema[itemName];
return builded;
}, join: (first, join, ...next) => {
const f = loop(first, schema, opts);
if (Array.isArray(f))
return f.join(join);
return [f, ...loop([join, ...next], schema, opts)].join('');
}, ignore: (d, def) => {
return d.substring(1).split(opts.delimiter)
.reduce((obj, k) => obj[k], schema) || def;
}, if: (d, found, def) => {
return (d.substring(1).split(opts.delimiter)
.reduce((obj, k) => obj[k], schema) && loop(found, schema, opts)) || def;
} }, opts.extraTasks);
const [task, ...attrs] = opts.rules[key];
return typeof tasks[task] === 'function' ? tasks[task](...attrs) : undefined;
};
/**
* Loop through an item and resolve references.
* @param {*} item - The item to process.
* @param {*} schema - The schema of the object.
* @param {Options} opts - Configuration options.
* @returns {*} The object with resolved references.
*/
const loop = (item, schema, opts) => {
if (item === null)
return item;
if (typeof opts.omit === 'function' && opts.omit(item))
return item;
if (Array.isArray(item)) {
return item.map(a => loop(a, schema, opts)).flat();
}
else if (typeof item === 'object') {
let mergedObject = {};
if (item.ref) {
const ref = item.ref;
delete item.ref;
const unflattened = (0, flat_1.unflatten)(item, opts.delimiter);
console.log(unflattened);
const refObj = loop(ref, schema, opts);
const modify = loop(unflattened, schema, opts);
mergedObject = typeof refObj === 'string'
? (0, object_mutation_1.deepMerge)({ ref: refObj }, modify)
: (0, object_mutation_1.deepMerge)({}, refObj, modify);
}
else {
for (const key of Object.keys(item)) {
mergedObject[key] = loop(item[key], schema, opts);
}
}
return mergedObject;
}
else if (typeof item === 'string' && item[0] === '$') {
const fixed = processRules(item, schema, opts);
if (fixed !== undefined)
return fixed;
const orKeys = item.substring(1).split(opts.delimiter);
;
let data;
for (const orKey of orKeys) {
const keys = orKey.split(opts.delimiter);
data = keys.reduce((obj, key) => {
return obj ? obj[key] : undefined;
}, schema);
if (data !== undefined)
break;
}
if (data === undefined) {
return opts.notFound !== undefined ? opts.notFound : item;
}
if (data.constructor.name === 'Object') {
data = JSON.parse(JSON.stringify(data));
}
const loopAgain = (typeof opts.deep === 'number' && opts.deep > 0) ? !!(--opts.deep) : true;
return loopAgain ? loop(data, schema, opts) : data;
}
else {
return item;
}
};
/**
* Resolves the references of an object.
* @param {*} object - The object to process.
* @param {*} schema - The schema of the object.
* @param {Options} options - Configuration options.
* @returns {*} The object with resolved references.
*/
const resolveRefs = (object, schema, options = {}) => {
const opts = {
delimiter: options.delimiter || '/',
omit: options.omit,
notFound: options.notFound,
deep: options.deep,
rules: options.rules || {},
extraTasks: options.extraTasks || {},
};
const clonedObject = JSON.parse(JSON.stringify(object));
return loop(clonedObject, schema || clonedObject, opts);
};
exports.default = resolveRefs;