Skip to content

Commit

Permalink
Start improve iterate()
Browse files Browse the repository at this point in the history
  • Loading branch information
ehmicky committed Mar 13, 2022
1 parent 64d234e commit d5c5403
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 33 deletions.
41 changes: 32 additions & 9 deletions src/config/normalize/lib/wild_wild_path/iterate.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,46 @@
import { groupBy } from '../../../../utils/group.js'

import { parse } from './parsing/parse.js'
import { serialize } from './parsing/serialize.js'
import { getObjectTokenType } from './tokens/main.js'

// List all values (and their associated path) matching a specific query for
// on specific target value.
export const iterate = function (target, queryOrPath) {
const path = parse(queryOrPath)
return path.reduce(listTokenEntries, [
{ value: target, path: [], missing: false },
])
export const iterate = function (target, queryOrPaths) {
const paths = parse(queryOrPaths)
const entries = paths.map((path) => ({
path,
value: target,
props: [],
missing: false,
}))
const entriesA = iterateLevel(entries, 0)
return entriesA
}

const listTokenEntries = function (entries, token) {
return entries.flatMap((entry) => getTokenEntries(entry, token))
const iterateLevel = function (entries, index) {
const parentEntries = entries.filter(({ path }) => path.length === index)
const levelEntries = entries
.filter(({ path }) => path.length !== index)
.flatMap((entry) => iteratePath(entry, index))
const entriesGroups = Object.values(groupBy(levelEntries, 'prop'))
const nextIndex = index + 1
const childEntries = entriesGroups.flatMap((levelEntriesA) =>
iterateLevel(levelEntriesA, nextIndex),
)
return [...parentEntries, ...childEntries]
}

const getTokenEntries = function ({ value, path }, token) {
const iteratePath = function ({ path, value, props }, index) {
const token = path[index]
const { tokenType, missing, value: valueA } = handleMissingValue(value, token)
return tokenType.iterate(valueA, path, token, missing)
const levelEntries = tokenType.iterate(valueA, token, missing)
return levelEntries.map(({ value: childValue, prop, missing: missingA }) => ({
path,
value: childValue,
props: [...props, prop],
missing: missingA,
}))
}

// When the value does not exist, we set it deeply with `set()` but not with
Expand Down
7 changes: 3 additions & 4 deletions src/config/normalize/lib/wild_wild_path/tokens/any.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,18 @@ const normalize = function ({ type }) {

// Use the token to list entries against a target value.
// We purposely ignore symbol properties by using `Object.keys()`.
// eslint-disable-next-line max-params
const iterate = function (value, path, token, missing) {
const iterate = function (value, token, missing) {
if (Array.isArray(value)) {
return value.map((childValue, index) => ({
value: childValue,
path: [...path, index],
prop: index,
missing,
}))
}

return Object.keys(value).map((childKey) => ({
value: value[childKey],
path: [...path, childKey],
prop: childKey,
missing,
}))
}
Expand Down
5 changes: 2 additions & 3 deletions src/config/normalize/lib/wild_wild_path/tokens/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,12 @@ const normalize = function (token) {
}

// Use the token to list entries against a target value.
// eslint-disable-next-line max-params
const iterate = function (value, path, token, missing) {
const iterate = function (value, token, missing) {
const index = getArrayIndex(value, token)
return [
{
value: value[index],
path: [...path, index],
prop: index,
missing: missing || index >= value.length,
},
]
Expand Down
9 changes: 2 additions & 7 deletions src/config/normalize/lib/wild_wild_path/tokens/prop.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,9 @@ const normalize = function (token) {
// We distinguish between:
// - Missing property name: return no entries
// - Property exists but has `undefined` value: return an entry
// eslint-disable-next-line max-params
const iterate = function (value, path, token, missing) {
const iterate = function (value, token, missing) {
return [
{
value: value[token],
path: [...path, token],
missing: missing || !(token in value),
},
{ value: value[token], prop: token, missing: missing || !(token in value) },
]
}

Expand Down
9 changes: 2 additions & 7 deletions src/config/normalize/lib/wild_wild_path/tokens/regexp.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,10 @@ const equals = function (tokenA, tokenB) {
}

// Use the token to list entries against a target value.
// eslint-disable-next-line max-params
const iterate = function (value, path, token, missing) {
const iterate = function (value, token, missing) {
return Object.keys(value)
.filter((childKey) => token.test(childKey))
.map((childKey) => ({
value: value[childKey],
path: [...path, childKey],
missing,
}))
.map((childKey) => ({ value: value[childKey], prop: childKey, missing }))
}

export const REGEXP_TOKEN = {
Expand Down
5 changes: 2 additions & 3 deletions src/config/normalize/lib/wild_wild_path/tokens/slice.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,12 @@ const normalize = function ({ type, from = 0, to }) {
}

// Use the token to list entries against a target value.
// eslint-disable-next-line max-params
const iterate = function (value, path, { from, to }, missing) {
const iterate = function (value, { from, to }, missing) {
const fromIndex = getBoundedIndex(value, from)
const toIndex = Math.max(getBoundedIndex(value, to), fromIndex)
return new Array(toIndex - fromIndex).fill().map((_, index) => ({
value: value[index + fromIndex],
path: [...path, index + fromIndex],
prop: index + fromIndex,
missing,
}))
}
Expand Down

0 comments on commit d5c5403

Please sign in to comment.