UNPKG

entodicton

Version:

97 lines (90 loc) 2.49 kB
const _ = require('lodash') const helpers = require('./helpers') function pathEquals (p1, p2) { if (p1.length !== p2.length) { return false } for (let i = 0; i < p1.length; ++i) { if (p1[i] !== p2[i]) { return false } } return true } function fragmentInstantiator (args, contexts) { return new Object({ contexts: () => { return _.cloneDeep(contexts) }, instantiate: async (mappings) => { const instantiated = _.cloneDeep(contexts) const todo = [{ context: instantiated, path: [] }] args = { ...args } args.pathEquals = pathEquals while (todo.length > 0) { const { context, path } = todo.pop() args.context = context args.path = path for (const mapping of mappings) { if (await mapping.match(args)) { await mapping.apply(args) } } for (const key of Object.keys(context)) { // if (['number', 'string', 'boolean'].includes(typeof (context[key]))) { if (!helpers.isCompound(context[key])) { continue } if (context[key].instantiated) { continue } todo.push({ context: context[key], path: [...path, key] }) } } if (contexts.length == 1 && instantiated.length == 1) { return instantiated[0] } else { return instantiated } } }) } async function fragmentMapperInstantiator(values, modelFrom, modelTo) { const paths = {} for (const value of values) { paths[value] = { value } } { const fi = fragmentInstantiator({paths}, modelFrom) await fi.instantiate([ { match: ({context, path}) => values.includes(context.value), apply: ({context, path}) => paths[context.value].from = path }, ]) } { const fi = fragmentInstantiator({paths}, modelTo) await fi.instantiate([ { match: ({context, path}) => values.includes(context.value), apply: ({context, path}) => paths[context.value].to = path }, ]) } return { instantiate: (actualFrom) => { const actualTo = structuredClone(modelTo) for (const value in paths) { const { from, to } = paths[value] const actualValue = helpers.getByPath(actualFrom, from, null) helpers.setByPath(actualTo, to, actualValue) } return actualTo } } } module.exports = { fragmentInstantiator, fragmentMapperInstantiator, }