-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
130 additions
and
125 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import isPlainObj from 'is-plain-obj' | ||
|
||
import { parseQuery } from './parse.js' | ||
|
||
// List all values (and their associated path) matching a specific query for | ||
// on specific target value. | ||
export const listEntries = function (target, query) { | ||
const tokens = parseQuery(query) | ||
return tokens.reduce(listTokenEntries, [{ value: target, path: [] }]) | ||
} | ||
|
||
const listTokenEntries = function (entries, token) { | ||
return entries.flatMap((entry) => getTokenEntries(entry, token)) | ||
} | ||
|
||
const getTokenEntries = function ( | ||
{ value, path }, | ||
{ key, isArray, isAny, isStrict }, | ||
) { | ||
if (isArray) { | ||
const missing = !Array.isArray(value) | ||
|
||
if (missing) { | ||
if (isStrict) { | ||
if (isAny || key === 0) { | ||
return [{ value, path: [...path, { key: 0, missing }] }] | ||
} | ||
|
||
return [{ value: undefined, path: [...path, { key, missing }] }] | ||
} | ||
|
||
return [] | ||
} | ||
|
||
if (isAny) { | ||
return value.map((childValue, index) => ({ | ||
value: childValue, | ||
path: [...path, { key: index, missing }], | ||
})) | ||
} | ||
|
||
return [{ value: value[key], path: [...path, { key, missing }] }] | ||
} | ||
|
||
const missing = !isPlainObj(value) | ||
|
||
if (missing) { | ||
if (isStrict) { | ||
return [{ value: undefined, path: [...path, { key, missing }] }] | ||
} | ||
|
||
return [] | ||
} | ||
|
||
if (isAny) { | ||
return Object.entries(value).map(([childKey, childValue]) => ({ | ||
value: childValue, | ||
path: [...path, { key: childKey, missing }], | ||
})) | ||
} | ||
|
||
return [{ value: value[key], path: [...path, { key, missing }] }] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,44 @@ | ||
import { getPropResults } from './results.js' | ||
import { listEntries } from './entries.js' | ||
|
||
export const getEntries = function (object, propPathStr) { | ||
const propResults = getPropResults(object, propPathStr) | ||
return propResults.map(getEntry) | ||
// Retrieve all entries (values + paths) matching a query string in `target` | ||
export const getEntries = function (target, query) { | ||
const entries = listEntries(target, query) | ||
return entries.map(normalizeEntry) | ||
} | ||
|
||
const getEntry = function ({ value, path }) { | ||
const key = getKey({ path }) | ||
return { key, value } | ||
const normalizeEntry = function ({ value, path }) { | ||
const pathStr = serializePath({ path }) | ||
return { path: pathStr, value } | ||
} | ||
|
||
export const getValues = function (object, propPathStr) { | ||
const propResults = getPropResults(object, propPathStr) | ||
return propResults.map(getValue) | ||
// Same but only retrieving the values | ||
export const getValues = function (target, query) { | ||
const entris = listEntries(target, query) | ||
return entris.map(getEntryValue) | ||
} | ||
|
||
const getValue = function ({ value }) { | ||
const getEntryValue = function ({ value }) { | ||
return value | ||
} | ||
|
||
export const getKeys = function (object, propPathStr) { | ||
const propResults = getPropResults(object, propPathStr) | ||
return propResults.map(getKey) | ||
// Same but only retrieving the paths | ||
export const getPaths = function (target, query) { | ||
const entries = listEntries(target, query) | ||
return entries.map(serializePath) | ||
} | ||
|
||
const getKey = function ({ path }) { | ||
return path.map(getPathName).reduce(serializePathName, '') | ||
const serializePath = function ({ path }) { | ||
return path.map(getPathKey).reduce(appendKey, '') | ||
} | ||
|
||
const getPathName = function ({ name }) { | ||
return name | ||
const getPathKey = function ({ key }) { | ||
return key | ||
} | ||
|
||
const serializePathName = function (names, name) { | ||
if (typeof name !== 'string') { | ||
return `${names}[${name}]` | ||
const appendKey = function (pathStr, key) { | ||
if (typeof key !== 'string') { | ||
return `${pathStr}[${key}]` | ||
} | ||
|
||
return names === '' ? `${names}${name}` : `${names}.${name}` | ||
return pathStr === '' ? `${pathStr}${key}` : `${pathStr}.${key}` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,27 @@ | ||
import { setArray } from '../../../utils/set.js' | ||
|
||
import { getPropResults } from './results.js' | ||
import { listEntries } from './entries.js' | ||
|
||
export const set = function (object, propPathStr, setValue) { | ||
const propResults = getPropResults(object, propPathStr) | ||
return propResults.reduce( | ||
(objectA, { path }) => setResult(objectA, path, setValue), | ||
object, | ||
// Set a value to one or multiple properties in `target` using a query string | ||
export const set = function (target, query, setValue) { | ||
const entries = listEntries(target, query) | ||
return entries.reduce( | ||
(targetA, { path }) => setResult(targetA, path, setValue), | ||
target, | ||
) | ||
} | ||
|
||
const setResult = function (value, [{ name, missing }, ...path], setValue) { | ||
if (typeof name === 'string') { | ||
const setResult = function (value, [{ key, missing }, ...path], setValue) { | ||
if (typeof key === 'string') { | ||
const setValueA = | ||
path.length === 0 | ||
? setValue | ||
: setResult(missing ? {} : value[name], path, setValue) | ||
return { ...value, [name]: setValueA } | ||
: setResult(missing ? {} : value[key], path, setValue) | ||
return { ...value, [key]: setValueA } | ||
} | ||
|
||
const valueA = missing ? [value] : value | ||
const setValueB = | ||
path.length === 0 ? setValue : setResult(valueA[name], path, setValue) | ||
return setArray(valueA, name, setValueB) | ||
path.length === 0 ? setValue : setResult(valueA[key], path, setValue) | ||
return setArray(valueA, key, setValueB) | ||
} |