🀠 Functional utilities using object property paths with wildcards and regexps 🌡

Overview

Codecov Build Node Twitter Medium

🀠 Functional utilities using object property paths with wildcards and regexps. 🌡

Available functional methods include:

Unlike similar libraries, object properties can be get/set using dot-delimited paths, wildcards, regexps, slices and unions. It is built on top of wild-wild-path.

Install

npm install wild-wild-utils

This package is an ES module and must be loaded using an import or import() statement, not require().

API

Methods

map(target, query, mapFunction, options?)

target: Target
query: Query
mapFunction: (value) => value
options: Options?
Return value: Target

Use a mapFunction() to modify any property matching the query.

const target = { user: { firstName: 'Alice', lastName: 'Smith' } }
map(target, 'user.*', (userProp) => userProp.toLowerCase())
// { user: { firstName: 'alice', lastName: 'smith' } }

merge(target, query, value, options?)

target: Target
query: Query
value: any
options: Options?
Return value: Target

Deeply merge an object value with each object property matching the query.

If one of these properties is not an object, it is overridden instead.

Any object in value can change the merge mode using a _merge property with value "deep" (default), "shallow", "set" or "delete".

Arrays can be merged using objects in value where the keys are the array indices. Items can be updated, merged, added, inserted, appended, prepended or deleted.

const target = {
  userOne: { names: ['Alice', 'Smith'], settings: { deleted: true } },
  userTwo: { names: ['John', 'Doe'], settings: { deleted: false } },
}

merge(target, '*', { age: 72, settings: { admin: true } })
// {
//   userOne: {
//     names: ['Alice', 'Smith'],
//     settings: { deleted: true, admin: true },
//     age: 72,
//   },
//   userTwo: {
//     names: ['John', 'Doe'],
//     settings: { deleted: false, admin: true },
//     age: 72,
//   },
// }

merge(target, '*', { age: 72, settings: { admin: true }, _merge: 'shallow' })
// {
//   userOne: {
//     names: [ 'Alice', 'Smith' ],
//     settings: { admin: true },
//     age: 72,
//   },
//   userTwo: {
//     names: [ 'John', 'Doe' ],
//     settings: { admin: true },
//     age: 72,
//   },
// }

merge(target, '*', { names: { 1: 'Red' } })
// {
//   userOne: {
//     names: ['Alice', 'Red'],
//     settings: { deleted: true, admin: true },
//     age: 72,
//   },
//   userTwo: {
//     names: ['John', 'Red'],
//     settings: { deleted: false, admin: true },
//     age: 72,
//   },
// }

push(target, query, values, options?)

target: Target
query: Query
values: any[]
options: Options?
Return value: Target

Concatenate an array of values with each array property matching the query.

If one of these properties is not an array, it is overridden instead.

const target = {
  userOne: { firstName: 'Alice', colors: ['red'] },
  userTwo: { firstName: 'John', colors: ['blue'] },
}
push(target, '*.colors', ['yellow', 'silver'])
// {
//   userOne: { firstName: 'Alice', colors: ['red', 'yellow', 'silver'] },
//   userTwo: { firstName: 'John', colors: ['blue', 'yellow', 'silver'] },
// }

unshift(target, query, values, options?)

target: Target
query: Query
values: any[]
options: Options?
Return value: Target

Like push() but concatenates at the beginning of each property instead of at the end.

const target = {
  userOne: { firstName: 'Alice', colors: ['red'] },
  userTwo: { firstName: 'John', colors: ['blue'] },
}
unshift(target, '*.colors', ['yellow', 'silver'])
// {
//   userOne: { firstName: 'Alice', colors: ['yellow', 'silver', 'red'] },
//   userTwo: { firstName: 'John', colors: ['yellow', 'silver', 'blue'] },
// }

find(target, query, testFunction, options?)

target: Target
query: Query
testFunction: (value) => boolean
options: Options?
Return value: any

Return the first property that matches the query and that returns true with the testFunction().

const target = {
  userOne: { firstName: 'Alice', colors: ['red'] },
  userTwo: { firstName: 'John', colors: ['blue'] },
}
find(target, '*.firstName', (firstName) => firstName !== 'John') // 'Alice'

pick(target, query, options?)

target: Target
query: Query
options: Options?
Return value: Target

Keep only the properties matching the query.

