{"id":22903024,"url":"https://github.com/amekusa/obj-digger","last_synced_at":"2026-04-13T17:34:31.413Z","repository":{"id":45976319,"uuid":"514815355","full_name":"amekusa/obj-digger","owner":"amekusa","description":"Safely access the properties of deeply nested objects","archived":false,"fork":false,"pushed_at":"2024-04-17T13:07:54.000Z","size":83,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-07T17:03:57.546Z","etag":null,"topics":["general-purpose","js","json","npm-package","utility"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/amekusa.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-17T10:44:35.000Z","updated_at":"2024-04-17T16:02:13.000Z","dependencies_parsed_at":"2024-04-16T21:50:39.945Z","dependency_job_id":"b75619e7-8ba6-43bd-9213-ed8aa5592eef","html_url":"https://github.com/amekusa/obj-digger","commit_stats":{"total_commits":35,"total_committers":1,"mean_commits":35.0,"dds":0.0,"last_synced_commit":"7db770ace7a1c085f2405c8f6ce27b297a8c803a"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amekusa%2Fobj-digger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amekusa%2Fobj-digger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amekusa%2Fobj-digger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amekusa%2Fobj-digger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amekusa","download_url":"https://codeload.github.com/amekusa/obj-digger/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246598189,"owners_count":20802975,"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":["general-purpose","js","json","npm-package","utility"],"created_at":"2024-12-14T02:30:54.178Z","updated_at":"2026-04-13T17:34:26.392Z","avatar_url":"https://github.com/amekusa.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OBJ-DIGGER\n[![NPM Version](https://img.shields.io/npm/v/obj-digger?label=npm%20package)](https://www.npmjs.com/package/obj-digger) [![NPM License](https://img.shields.io/npm/l/obj-digger)](https://github.com/amekusa/obj-digger/blob/master/LICENSE) [![codecov](https://codecov.io/gh/amekusa/obj-digger/branch/master/graph/badge.svg?token=LYU3ZAOR84)](https://codecov.io/gh/amekusa/obj-digger)\n\nSafely access the properties of deeply nested objects.\n\n\n## How to install\nInstall it in your project via NPM:\n\n```sh\nnpm i obj-digger\n```\n\nThen, `import` or `require` the package in your JS:\n\n```js\n// ES\nimport dig from 'obj-digger';\n\n// CJS\nconst dig = require('obj-digger');\n```\n\n\n## How to use\nobj-digger is just a single function.\n\n```js\n// Basic Usage\n\nlet obj = {\n  Alice: {\n    age: 20,\n    accounts: {\n      twitter: 'alice123'\n    }\n  },\n  Bob: {\n    age: 30,\n    accounts: {\n      github: 'bob123'\n    }\n  }\n};\n\nlet dug = dig(obj, 'Alice.accounts.twitter');\nconsole.log( dug.key );   // 'twitter'\nconsole.log( dug.value ); // 'alice123'\n\n// Using object destructuring:\nlet { key, value } = dig(obj, 'Alice.accounts.twitter');\nconsole.log( key );   // 'twitter'\nconsole.log( value ); // 'alice123'\n```\n\nThe 2nd parameter is a **query** that points at the property you want to access.\nIf the property was not found, the returned object gets to have **`err`** object.\n\n```js\nlet dug = dig(obj, 'Alice.accounts.tiktok');\nif (dug.err) console.error( dug.err.name ); // 'NoSuchKey'\n```\n\nA query can also be an array:\n\n```js\nlet dug = dig(obj, ['Alice', 'accounts', 'twitter']);\n```\n\n\n## Advanced usage: Options\nThere is the optional 3rd parameter: **options** which enables you to easily manipulate deeply nested objects.\n\n### `options.set`\nThis option assigns its value to the query destination property if it exists.\n\n```js\nlet { value } = dig(obj, 'Alice.age', { set: 21 });\nconsole.log( value );         // 21\nconsole.log( obj.Alice.age ); // 21\n```\n\n---\n\n### `options.makePath`\nIf this option is `true`, all the intermediate objects in the query get to be created in the \"digging\" process if they don't exist.\n\n```js\nconsole.log( obj.Charlie ); // undefined\ndig(obj, 'Charlie.age', { makePath: true, set: 40 });\nconsole.log( obj.Charlie ); // { age: 40 }\n```\n\nThis creates the object `obj.Charlie` which didn't exist, and assigns `40` to `obj.Charlie.age`.\n\nYour can also pass a function that returns a custom object:\n\n```js\ndig(obj, 'Charlie.age', {\n  makePath(obj, prop, depth) {\n    //   obj: the current object\n    //  prop: the property name\n    // depth: the current nesting level\n    let person new Person();\n    person.foo = 'bar';\n    return person;\n  },\n  set: 40\n});\n\nconsole.log( obj.Charlie.age ); // 40\nconsole.log( obj.Charlie.foo ); // 'bar'\nconsole.log( obj.Charlie instanceof Person ) // true\n```\n\n---\n\n### `options.mutate`\nThis option is **a callback function** that can be used to mutate the current value of the property into a different value.\n\n```js\nconsole.log( obj.Bob.age ); // 30\ndig(obj, 'Bob.age', { mutate: age =\u003e age * 2 });\nconsole.log( obj.Bob.age ); // 60\n```\n\nThe 1st parameter of `options.mutate` takes the current value of the queried property.\nAnd the return value of `options.mutate` becomes the new value.\n\n---\n\n### `options.stack`\nIf this option is `true`, the return value gets to have **`stack`** property, which is an array of all the objects that obj-digger went through.\n\n```js\nlet dug = dig(obj, `Alice.accounts.twitter`, {stack: true});\ndug.stack[0].value === obj                // true\ndug.stack[1].key   === 'Alice'            // true\ndug.stack[1].value === obj.Alice          // true\ndug.stack[2].key   === 'accounts'         // true\ndug.stack[2].value === obj.Alice.accounts // true\n```\n\nAlso, `dug.stack` is structured like a **doubly-linked-list**, so you can access the adjacent objects via `prev` / `next` properties.\n\n```js\ndug.stack[0].next === dug.stack[1] // true\ndug.stack[1].prev === dug.stack[0] // true\ndug.stack[1].next === dug.stack[2] // true\ndug.stack[2].prev === dug.stack[1] // true\n```\n\n---\n\n### `options.throw`\nIf this option is `true`, the function throws errors when they occur.\n\n```js\ntry {\n  dig(obj, 'non_existent', { throw: true });\n} catch (e) {\n  console.error(e); // 'NoSuchKey'\n}\n```\n\n---\n\n### `options.has`\nBy default, obj-digger uses `in` operator to check if the object has the queried properties.\nIf this behavior is not desirable, you can override it with `options.has`.\n\n`options.has` takes a function that returns a boolean value.\nSo, for example, you can pass `Object.hasOwn`:\n\n```js\ndig(obj, 'xxx.yyy', { has: Object.hasOwn });\n```\n\n\n## Advanced usage: Array Queries\nIf you want to dig **multiple objects in an array** like this:\n\n```js\n// Example\n\nlet obj = {\n  items: [ // array\n    {\n      type:   'book',\n      title:  'The Origin of Consciousness in the Breakdown of the Bicameral Mind',\n      author: 'Julian Jaynes'\n    }, {\n      type:     'movie',\n      title:    'Mulholland Dr.',\n      director: 'David Lynch'\n    }, {\n      type:   'album',\n      title:  'Grace',\n      artist: 'Jeff Buckley'\n    }\n  ]\n};\n```\n\nThen, put **square brackets `[]`** to the name of the array property in the query, like this:\n\n```js\nlet dug = dig(obj, 'items[].type');\n```\n\nThe return value, at this time, has a different structure.\nThe function **recusively operates** for each object in the array, and stores each result into **`found`** property of the return value.\n\n```js\nconsole.log( dug.found[0].value ); // 'book'\nconsole.log( dug.found[1].value ); // 'movie'\nconsole.log( dug.found[2].value ); // 'album'\n\n// 'results' is deprecated, but still usable as an alias of 'found'\nconsole.log( dug.results[0].value ); // 'book'\n```\n\n\n## Advanced usage: Wildcards\nYou can use **asterisk `*`** character in the query as **a wildcard** which matches for any names of properties.\n\n```js\n// Example\n\nlet obj = {\n  mammals: {\n    ape:   { legs: 2 },\n    rhino: { legs: 4 }\n  },\n  birds: {\n    ostrich: { legs: 2 },\n    parrot:  { legs: 2 }\n  },\n  reptiles: {\n    snake:     { legs: 0 },\n    crocodile: { legs: 4 }\n  }\n};\n\nlet dug = dig(obj, 'mammals.*.legs');\n```\n\nJust like Array Queries, the function recursively operates for every object that is a direct child of `obj.mammals` in this example. And you get each result stored in `dug.found` object.\n\n```js\nconsole.log( dug.found.ape.value );   // 2\nconsole.log( dug.found.rhino.value ); // 4\n```\n\n---\n\n\u003e “Let me guess… Diggin'!”\n\u003e \u0026mdash; One tunneler\n\n\n## License\n\n```\nMIT License\n\nCopyright (c) 2022 Satoshi Soma\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famekusa%2Fobj-digger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famekusa%2Fobj-digger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famekusa%2Fobj-digger/lists"}