diff --git a/lib/resolve-idx-refs.js b/lib/resolve-idx-refs.js new file mode 100644 index 00000000..78c8defa --- /dev/null +++ b/lib/resolve-idx-refs.js @@ -0,0 +1,36 @@ +'use strict' + +const scanner = require('object-scan') +const toPath = require('lodash/toPath') +const get = require('lodash/get') + +// For all items in `tree` matching a path selector specified +// in `selector`, call `onRef` with the item, its parent and +// the path to the item. +// Example: +// tree: {foo: [{bar: 1}], hey: {there: [{bar: 2}]}} +// selector: **[*].bar +const findIdxRefs = (tree, selector, onRef) => { + const scan = scanner([selector]) + for (const pathStr of scan(tree)) { + const path = toPath(pathStr) + const val = get(tree, path) + const parent = get(tree, path.slice(0, -1), {}) + onRef(val, parent, path) + } +} + +// For all items in `tree` matching a path selector specified +// in `selector`: +// - interpret the item as an index in `source` +// - set the parent's field `prop` to `source[item]` +const resolveIdxRefs = (tree, selector, source, prop) => { + findIdxRefs(tree, selector, (idx, parent) => { + if ('number' === typeof idx) parent[prop] = source[idx] + }) +} + +module.exports = { + findIdxRefs, + resolveIdxRefs +} diff --git a/package.json b/package.json index 748d7a57..28149d77 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "gps-distance": "0.0.4", "lodash": "^4.17.5", "luxon": "^1.3.0", + "object-scan": "^10.0.9", "p-retry": "^4.1.0", "p-throttle": "^3.1.0", "pinkie-promise": "^2.0.1", diff --git a/parse/common.js b/parse/common.js index 35555edb..b70e0203 100644 --- a/parse/common.js +++ b/parse/common.js @@ -1,5 +1,8 @@ 'use strict' +const get = require('lodash/get') +const {findIdxRefs, resolveIdxRefs} = require('../lib/resolve-idx-refs') + // todo: move to separate file const parseIcon = (i) => { const res = { @@ -11,13 +14,13 @@ const parseIcon = (i) => { return res } -const parseCommonData = (profile, opt, raw) => { - const res = Object.assign({}, raw) - const c = raw.common || {} +const parseCommonData = (profile, opt, res) => { + const c = res.common || {} res.operators = [] if (Array.isArray(c.opL)) { res.operators = c.opL.map(op => profile.parseOperator(profile, op)) + resolveIdxRefs(res, '**.oprX', res.operators, 'operator') } res.icons = [] diff --git a/parse/line.js b/parse/line.js index 6de3f835..83f206d8 100644 --- a/parse/line.js +++ b/parse/line.js @@ -2,7 +2,7 @@ const slugg = require('slugg') -const createParseLine = (profile, opt, {operators}) => { +const createParseLine = (profile, opt, _) => { const byBitmask = [] for (let product of profile.products) { for (let bitmask of product.bitmasks) { @@ -37,10 +37,7 @@ const createParseLine = (profile, opt, {operators}) => { res.product = product && product.id || null } - if ('number' === typeof p.oprX) { - res.operator = operators[p.oprX] || null - } - + if (p.operator) res.operator = p.operator // todo: move up return res } return parseLine