Package Exports
- deep-entries
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (deep-entries) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
deep-entries
A utility that resolves deeply nested key-values as variadic tuples.
- Comparable to:
TL;DR: examples
install
Node
> npm install deep-entriesimport { deepEntries } = from 'deep-entries'Deno
Either / or:
import { deepEntries } from 'npm:deep-entries'
import { deepEntries } from 'https://deno.land/x/deepentries@v5/src/index.mjs'exposes
type DeepEntry = [unknown, unknown, ...unknown[]]Instances of DeepEntry will vary in length from one iteration
to the next but are essentially arrays of at least 2 elements.
core functions
Typically input types will be object | array though other built-in
types should yield intuitive results. Object types such as Date and
RegExp will be treated as if primitive, i.e. returned as whole
values and not enumerated. Objects resulting in a circular reference
will be ignored.
deepEntries
function deepEntries<T = DeepEntry>(
input: unknown,
mapFn?: (entry: DeepEntry) => T,
): T[]deepEntriesIterator
function deepEntriesIterator<T = DeepEntry>(
input: unknown,
mapFn?: (entry: DeepEntry) => T,
): IterableIterator<T>map functions
delimitEntryBy
function delimitEntryBy<T = unknown>(
delimiter: string,
): (entry: DeepEntry) => [string, T]delimitEntry
delimitEntry is an alias and is equivalent to delimitEntryBy('.')
function delimitEntry<T = unknown>(entry: DeepEntry): [string, T]rotateEntryBy
function rotateEntryBy(n: number): (entry: DeepEntry) => DeepEntryrotateEntry
rotateEntry is an alias and is equivalent to rotateEntryBy(1)
function rotateEntry(entry: DeepEntry): DeepEntrymisc. observations
In most use-cases DeepEntry keys will be of type string | number,
though instances of Map will yield Map.prototype.entries(), meaning
keys can be of any arbitrary type. If undesirable such results can be
filtered out via the mapFn.
examples
usage
import {
deepEntries,
deepEntriesIterator,
delimitEntryBy,
rotateEntryBy,
delimitEntry,
rotateEntry,
} from 'deep-entries'A shape made up of both Objects or Arrays can be described in terms of deep entries. Only enumerable own-members will be returned and iteration will honour index and / or insertion order. The following examples will consume this input:
const input = {
foo: 1,
bar: {
deep: {
key: 2,
},
},
baz: [
3,
[4, 5],
{
key: 6,
},
],
}Nested entries are returned as tuples of keys and a trailing value.
deepEntries(input)
// [
// [ 'foo', 1 ],
// [ 'bar', 'deep', 'key', 2 ],
// [ 'baz', 0, 3 ],
// [ 'baz', 1, 0, 4 ],
// [ 'baz', 1, 1, 5 ],
// [ 'baz', 2, 'key', 6 ]
// ]An optional map function is accepted as a second parameter.
deepEntries(input, delimitEntry)
// [
// [ 'foo', 1 ],
// [ 'bar.deep.key', 2 ],
// [ 'baz.0', 3 ],
// [ 'baz.1.0', 4 ],
// [ 'baz.1.1', 5 ],
// [ 'baz.2.key', 6 ]
// ]The rotate-functions are intended for convenience when destructuring an entry. Since JavaScript requires rest parameters only as the last parameter, rotating by 1 puts the value first instead.
for (let [value, ...keys] of deepEntriesIterator(input, rotateEntry)) {
console.log(keys, value)
}
// [ 'foo' ] 1
// [ 'bar', 'deep', 'key' ] 2
// [ 'baz', 0 ] 3
// [ 'baz', 1, 0 ] 4
// [ 'baz', 1, 1 ] 5
// [ 'baz', 2, 'key' ] 6filtering
The map-functions can also filter out entries by not returning them,
i.e. explicitly returning undefined instead.
const getValue = (entry) => entry[entry.length - 1]
deepEntries(input, (entry) => (getValue(entry) > 3 ? entry : undefined))
// [
// [ 'baz', 1, 0, 4 ],
// [ 'baz', 1, 1, 5 ],
// [ 'baz', 2, 'key', 6 ]
// ]The map-functions follow a pattern of returning undefined early if passed
undefined, such that they may be composed with filters and not throw errors.
const pipe =
(...fns) =>
(input) =>
fns.reduce((acc, fn) => fn(acc), input)
const atDepth = (n) => (entry) => {
if (entry.length === 2 + n) return entry
}
deepEntries(input, pipe(atDepth(1), delimitEntry))
// [
// [ 'baz.0', 3 ]
// ]