const target = {
  userOne: { firstName: 'Alice', lastName: 'Smith', age: 72, admin: true },
  userTwo: { firstName: 'John', lastName: 'Doe', age: 72, admin: true },
}
pick(target, '*./Name/')
// {
//   userOne: { firstName: 'Alice', lastName: 'Smith' },
//   userTwo: { firstName: 'John', lastName: 'Doe' },
// }

include(target, query, testFunction, options?)

target: Target
query: Query
testFunction: (value) => boolean
options: Options?
Return value: Target

Keep only the properties that match the query and that return true with the testFunction().

const target = {
  userOne: { firstName: 'Alice', lastName: 'Smith', age: 72, admin: true },
  userTwo: { firstName: 'John', lastName: 'Doe', age: 72, admin: true },
}
include(target, '**', (value) => typeof value === 'string')
// {
//   userOne: { firstName: 'Alice', lastName: 'Smith' },
//   userTwo: { firstName: 'John', lastName: 'Doe' },
// }

exclude(target, query, testFunction, options?)

target: Target
query: Query
testFunction: (value) => boolean
options: Options?
Return value: Target

Remove any property that matches the query and that returns true with the testFunction().

const target = {
  userOne: { firstName: 'Alice', lastName: 'Smith', age: 72, admin: true },
  userTwo: { firstName: 'John', lastName: 'Doe', age: 72, admin: true },
}
exclude(target, '**', (value) => typeof value === 'string')
// {
//   userOne: { age: 72, admin: true },
//   userTwo: { age: 72, admin: true },
// }

Target

The target value must be an object or an array.

Query

The query format is documented here. Both query strings and arrays can be used.

Options

Options are optional plain objects. They are almost the same as in wild-wild-path.

mutate

Methods: map(), merge(), push(), unshift(), exclude()
Type: boolean
Default: false

By default, the target is deeply cloned.
When true, it is directly mutated instead, which is faster but has side effects.

const target = { colors: ['red'] }
console.log(push(target, 'colors', ['blue']))
// { colors: ['red', 'blue'] }
console.log(target)
// { colors: ['red'] }
console.log(push(target, 'colors', ['blue'], { mutate: true }))
// { colors: ['red', 'blue'] }
console.log(target)
// { colors: ['red', 'blue'] }

entries

Methods: map(), find(), include(), exclude()
Type: boolean
Default: false

By default, properties' values are:

  • Passed as argument to callbacks like mapFunction() and testFunction()
  • Returned by find()

When true, objects with the following shape are used instead:

  • value any: property's value
  • path Path: property's full path
  • missing boolean: whether the property is missing from the target
const target = { job: '', firstName: 'Alice', lastName: 'Smith' }
find(target, '*', (value) => value !== '') // 'Alice'
find(
  target,
  '*',
  (entry) => entry.value !== '' && entry.path[0] !== 'firstName',
  { entries: true },
)
// { value: 'Smith', path: ['lastName'], missing: false },

missing

Methods: map(), merge(), push(), unshift()
Type: boolean
Default: false with map(), true with merge|push|unshift()

When false, properties not defined in the target are ignored.

const target = {}

push(target, 'colors', ['red']) // { colors: ['red'] }
push(target, 'colors', ['red'], { missing: false }) // {}

map(target, 'name', (value = 'defaultName') => value) // {}
map(target, 'name', ({ value = 'defaultName' }) => value, {
  missing: true,
  entries: true,
}) // { name: 'defaultName' }

sort

Methods: find(), pick(), include()
Type: boolean
Default: false

When returning sibling object properties, sort them by the lexigographic order of their names (not values).

const target = { user: { lastName: 'Doe', firstName: 'John', age: 72 } }
pick(target, 'user./Name/')
// { user: { lastName: 'Doe', firstName: 'John' } }
pick(target, 'user./Name/', { sort: true })
// { user: { firstName: 'John', lastName: 'Doe' } }

childFirst

Methods: find()
Type: boolean
Default: false

When using unions or deep wildcards, a query might match both a property and some of its children.

This option decides whether the returned properties should be sorted from children to parents, or the reverse.

const target = { user: { firstName: 'Alice', lastName: '' } }
const isDefined = (value) => value !== ''
find(target, 'user.**', isDefined) // { firstName: 'Alice', lastName: '' }
find(target, 'user.**', isDefined, { childFirst: true }) // 'Alice'

leaves

Methods: map(), merge(), push(), unshift(), find()
Type: boolean
Default: false

When using unions or deep wildcards, a query might match both a property and some of its children.

When true, only leaves are matched. In other words, a matching property is ignored if one of its children also matches.

