Comparing version 1.0.8 to 1.0.9
{ | ||
"optOut": false, | ||
"lastUpdateCheck": 1666021392557 | ||
"lastUpdateCheck": 1666107934926 | ||
} |
{ | ||
"name": "manyfest", | ||
"version": "1.0.8", | ||
"version": "1.0.9", | ||
"description": "JSON Object Manifest for Data Description and Parsing", | ||
@@ -61,3 +61,6 @@ "main": "source/Manyfest.js", | ||
}, | ||
"dependencies": {}, | ||
"dependencies": { | ||
"elucidator": "^1.0.2", | ||
"precedent": "^1.0.6" | ||
}, | ||
"author": "steven velozo <steven@velozo.com>", | ||
@@ -64,0 +67,0 @@ "license": "MIT", |
@@ -6,2 +6,3 @@ /** | ||
let libSimpleLog = require('./Manyfest-LogToConsole.js'); | ||
let libPrecedent = require('precedent'); | ||
@@ -23,2 +24,4 @@ /** | ||
* | ||
* TODO: Once we validate this pattern is good to go, break these out into | ||
* three separate modules. | ||
* | ||
@@ -34,2 +37,5 @@ * @class ManyfestObjectAddressResolver | ||
this.logError = (typeof(pErrorLog) == 'function') ? pErrorLog : libSimpleLog; | ||
this.elucidatorSolver = false; | ||
this.elucidatorSolverState = {}; | ||
} | ||
@@ -242,9 +248,53 @@ | ||
checkFilters(pAddress, pRecord) | ||
{ | ||
let tmpPrecedent = new libPrecedent(); | ||
// If we don't copy the string, precedent takes it out for good. | ||
// TODO: Consider adding a "don't replace" option for precedent | ||
let tmpAddress = pAddress; | ||
if (this.elucidatorSolver) | ||
{ | ||
// This allows the magic filtration with elucidator configuration | ||
// TODO: We could pass more state in (e.g. parent address, object, etc.) | ||
// TODO: Discuss this metaprogramming AT LENGTH | ||
let tmpFilterState = ( | ||
{ | ||
Record: pRecord, | ||
keepRecord: true | ||
}); | ||
// This is about as complex as it gets. | ||
// TODO: Optimize this so it is only initialized once. | ||
// TODO: That means figuring out a healthy pattern for passing in state to this | ||
tmpPrecedent.addPattern('{<~~', '~~>}', | ||
(pInstructionHash) => | ||
{ | ||
// This is for internal config on the solution steps. Right now config is not shared across steps. | ||
if (this.elucidatorSolverState.hasOwnProperty(pInstructionHash)) | ||
{ | ||
tmpFilterState.SolutionState = this.elucidatorSolverState[pInstructionHash]; | ||
} | ||
this.elucidatorSolver.solveInternalOperation('Custom', pInstructionHash, tmpFilterState); | ||
}); | ||
tmpPrecedent.parseString(tmpAddress); | ||
// It is expected that the operation will mutate this to some truthy value | ||
return tmpFilterState.keepRecord; | ||
} | ||
else | ||
{ | ||
return true; | ||
} | ||
} | ||
// Get the value of an element at an address | ||
getValueAtAddress (pObject, pAddress, pParentAddress) | ||
{ | ||
// Make sure pObject is an object | ||
// Make sure pObject (the object we are meant to be recursing) is an object (which could be an array or object) | ||
if (typeof(pObject) != 'object') return undefined; | ||
// Make sure pAddress is a string | ||
// Make sure pAddress (the address we are resolving) is a string | ||
if (typeof(pAddress) != 'string') return undefined; | ||
// Stash the parent address for later resolution | ||
let tmpParentAddress = ""; | ||
@@ -344,3 +394,15 @@ if (typeof(pParentAddress) == 'string') | ||
return pObject[tmpBoxedPropertyName]; | ||
let tmpInputArray = pObject[tmpBoxedPropertyName]; | ||
let tmpOutputArray = []; | ||
for (let i = 0; i < tmpInputArray.length; i++) | ||
{ | ||
// The filtering is complex but allows config-based metaprogramming directly from schema | ||
let tmpKeepRecord = this.checkFilters(pAddress, tmpInputArray[i]); | ||
if (tmpKeepRecord) | ||
{ | ||
tmpOutputArray.push(tmpInputArray[i]); | ||
} | ||
} | ||
return tmpOutputArray; | ||
} | ||
@@ -464,3 +526,4 @@ // The object has been flagged as an object set, so treat it as such | ||
let tmpPropertyParentAddress = `${tmpParentAddress}[${i}]`; | ||
let tmpValue = this.getValueAtAddress(pObject[tmpBoxedPropertyName][i], tmpNewAddress, tmpPropertyParentAddress);; | ||
let tmpValue = this.getValueAtAddress(pObject[tmpBoxedPropertyName][i], tmpNewAddress, tmpPropertyParentAddress); | ||
tmpContainerObject[`${tmpPropertyParentAddress}.${tmpNewAddress}`] = tmpValue; | ||
@@ -495,4 +558,10 @@ } | ||
let tmpPropertyParentAddress = `${tmpParentAddress}.${tmpObjectPropertyKeys[i]}`; | ||
let tmpValue = this.getValueAtAddress(pObject[tmpObjectPropertyName][tmpObjectPropertyKeys[i]], tmpNewAddress, tmpPropertyParentAddress);; | ||
tmpContainerObject[`${tmpPropertyParentAddress}.${tmpNewAddress}`] = tmpValue; | ||
let tmpValue = this.getValueAtAddress(pObject[tmpObjectPropertyName][tmpObjectPropertyKeys[i]], tmpNewAddress, tmpPropertyParentAddress); | ||
// The filtering is complex but allows config-based metaprogramming directly from schema | ||
let tmpKeepRecord = this.checkFilters(pAddress, tmpValue); | ||
if (tmpKeepRecord) | ||
{ | ||
tmpContainerObject[`${tmpPropertyParentAddress}.${tmpNewAddress}`] = tmpValue; | ||
} | ||
} | ||
@@ -499,0 +568,0 @@ |
@@ -7,2 +7,4 @@ /** | ||
let libPrecedent = require('precedent'); | ||
let libHashTranslation = require('./Manyfest-HashTranslation.js'); | ||
@@ -52,2 +54,6 @@ let libObjectAddressResolver = require('./Manyfest-ObjectAddressResolver.js'); | ||
this.elementDescriptors = undefined; | ||
// This can cause a circular dependency chain, so it only gets initialized if the schema specifically calls for it. | ||
this.dataSolvers = undefined; | ||
// So solvers can use their own state | ||
this.dataSolverState = undefined; | ||
@@ -78,2 +84,7 @@ this.reset(); | ||
this.elementDescriptors = {}; | ||
this.dataSolvers = undefined; | ||
this.dataSolverState = {}; | ||
this.libElucidator = undefined; | ||
this.objectAddressResolver.elucidatorSolver = false; | ||
} | ||
@@ -145,2 +156,31 @@ | ||
} | ||
// This seems like it would create a circular dependency issue but it only goes as deep as the schema defines Solvers | ||
if ((pManifest.hasOwnProperty('Solvers')) && (typeof(pManifest.Solvers) == 'object')) | ||
{ | ||
// There are elucidator solvers passed-in, so we will create one to filter data. | ||
let libElucidator = require('elucidator'); | ||
// WARNING THESE CAN MUTATE THE DATA | ||
// The pattern for the solver is: {<~~SolverName~~>} anywhere in a property. | ||
// Yes, this means your Javascript elements can't have my self-styled jellyfish brackets in them. | ||
// This does, though, mean we can filter at multiple layers safely. | ||
// Because these can be put at any address | ||
// The solver themselves: | ||
// They are passed-in an object, and the current record is in the Record subobject. | ||
// Basic operations can just write to the root object but... | ||
// IF YOU PERMUTE THE Record SUBOBJECT YOU CAN AFFECT RECURSION | ||
// This is mostly meant for if statements to filter. | ||
// Basically on aggregation, if a filter is set it will set "keep record" to true and let the solver decide differently. | ||
this.dataSolvers = new libElucidator(pManifest.Solvers, this.logInfo, this.logError); | ||
this.objectAddressResolver.elucidatorSolver = this.dataSolvers; | ||
// Load the solver state in so each instruction can have internal config | ||
// TODO: Should this just be a part of the lower layer pattern? | ||
let tmpSolverKeys = Object.keys(pManifest.Solvers) | ||
for (let i = 0; i < tmpSolverKeys.length; i++) | ||
{ | ||
this.dataSolverState[tmpSolverKeys] = pManifest.Solvers[tmpSolverKeys[i]]; | ||
} | ||
this.objectAddressResolver.elucidatorSolverState = this.dataSolverState; | ||
} | ||
} | ||
@@ -147,0 +187,0 @@ |
248885
43
4162
2
+ Addedelucidator@^1.0.2
+ Addedprecedent@^1.0.6
+ Addeddecimal.js@10.5.0(transitive)
+ Addedelucidator@1.0.9(transitive)
+ Addedfable-serviceproviderbase@3.0.15(transitive)
+ Addedprecedent@1.0.15(transitive)