theprogrammablemind_4wp
Version:
84 lines (78 loc) • 2.26 kB
JavaScript
const _ = require('lodash')
const helpers = require('./helpers')
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 }
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,
}