const target = { user: { settings: { firstName: 'Alice', lastName: 'Smith' } } }
merge(target, 'user user.settings', { age: 72 })
// {
//   user: {
//     settings: { firstName: 'Alice', lastName: 'Smith', age: 72 },
//     age: 72,
//   }
// }
merge(target, 'user user.settings', { age: 72 }, { leaves: true })
// {
//   user: {
//     settings: { firstName: 'Alice', lastName: 'Smith', age: 72 },
//   }
// }

roots

Methods: map(), merge(), push(), unshift(), find()
Type: boolean
Default: false

When using unions or deep wildcards, a query might match both a property and some of its children.

When true, only roots are matched. In other words, a matching property is ignored if one of its parents also matches.

const target = { user: { settings: { firstName: 'Alice', lastName: 'Smith' } } }
merge(target, 'user user.settings', { age: 72 })
// {
//   user: {
//     settings: { firstName: 'Alice', lastName: 'Smith', age: 72 },
//     age: 72,
//   }
// }
merge(target, 'user user.settings', { age: 72 }, { roots: true })
// {
//   user: {
//     settings: { firstName: 'Alice', lastName: 'Smith' },
//     age: 72,
//   }
// }

classes

Methods: all
Type: boolean
Default: false

Unless true, wildcards and regexps ignore properties of objects that are not plain objects (like class instances, errors or functions). Those can still be matched by using their property name.

const target = { user: new User({ name: 'Alice' }) }
const isDefined = (value) => value !== ''
find(target, 'user.*', isDefined) // undefined
find(target, 'user.*', isDefined, { classes: true }) // 'Alice'

inherited

Methods: all
Type: boolean
Default: false

By default, wildcards and regexps ignore properties that are either inherited or not enumerable. Those can still be matched by using their property name.

When true, inherited properties are not ignored, but not enumerable ones still are.

Related projects

Support

For any question, don't hesitate to submit an issue on GitHub.

Everyone is welcome regardless of personal background. We enforce a Code of conduct in order to promote a positive and inclusive environment.

Contributing

This project was made with ❀️ . The simplest way to give back is by starring and sharing it online.

If the documentation is unclear or has a typo, please click on the page's Edit button (pencil icon) and suggest a correction.

If you would like to help us fix a bug or add a new feature, please check our guidelines. Pull requests are welcome!

You might also like...

Smoothly interpolate between variations of SVG paths.

svg-path-morph A simple library for morphing between variations of SVG paths. Use svg-path-morph to smoothly morph between X variations of the same SV

Jan 3, 2023

A plugin that can find the paths between two notes. Not sure who will want to use it...

Obsidian Path Finder Plugin Install BRAT Install Obsidian42-BRAT plugin. Click Add new beta plugin and fill in jerrywcy/obsidian-path-finder. Activate

Dec 31, 2022

A webpack plugin to enforce case-sensitive paths when resolving module

@umijs/case-sensitive-paths-webpack-plugin A webpack plugin to enforce case-sensitive paths when resolving module, similar to the well-known case-sens

Jul 25, 2022

A jQuery plug-in to notify you of CSS, Attribute or Property changes in an element

selectWatch.js jQuery plug-in gives an opportunity to monitor changes of DOM element's CSS styles, attributes, properties, input element or select ele

Oct 28, 2022

πŸ“ƒ Typed primitives for Typescript to work with file paths

typed-file-system-path typed-file-system-path takes inspiration from Path.swift in swift-tools-support-core and provides typed primitives to work with

Dec 15, 2022

This is a fully functional DAO, a Web3 project made using Solidity, Hardhat, JS, Next.js, Openzeppelin, CSS, HTML, using the Rinkerby network!

My First DAO! This is made for a DAO-Tutorial via learnweb3.io This is a DAO, a decentralised autonomous organisation, essentially a more collective a

Jun 20, 2022

Some of the utilities I made to facilitate me while using PhysicsWallah's website.

Some of the utilities I made to facilitate me while using PhysicsWallah's website.

PWUtils Some of the utilities I made to facilitate me while using PhysicsWallah's website. Documentation Dark Mode KeyConVP PWRpc Downloader Dark Mode

Dec 31, 2022

This is a project that allows users to add/remove books from a list. we accomplish this by using a JavaScript object. Built with JavaScript, Html and CSS.

Awesome-book This is a project that allows users to add/remove book from a list. we accomplish this by usig javascript oject. Built With HTML5 CSS3 Ja

