{"id":19451264,"url":"https://github.com/thekashey/proxyequal","last_synced_at":"2025-08-03T16:32:56.920Z","repository":{"id":29357871,"uuid":"121067739","full_name":"theKashey/proxyequal","owner":"theKashey","description":"There is a bit more smart way to compare things, than a shallow equal.","archived":false,"fork":false,"pushed_at":"2023-01-03T19:15:46.000Z","size":3498,"stargazers_count":72,"open_issues_count":33,"forks_count":7,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-23T08:54:29.567Z","etag":null,"topics":["compare","javascript","proxy","shallow"],"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/theKashey.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":"2018-02-11T00:36:08.000Z","updated_at":"2023-12-14T23:32:19.000Z","dependencies_parsed_at":"2023-01-14T15:00:37.307Z","dependency_job_id":null,"html_url":"https://github.com/theKashey/proxyequal","commit_stats":null,"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theKashey%2Fproxyequal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theKashey%2Fproxyequal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theKashey%2Fproxyequal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theKashey%2Fproxyequal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/theKashey","download_url":"https://codeload.github.com/theKashey/proxyequal/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250536490,"owners_count":21446743,"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":["compare","javascript","proxy","shallow"],"created_at":"2024-11-10T16:41:03.055Z","updated_at":"2025-04-24T00:23:46.663Z","avatar_url":"https://github.com/theKashey.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"proxyequal\n=====\n[![CircleCI status](https://img.shields.io/circleci/project/github/theKashey/proxyequal/master.svg?style=flat-square)](https://circleci.com/gh/theKashey/proxyequal/tree/master)\n[![Greenkeeper badge](https://badges.greenkeeper.io/theKashey/proxyequal.svg)](https://greenkeeper.io/)\n\nShallow equal is a good thing, but it compares thing you don't need.\n\nProxy equal - \"MobX\"-like solution, which will \"magically\" compare only used keys.\n\n[![NPM](https://nodei.co/npm/proxyequal.png?downloads=true\u0026stars=true)](https://nodei.co/npm/proxyequal/) \n\n## Usage\n* Wrap an object with `proxyState`\n* Run some computations using providing proxyObject.\nproxyState returns object with shape \n  * state - a double of provided state, with _tracking_ enabled\n  * affected - list of used keys in a state.\n  * seal - disables tracking\n  * unseal - enabled tracking\n  * replaceState(newState) - replaces top level state, maintaining rest of data.\n  * reset - resets tracked keys\n   \n\n* `proxy` will collect all referenced or used keys\n* `proxyEqual` will compare all used \"endpoint\" keys of 2 objects\n* `proxyShallow` will compare all used __NON__ \"endpoint\" keys of 2 objects.\n\nThe difference between proxyEqual and proxyShallow is in _expectations_.\n* proxyShallow is similar to `shallowEqual`, it compares the top level objects. Might be they are still the same.\n* proxyEqual working on variable-value level, performing (very) deep comparison of objects. \n\n## Extra API\n- `spreadGuardsEnabled(boolean=[true])` - controls spread guards, or all-keys-enumeration, which makes proxyEqual ineffective.\n- `sourceMutationsEnabled(boolean=[false])` - controls set behavior. By default proxied state is frozen.\n\n## When to use proxyequal\nWhen you have a big state, for example redux state, but some function (redux selector, or mapStateToProps)\nuses just a small subset.\n\nHere proxyequal can shine, detecting the only used branches, and comparing only the used keys.\n\n## Example\n```js\nimport {proxyState, proxyEqual, proxyShallow} from 'proxyequal';\n\n// wrap the original state\nconst trapped = proxyState(state);\n\n// use provided one in computations\nmapStateToProps(trapped.state);\n\n// first shallow compare\nproxyShallow(state, newState, trapped.affected);\n\n// next - deep compare\nproxyEqual(state, newState, trapped.affected);\n```\n### Don't forget to disable\n```js\nconst trapped = proxyState(state);\n// do something\nworkWith(trapped.state);\n\ntrapped.seal();\n\n// now tracking is disabled\n\ntrapped.unseal();\n// and enabled\n```\n\n## Speed\n\nUses `ES6 Proxy` underneath to detect used branches(as `MobX`), and `search-trie` to filter out keys for shallow or equal compare.\n\nSo - it is lighting fast.\n\n## Limitations\n\nUnfortunately, due to Proxy wrappers all `objects` will be unique each run.\n```js\n shallowEqual(proxyState(A), proxyState(A)) === false\n```\nThere is a undocumented way to solve it, used internally in [memoize-state](https://github.com/theKashey/memoize-state) library.\nOnce it will be proven to work stable - we will expose it.\n\n## Compatibility\n\nRequires [`Proxy`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) support, so the [proxy-polyfill](https://github.com/GoogleChrome/proxy-polyfill) is included in the common bundle for Internet Explorer 11. How this works may change in future, see [issue #15 \"ProxyPolyfill is unconditionally imported\"](https://github.com/theKashey/proxyequal/issues/15) for details.\n\n# Licence\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthekashey%2Fproxyequal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthekashey%2Fproxyequal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthekashey%2Fproxyequal/lists"}