{"id":19427155,"url":"https://github.com/apphp/js-object-resolver","last_synced_at":"2026-05-08T02:20:03.708Z","repository":{"id":57098327,"uuid":"436296305","full_name":"apphp/js-object-resolver","owner":"apphp","description":"Provides general functionality for for dealing with nested properties in JavaScript objects with unlimited depth.","archived":false,"fork":false,"pushed_at":"2024-04-06T15:14:35.000Z","size":51,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-23T05:46:29.786Z","etag":null,"topics":["javascript","nodejs","npm","object"],"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/apphp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2021-12-08T15:25:42.000Z","updated_at":"2022-03-25T10:45:06.000Z","dependencies_parsed_at":"2024-11-10T14:10:55.176Z","dependency_job_id":"2e6d80a5-a3fd-48d9-a455-ae1df4b25040","html_url":"https://github.com/apphp/js-object-resolver","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apphp%2Fjs-object-resolver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apphp%2Fjs-object-resolver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apphp%2Fjs-object-resolver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apphp%2Fjs-object-resolver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/apphp","download_url":"https://codeload.github.com/apphp/js-object-resolver/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240605853,"owners_count":19827987,"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":["javascript","nodejs","npm","object"],"created_at":"2024-11-10T14:10:37.287Z","updated_at":"2026-05-08T02:20:03.650Z","avatar_url":"https://github.com/apphp.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Object Resolver \n### Provides general functionality for dealing with nested properties in JavaScript objects\n\u0026nbsp;\n\nAvailable methods:\n- isEqual\n- filterObject\n- removeUndefinedProperties\n- hasNestedProperty\n- getNestedProperty\n- fetchLastNestedProperty\n- setNestedProperty\n- deleteNestedProperty\n- setNestedPropertyImmutable\n- deleteNestedPropertyImmutable\n- cloneObject\n- cloneStructure\n\n\u0026nbsp;\n\n## Install\n\nInstall / Uninstall with [npm](https://www.npmjs.com/):\n\n```sh\n$ npm install @apphp/object-resolver\n```\n\n## Uninstall\n\n```sh\n$ npm uninstall @apphp/object-resolver\n```\n\n## Run Tests\n```sh\n$ npm run test\n```\nAfter tests running coverage report can be found in coverage directory\n\n\n## Run ESLint\nTo perform ESlint check run following command: \n```sh\n$ npm run eslint\n```\nTo fix issues, found by ESLint run:\n```sh\n$ npm run eslint-fix\n```\n\n## Usage\n\nRequire package:\n```js\n// by using require\nconst resolver = require('@apphp/object-resolver');\n// by using import \n//import resolver from \"@apphp/object-resolver\";\n// by using object destructor\n//const {cloneObject} = require('dist/object-resolver');\n```\n\n### isEqual(value1, value2)\nCompares two values for deep equality.\n\n`isEqual()` performs a recursive deep comparison and supports primitives, arrays, plain objects, and common built-in JavaScript types.\n\nBehavior highlights:\n- Object key order does not matter (`{ a: 1, b: 2 }` equals `{ b: 2, a: 1 }`)\n- Nested objects/arrays are compared deeply\n- Supports `Date`, `RegExp`, `Map`, `Set`, `ArrayBuffer`, and typed arrays\n- Handles circular references safely\n- Uses strict prototype checks (values with different prototypes are not equal)\n\n```js\nresolver.isEqual({ a: 1, b: { c: 2 } }, { b: { c: 2 }, a: 1 }); // true\nresolver.isEqual([1, 2, 3], [1, 2, 4]); // false\n\nresolver.isEqual(new Date('2023-01-01'), new Date('2023-01-01')); // true\nresolver.isEqual(/abc/gi, /abc/g); // false\n\nresolver.isEqual(new Set([1, { a: 2 }]), new Set([{ a: 2 }, 1])); // true\n\nconst x = { a: 1 };\nconst y = { a: 1 };\nx.self = x;\ny.self = y;\nresolver.isEqual(x, y); // true\n```\n\n### filterObject(obj, predicate)\nFilters the properties of an object based on a predicate function\n```js\nconst filtered = resolver.filterObject({ a: 1, b: 2, c: 3, d: 4 }, (value, key) =\u003e value % 2 === 0);\n```\n\n### removeUndefinedProperties(obj)\nRemoves properties with `undefined` values from an object\n```js\nconst cleaned = resolver.removeUndefinedProperties({ a: 1, b: undefined, c: { d: 4, e: undefined } });\n```\n\n### hasNestedProperty(obj, propertyPath)\nChecks whether a nested property exists and returns a boolean result\n```js\nconst exists = resolver.hasNestedProperty(obj, 'innerObject.deepObject.value'); // true/false\n```\n\n### getNestedProperty(objParam, propertyPath, defaultValue)\nGet nested property exists and if not empty perform some action\n```js\nconst prop = resolver.getNestedProperty(obj, 'innerObject.deepObject.value')\nif (prop) {\n  // ...\n}\n```\n\n### fetchLastNestedProperty(obj, path)\nFetch last chained nested property\n```js\nconst prop = resolver.fetchLastNestedProperty(obj, 'prop');\n```\n\n### setNestedProperty(obj, path, value)\nSet a deeply nested property in an object (mutates the original object)\n\nBehavior notes:\n- Mutates `obj` in place; returns `undefined`\n- Creates missing intermediate objects on the path when needed\n- `path` may be a dot-separated string or an array of keys\n- Throws an error for invalid path type (not string/array)\n- Throws an error for protected keys: `__proto__`, `constructor`, `prototype`\n- Supports numeric object keys; limited bracket-style handling is supported by current implementation\n```js\nconst prop = resolver.setNestedProperty(obj, 'user.profile.name', 'John Doe');\n```\n\n### deleteNestedProperty(obj, path)\nDelete a deeply nested property in an object (mutates the original object)\n\nBehavior notes:\n- Mutates `obj` in place; returns `undefined`\n- If `obj` is `null` or not an object, it does nothing\n- If any intermediate path segment is missing, it exits early (no throw)\n- For array targets, it removes items via `splice(index, 1)`\n- For object targets, it uses `delete` on the last key\n```js\nconst prop = resolver.deleteNestedProperty(obj, 'user.profile.name', 'John Doe');\n```\n\n### setNestedPropertyImmutable(obj, path, value)\nSet a deeply nested property without mutating the original object\n```js\nconst updatedObj = resolver.setNestedPropertyImmutable(obj, 'user.profile.name', 'John Doe');\n```\n\n### deleteNestedPropertyImmutable(obj, path)\nDelete a deeply nested property without mutating the original object\n```js\nconst updatedObj = resolver.deleteNestedPropertyImmutable(obj, 'user.profile.name');\n```\n\n### cloneObject(obj)\nDeep cloning of object\n```js\nconst objCopy = resolver.cloneObject(obj);\n```\n\n### cloneStructure(obj, options)\nDeep cloning of structure (node \u003e v17)\n```js\nconst structureCopy = resolver.cloneStructure(obj, options);\n```\n\n## Mutation and edge cases\n\n### Mutates input\n- `setNestedProperty`\n- `deleteNestedProperty`\n\n### Returns new value (non-mutating)\n- `filterObject`\n- `removeUndefinedProperties`\n- `setNestedPropertyImmutable`\n- `deleteNestedPropertyImmutable`\n- `cloneObject`\n- `cloneStructure`\n\n### Read-only helpers (no mutation)\n- `isEqual`\n- `hasNestedProperty`\n- `getNestedProperty`\n- `fetchLastNestedProperty`\n\n### Edge-case quick reference\n- `hasNestedProperty(obj, path)` returns `false` when `obj` or `path` is missing/falsy\n- `getNestedProperty(obj, path, defaultValue)` returns `defaultValue` only when resolved value is `undefined`\n- `setNestedProperty` throws for invalid path type and protected keys\n- `deleteNestedProperty` safely no-ops for invalid root/non-existing intermediate path\n\n## Examples\n\n```js\nconst obj1 = { a: 1, b: { c: 2 } };\nconst obj2 = { a: 1, b: { c: 2 } };\nconst compareResult = resolver.isEqual(obj1, obj2);\n```\n\n```js\nconst original = { a: 1, b: 2, c: 3, d: 4 };\nconst filtered = resolver.filterObject(original, (value, key) =\u003e value % 2 === 0);\nconsole.log(filtered); \n```\n\n```js\nconst original = { a: 1, b: undefined, c: { d: 4, e: undefined } };\nconst cleaned = resolver.removeUndefinedProperties(original);\n```\n\n```js\nconst obj = {\n  innerObject: {\n    deepObject: {\n      value: 'Here I am'\n    }\n  }\n};\n\nconsole.log(resolver.hasNestedProperty(obj, 'innerObject.deepObject.value'));                         // true\nconsole.log(resolver.hasNestedProperty(obj, 'innerObject.deepObject.wrongValue'));                    // false\nconsole.log(resolver.getNestedProperty(obj, 'innerObject.deepObject.value'));                         // 'Here I am'\nconsole.log(resolver.getNestedProperty(obj, 'innerObject.deepObject.wrongValue'));                    // undefined\nconsole.log(resolver.getNestedProperty(obj, 'innerObject.deepObject.wrongValue.oneMore', 'Oh-h-h'));  // 'Oh-h-h'\n```\n\n```js\nconst obj = {\n  innerObject: {\n    deepObject: [\n      { name: 'John' },\n      { name: 'Nick' },\n      { name: 'Ron' }\n    ]\n  }\n};\n\nconsole.log(resolver.hasNestedProperty(obj, 'innerObject.deepObject.0.name'));              // true\nconsole.log(resolver.getNestedProperty(obj, 'innerObject.deepObject.1.name'));              // 'Nick'\n```\n\n```js\nconst obj = { role: { role: { role: 'student' } }};\nconst role = resolver.fetchLastNestedProperty(obj, 'role');\n```\n\n```js\nconst obj = {'a':{'b':2}, 'c':3};\nconst objCopy = resolver.cloneObject(obj);\n```\n\n## License\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapphp%2Fjs-object-resolver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapphp%2Fjs-object-resolver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapphp%2Fjs-object-resolver/lists"}