May 27, 2022

Create a 3D interactive object using images and one simple JS call

#Interactive 3D by Pete R. Create a 3D interactive object using images and one simple JS call Created by Pete R., Founder of BucketListly Demo View de

Nov 17, 2022
Comments
  • Bump decode-uri-component from 0.2.0 to 0.2.2

    Bump decode-uri-component from 0.2.0 to 0.2.2

    Bumps decode-uri-component from 0.2.0 to 0.2.2.

    Release notes

    Sourced from decode-uri-component's releases.

    v0.2.2

    • Prevent overwriting previously decoded tokens 980e0bf

    https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.1...v0.2.2

    v0.2.1

    • Switch to GitHub workflows 76abc93
    • Fix issue where decode throws - fixes #6 746ca5d
    • Update license (#1) 486d7e2
    • Tidelift tasks a650457
    • Meta tweaks 66e1c28

    https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.1

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
Releases(4.9.0)
  • 4.9.0(Dec 12, 2022)

  • 4.8.0(Nov 11, 2022)

  • 4.7.0(Nov 7, 2022)

  • 4.6.0(Oct 26, 2022)

  • 4.5.0(Oct 26, 2022)

  • 4.4.0(Oct 26, 2022)

  • 4.3.0(Oct 13, 2022)

  • 4.2.0(Oct 8, 2022)

  • 4.1.0(Aug 16, 2022)

  • 4.0.0(May 23, 2022)

  • 3.0.0(May 9, 2022)

  • 2.1.1(Apr 6, 2022)

    • Upgrade wild-wild-path 2.3.0 -> 2.4.0 (efa4846)
    • Upgrade wild-wild-parser 2.2.0 -> 2.3.0 (5af38d0)
    • Fix tests (28bbeaf)
    • Upgrade wild-wild-path 2.2.0 -> 2.3.0 (f520a64)
    • Update README (039e334)
    • Upgrade wild-wild-path 2.1.0 -> 2.2.0 (6750752)
    • Upgrade wild-wild-parser 2.1.0 -> 2.2.0 (acaee6b)
    Source code(tar.gz)
    Source code(zip)
  • 2.1.0(Apr 5, 2022)

    • Upgrade wild-wild-path 2.0.0 -> 2.1.0 (a18563f)
    • Upgrade wild-wild-parser 2.0.0 -> 2.1.0 (eb3326f)
    • Improve types (55a1106)
    • Update README (8818dea)
    • Update README (337ebfd)
    • Update types (c09b913)
    • Update README (8cbfd40)
    • Update README (8fc828e)
    • Update README (6f474cd)
    • Add examples (b35dcc4)
    • Update README (113f496)
    • Fix examples (1695874)
    Source code(tar.gz)
    Source code(zip)
  • 2.0.0(Apr 4, 2022)

    • Fix map() (6455925)
    • Upgrade wild-wild-path 1.1.0 -> 2.0.0 (3b2716a)
    • Upgrade wild-wild-parser 1.1.0 -> 2.0.0 (65248c2)
    • Fix links (edbf15c)
    • Add emoji (7187b1a)
    • Add emoji (0ee29b6)
    • Add logo (6db4a91)
    • Update README (ccbf533)
    • Update README (748aa04)
    • Update README (7e66265)
    • Update README (bafa1a1)
    • Update README (b1ecddd)
    • Update README (18f4d58)
    • Update README (62bf09d)
    • Update README (b2bc28b)
    • Update README (6d7b390)
    • Update README (5e13d7a)
    • Update README (efe71ca)
    • Update README (0d8ca0b)
    • Update README (676f44a)
    • Fix types (fd2f394)
    • Remove examples (a45b045)
    • Improve types (aeb2c7e)
    • Fix README (5fac6a0)
    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Apr 2, 2022)

    • Add more types (08e4e3a)
    • Add more types (6ea3cb3)
    • Add more types (ba2cd01)
    • Add more type tests (ec4fca0)
    • Add more types (0ab346a)
    • Add more types (4d718b1)
    • Add more types (fe71be2)
    • Add more types (bf899d8)
    • Add more types (99f6b08)
    • Fix name (ffd549d)
    • Upgrade wild-wild-path 1.0.2 -> 1.1.0 (d9ad97a)
    • Upgrade wild-wild-parser 1.0.1 -> 1.1.0 (b77ee14)
    • Upgrade wild-wild-path 1.0.1 -> 1.0.2 (c2b0a41)
    • Upgrade wild-wild-parser 1.0.0 -> 1.0.1 (500466e)
    • Move files (6565b91)
    • Split file (93a9078)
    • Renaming (c8533b1)
    • Fix code duplication (fd81d72)
    • Fix code duplication (57b761e)
    • Revert "Fix code duplication" (885d162)
    • Fix code duplication (98edc67)
    • Fix code duplication (6a874f3)
    • Refactoring (56e8cbb)
    • Refactoring (9b62774)
    • Fix code duplication (68a0333)
    • Validate merge() argument (7668360)
    • Validate push|unshift() arguments (8dfd20c)
    • Validate include|exclude arguments (5c3d733)
    • Validate find() argument (0b079b4)
    • Validate map function (d39d8bc)
    • Improve performance (0abcb15)
    • Add more tests (a1af24c)
    • Add more tests (706ad09)
    • Add more tests (6d368a9)
    • Add more tests (d4b2470)
    • Add more tests (36f47eb)
    • Make missing default to true for push|unshift|merge (9505bbe)
    • Rename files (fe32f7b)
    • Improve merge() (404408f)
    • Upgrade wild-wild-path 1.0.0 -> 1.0.1 (a4329b1)
    • Refactoring (33d2fe2)
    • Refactoring (df99376)
    • Add more tests (ebdcb03)
    • Add more tests (28948ff)
    • Add more tests (39bcbad)
    • Add more tests (68ac7a6)
    • Add more tests (9510229)
    • Add more tests (f640901)
    • Update tests (16213c5)
    • Add more tests (b9ca3d8)
    • Add more tests (0a9691c)
    • Add more tests (0f51487)
    • Add more tests (6aef60f)
    • Add more tests (7ac82ef)
    • Add more tests (bc800ea)
    • Add more tests (7ee50e1)
    • Initial commit (bf64216)
    Source code(tar.gz)
    Source code(zip)
