{"id":19050478,"url":"https://github.com/blakek/deep","last_synced_at":"2025-04-24T01:23:36.897Z","repository":{"id":38271177,"uuid":"268832705","full_name":"blakek/deep","owner":"blakek","description":"🐡 Get, set, remove, and test for deeply nested properties","archived":false,"fork":false,"pushed_at":"2023-01-06T07:42:37.000Z","size":658,"stargazers_count":2,"open_issues_count":7,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-18T09:34:21.478Z","etag":null,"topics":["deep","get","getters","javascript","nested-properties","properties","setter","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blakek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-06-02T15:04:49.000Z","updated_at":"2022-06-07T02:51:59.000Z","dependencies_parsed_at":"2023-02-05T15:46:42.626Z","dependency_job_id":null,"html_url":"https://github.com/blakek/deep","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blakek%2Fdeep","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blakek%2Fdeep/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blakek%2Fdeep/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blakek%2Fdeep/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blakek","download_url":"https://codeload.github.com/blakek/deep/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250541955,"owners_count":21447606,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deep","get","getters","javascript","nested-properties","properties","setter","typescript"],"created_at":"2024-11-08T23:15:02.839Z","updated_at":"2025-04-24T01:23:36.871Z","avatar_url":"https://github.com/blakek.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# deep\n\n\u003e 🐡 Get, set, remove, and test for deeply nested properties\n\nHelps you safely work with nested properties.\n\n## Install\n\nUsing [Yarn]:\n\n```bash\n$ yarn add @blakek/deep\n```\n\n…or using [npm]:\n\n```bash\n$ npm i --save @blakek/deep\n```\n\n## Usage\n\n```js\nimport {\n  clone,\n  createGetter,\n  get,\n  has,\n  omit,\n  pluck,\n  remove,\n  set\n  // also available:\n  // - createHas\n  // - createOmit\n  // - createPluck\n  // - createRemove\n  // - createSetter\n  // - isObject\n  // - traverseObject\n} from '@blakek/deep';\n\nconst user = {\n  id: 'abf87de',\n  roles: ['alert:create', 'alert:read'],\n  sites: {\n    github: {\n      username: 'blakek'\n    }\n  }\n};\n\n// Deeply clone most values\nconst userCopy = clone(user);\nuser === userCopy; //» false\nuser.id === userCopy.id; //» true\nuser.roles === userCopy.roles; //» false\nuser.roles[0] === userCopy.roles[0]; //» true\n\n// Get a property value\nget('sites.github.username', user); //» 'blakek'\n\n// Get a property value with a fallback other than `undefined`\nget('sites.facebook.username', user, 'no-account'); //» 'no-account'\n\n// Create a function to get a property value later\nconst getUsername = createGetter('sites.github.username');\ngetUsername(user); //» 'blakek'\n\n// Test for a property value\nhas('sites.github', user); //» true\n\n// Clone an object and omit properties\nomit(['roles', 'sites'], user); //» { id: 'abf87de' }\n\n// Pluck a subset of properties\npluck(['id', 'roles'], user);\n//» { id: 'abf87de', roles: [ 'alert:create', 'alert:read' ] }\n\n// Remove a property value, modifying the current object\nremove('a', { a: 42, b: 123 }); //» { b: 123 }\n\n// Set a property value, modifying the current object\nset(123, 'a.b.c', { a: 42 }); //» { a: { b: { c: 123 } } }\n```\n\n## API\n\nFor all these:\n\n- `path` can be either a dot-notation string or array of path parts\n\n### `clone`\n\nReturns a deep clone / deep copy of most values: primitive values, objects, arrays, Map, Set, Date, etc.\n\n```ts\nfunction clone\u003cT extends unknown\u003e(value: T): T;\n```\n\n```js\nconst object = { value: 'yep' };\nconst cloned = clone(object);\n\ncloned === object; //» false\ncloned.value === object.value; //» true\n```\n\n### `get` / `createGetter`\n\nGets the value for a given path with an optional fallback value.\n\n```ts\nfunction get(path: Path, object: object, fallbackValue?: any): unknown;\n\nfunction createGetter(\n  path: Path,\n  fallbackValue?: any\n): (object: object) =\u003e unknown;\n```\n\n```js\nconst user = {\n  id: 'abf87de',\n  roles: ['alert:create', 'alert:read'],\n  sites: {\n    github: {\n      username: 'blakek'\n    }\n  }\n};\n\nget('id', user); //» 'abf87de'\nget('roles.0', user); //» 'alert:create'\nget('roles[0]', user); //» 'alert:create'\nget(['roles', 1], user); //» 'alert:read'\nget('sites.github.username', user); //» 'blakek'\nget('sites.github.avatar.src', user, 'default.png'); //» 'default.png'\n\nconst getID = get('id');\ngetID(user); //» 'abf87de'\n\nconst getRoles = createGetter('roles');\ngetRoles(user); //» ['alert:create', 'alert:read']\n```\n\n### `has` / `createHas`\n\nReturns `true` if a value was found at the given path or `false` if nothing was\nfound.\n\n```ts\nfunction has(path: Path, object: any): boolean;\n\nfunction createHas(path: Path): (object: any) =\u003e boolean;\n```\n\n```js\nconst product = {\n  id: 'abf87de',\n  name: 'Logo T-Shirt',\n  attributes: {\n    isCool: undefined,\n    materials: ['cotton']\n  }\n};\n\nhas('attributes.materials', product); //» true\nhas(['avability', 'sizes'], product); //» false\nhas('attributes.isCool', product); //» true; property exists but is undefined\n\nconst hasMaterials = createHas('attributes.materials');\nhasMaterials(product); //» true\n\n// NOTE: `get()` should be used if you want to ensure a value is not `undefined`\nget('attributes.isCool', product, false); //» false\n```\n\n### `omit` / `createOmit`\n\nReturns a clone of an object with a list of properties removed.\n\nNote: `omit()` returns a clone with properties removed. If you'd rather modify\nthe existing object for performance, consider using `remove()`.\n\n```ts\nfunction omit(properties: Path[], object: any): any;\n\nfunction createOmit(properties: Path[]): (object: any) =\u003e any;\n```\n\n```js\nconst user = {\n  username: 'blakek',\n  roles: ['alert:create', 'alert:read'],\n  sites: {\n    github: {\n      username: 'blakek'\n    }\n  }\n};\n\nomit(['roles', 'sites'], user); //» { username: 'blakek' }\nomit(['username', 'roles', 'sites.doesnt.exist'], user);\n//» { sites: { github: { username: 'blakek' } } }\n\nconst omitExtra = createOmit(['roles, sites']);\nomitExtra(user); //» { username: 'blakek' }\n```\n\n### `pluck` / `createPluck`\n\nGets a subset of properties from an object.\n\n```ts\nfunction pluck(properties: Path[], object: any): any;\n```\n\n```js\nconst user = {\n  username: 'blakek',\n  roles: ['alert:create', 'alert:read'],\n  sites: {\n    github: {\n      username: 'blakek'\n    }\n  }\n};\n\npluck(['username'], user); //» { username: 'blakek' }\npluck(['username', 'roles'], user);\n//» { username: 'blakek', roles: [ 'alert:create', 'alert:read' ] }\n\nconst permissionInfo = pluck(['roles', 'username']);\npermissionInfo(user); //» { roles: [ 'alert:create', 'alert:read' ], username: 'blakek' }\n```\n\n### `remove` / `createRemove`\n\nRemoves a value at a path and returns the object.\n\nNote: `remove()` modifies the passed-in object rather than creating a copy. If\nyou'd rather return a new object:\n\n- use `omit()`; `omit()` returns a clone with a list of properties removed\n- use `clone()` before `remove()`\n- consider another solution ([unchanged] is really good)\n\n```ts\nfunction remove(path: Path, object: any): any;\n\nfunction createRemove(path: Path): (object: any) =\u003e any;\n```\n\n```js\nconst user = {\n  username: 'blakek',\n  password: 'wouldntyouliketoknow'\n};\n\nremove('password', user); //» { username: 'blakek' }\nremove('property.does.not.exist', user);\n//» { username: 'blakek' } (same object from previous line)\n\nconst removePassword = createRemove('password');\nremovePassword({ username: 'bob', password: 'laskjfl' }); //» { username: 'bob' }\n```\n\n### `set` / `createSetter`\n\nSets a value at a path and returns the object.\n\nNote: `set()` modifies the passed-in object rather than creating a copy. If\nyou'd rather return a new object:\n\n- use `clone()` before `set()`\n- consider another solution ([unchanged] is really good)\n\n```ts\nfunction set(value: any, path: Path, object: any): any;\n\nfunction createSetter(path: Path, object: any): (value: any) =\u003e any;\n```\n\n```js\nconst user = {\n  profile: {\n    bgColor: '#639'\n  }\n};\n\nset('tomato', 'profile.bgColor', user); //» { profile: { bgColor: 'tomato' } }\n\nset('/images/user.png', 'profile.bgImage', user);\n//» { profile: { bgColor: 'tomato', bgImage: '/images/user.png' } }\n\nconst logout = set(null, 'profile');\nlogout(user); //» { profile: null }\n\nconst setUsername = createSetter('username', user);\nsetUsername('blakek'); //»  { profile: { bgColor: 'tomato', bgImage: '/images/user.png' }, username: 'blakek' }\n```\n\n## Contributing\n\n[Node.js] and [Yarn] are required to work with this project.\n\nTo install all dependencies, run:\n\n```bash\nyarn\n```\n\n### Useful Commands\n\n|                     |                                                 |\n| ------------------- | ----------------------------------------------- |\n| `yarn build`        | Builds the project to `./dist`                  |\n| `yarn format`       | Format the source following the Prettier styles |\n| `yarn test`         | Run project tests                               |\n| `yarn test --watch` | Run project tests, watching for file changes    |\n\n## License\n\nMIT\n\n[node.js]: https://nodejs.org/\n[npm]: https://npmjs.com/\n[unchanged]: https://github.com/planttheidea/unchanged\n[yarn]: https://yarnpkg.com/en/docs/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblakek%2Fdeep","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblakek%2Fdeep","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblakek%2Fdeep/lists"}