Owner
ehmicky
Node.js back-end developer
ehmicky
Given an object and a property, replaces a property descriptor (or deletes it), and returns a thunk to restore it.

Given an object and a property, replaces a property descriptor (or deletes it), and returns a thunk to restore it.

Jordan Harband 7 Apr 20, 2022
A plugin that provides utilities for animation property.

tailwindcss-animation-property A plugin that provides utilities for animation property. Not only does the plugin provide the usual animation propertie

ZXT 12 Sep 23, 2022
An algorithm for fast 2D pattern-matching with wildcards.

pattern-match-2d.js An algorithm for fast 2D pattern-matching with wildcards, with a demo app inspired by MarkovJunior (by Maxim Gumin). The algorithm

null 16 Nov 5, 2022
Types generator will help user to create TS types from JSON. Just paste your single object JSON the Types generator will auto-generate the interfaces for you. You can give a name for the root object

Types generator Types generator is a utility tool that will help User to create TS Interfaces from JSON. All you have to do is paste your single objec

Vineeth.TR 16 Dec 6, 2022
To keep online organized data and be able to add listeners in certain paths by socket.io and http clients

The purpose of this project is to create a state machine server to keep organized data and be able to add listeners with socket.io in specific paths and in addition to providing a possible form of messages between socket.io clients.

Manga 3 Mar 19, 2022
Calculate the price range for property advertised on Domain and Real Estate.

Property Seeker Calculate the price range for property advertised on Domain and Real Estate. Install Chrome Firefox Edge Privacy All searches are perf

null 42 Dec 27, 2022
Convert your SVG file directly to Flutter paths and prevent all the messing with bezier curves.

svg-to-flutter-path-converter Convert your SVG file directly to Flutter paths and prevent all the messing with bezier curves. Flutter Clutter The tool

null 30 Jan 2, 2023
Explore Alveus Sanctuary with an interactive map and find out more about the different buildings on the property.

Alveus Sanctuary Interactive Map Explore Alveus Sanctuary with an interactive map and find out more about the different buildings on the property. htt

Matt Cowley 3 Aug 16, 2022
Adds a handy $parent magic property to your Alpine components.

✨ Help support the maintenance of this package by sponsoring me. Alpine $parent Access parent components using a handy $parent magic variable. This pa

Ryan Chandler 10 Aug 29, 2022
Generate fluid, custom property based design systems on the fly β€” entirely based on Utopia

Fluid Design Systems With Netlify On-demand Builders A proof of concept demonstrating how Netlify on-demand builders can help generate fluid, custom p

George Francis 53 Jan 5, 2023