{"_id":"stable-hash-x","_rev":"3-2e9acdc06315cb523179a3fbaa368e25","name":"stable-hash-x","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"stable-hash-x","version":"0.1.0","author":{"name":"Shu Ding"},"license":"MIT","_id":"stable-hash-x@0.1.0","maintainers":[{"name":"jounqin","email":"admin@1stg.me"}],"homepage":"https://github.com/un-ts/stable-hash-x#readme","bugs":{"url":"https://github.com/un-ts/stable-hash-x/issues"},"dist":{"shasum":"836e37c9976ad0f319398709689866216bb08f7d","tarball":"https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.1.0.tgz","fileCount":7,"integrity":"sha512-38p0Tzqqvz0JRp5qAmHN/8bO/dJu+waM9nlxFHFRCgs2Xt8TAJOpidgY36XTjxkVEjZRPW8Fnc9qPEzjwl9x/A==","signatures":[{"sig":"MEYCIQClTLkt0JDAR2uMUAeOZcJww3Tw6vzztprBW1gTxTiL6wIhAPs12pmOil0ZFA+v/htHohfHzwOOuBISlLvVDvxW2CHA","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/stable-hash-x@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":14639},"main":"./lib/index.cjs","type":"module","types":"./lib/index.d.cts","module":"./lib/index.js","exports":{".":{"import":{"types":"./lib/index.d.ts","default":"./lib/index.js"},"require":{"types":"./lib/index.d.cts","default":"./lib/index.cjs"}},"./package.json":"./package.json"},"gitHead":"548068267ef0acaf6435f24231ff2b572b1c4a26","_npmUser":{"name":"jounqin","email":"admin@1stg.me"},"repository":{"url":"git+https://github.com/un-ts/stable-hash-x.git","type":"git"},"_npmVersion":"10.9.2","description":"Stable JS value hash.","directories":{},"_nodeVersion":"22.16.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/stable-hash-x_0.1.0_1749051755902_0.4928195907128865","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"stable-hash-x","version":"0.1.1","author":{"name":"Shu Ding"},"license":"MIT","_id":"stable-hash-x@0.1.1","maintainers":[{"name":"jounqin","email":"admin@1stg.me"}],"homepage":"https://github.com/un-ts/stable-hash-x#readme","bugs":{"url":"https://github.com/un-ts/stable-hash-x/issues"},"dist":{"shasum":"1dc602f65183ef049a44a9be4fce249a4c71fc84","tarball":"https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.1.1.tgz","fileCount":7,"integrity":"sha512-l0x1D6vhnsNUGPFVDx45eif0y6eedVC8nm5uACTrVFJFtl2mLRW17aWtVyxFCpn5t94VUPkjU8vSLwIuwwqtJQ==","signatures":[{"sig":"MEQCIH684pgHdVeJawubLuYEacSVjoNA6ukHwqZzv/vw47IdAiArxeurcGPHU906OgVviYyyhtwb5ZpQPKxmfRYVmT05Cw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/stable-hash-x@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":14768},"main":"./lib/index.cjs","type":"module","types":"./lib/index.d.cts","module":"./lib/index.js","engines":{"node":">=12.0.0"},"exports":{".":{"import":{"types":"./lib/index.d.ts","default":"./lib/index.js"},"require":{"types":"./lib/index.d.cts","default":"./lib/index.cjs"}},"./package.json":"./package.json"},"gitHead":"5f73a1168b4c93eb8d06f6e084fa28b29e77c44e","_npmUser":{"name":"jounqin","email":"admin@1stg.me"},"repository":{"url":"git+https://github.com/un-ts/stable-hash-x.git","type":"git"},"_npmVersion":"10.9.2","description":"Stable JS value hash.","directories":{},"_nodeVersion":"22.16.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/stable-hash-x_0.1.1_1749053535442_0.46158443723091147","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"stable-hash-x","version":"0.2.0","type":"module","description":"Stable JS value hash.","repository":{"type":"git","url":"git+https://github.com/un-ts/stable-hash-x.git"},"homepage":"https://github.com/un-ts/stable-hash-x#readme","author":{"name":"Shu Ding"},"maintainers":[{"name":"jounqin","email":"admin@1stg.me"}],"license":"MIT","engines":{"node":">=12.0.0"},"main":"./lib/index.cjs","types":"./lib/index.d.cts","module":"./lib/index.js","exports":{".":{"import":{"types":"./lib/index.d.ts","default":"./lib/index.js"},"require":{"types":"./lib/index.d.cts","default":"./lib/index.cjs"}},"./package.json":"./package.json"},"_id":"stable-hash-x@0.2.0","gitHead":"02350269a241ca25d38efd1181b04c002be464e5","bugs":{"url":"https://github.com/un-ts/stable-hash-x/issues"},"_nodeVersion":"22.16.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==","shasum":"dfd76bfa5d839a7470125c6a6b3c8b22061793e9","tarball":"https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz","fileCount":7,"unpackedSize":16915,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/stable-hash-x@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCvGqBF5xXjIihiYYFZK33r61Rz/b0qUYu6hfktes0d5gIgMBUViOWiP7Wec/VBeHWkZ4zDhwrfSPxgCZjAfXFyrkQ="}]},"_npmUser":{"name":"jounqin","email":"admin@1stg.me","actor":{"name":"jounqin","email":"admin@1stg.me","type":"user"}},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/stable-hash-x_0.2.0_1750863800773_0.8986028397639425"},"_hasShrinkwrap":false}},"time":{"created":"2025-06-04T15:42:35.787Z","modified":"2025-06-25T15:03:21.313Z","0.1.0":"2025-06-04T15:42:36.102Z","0.1.1":"2025-06-04T16:12:15.634Z","0.2.0":"2025-06-25T15:03:20.951Z"},"bugs":{"url":"https://github.com/un-ts/stable-hash-x/issues"},"author":{"name":"Shu Ding"},"license":"MIT","homepage":"https://github.com/un-ts/stable-hash-x#readme","repository":{"type":"git","url":"git+https://github.com/un-ts/stable-hash-x.git"},"description":"Stable JS value hash.","maintainers":[{"name":"jounqin","email":"admin@1stg.me"}],"readme":"# stable-hash-x\n\n[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/un-ts/stable-hash-x/ci.yml?branch=main)](https://github.com/un-ts/stable-hash-x/actions/workflows/ci.yml?query=branch%3Amain)\n[![Codecov](https://img.shields.io/codecov/c/github/un-ts/stable-hash-x.svg)](https://codecov.io/gh/un-ts/stable-hash-x)\n[![type-coverage](https://img.shields.io/badge/dynamic/json.svg?label=type-coverage&prefix=%E2%89%A5&suffix=%&query=$.typeCoverage.atLeast&uri=https%3A%2F%2Fraw.githubusercontent.com%2Fun-ts%2Fstable-hash-x%2Fmain%2Fpackage.json)](https://github.com/plantain-00/type-coverage)\n[![CodeRabbit Pull Request Reviews](https://img.shields.io/coderabbit/prs/github/un-ts/stable-hash-x)](https://coderabbit.ai)\n[![npm](https://img.shields.io/npm/v/stable-hash-x.svg)](https://www.npmjs.com/package/stable-hash-x)\n[![GitHub Release](https://img.shields.io/github/release/un-ts/stable-hash-x)](https://github.com/un-ts/stable-hash-x/releases)\n\n[![Conventional Commits](https://img.shields.io/badge/conventional%20commits-1.0.0-yellow.svg)](https://conventionalcommits.org)\n[![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovatebot.com)\n[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)\n[![Code Style: Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)\n[![changesets](https://img.shields.io/badge/maintained%20with-changesets-176de3.svg)](https://github.com/changesets/changesets)\n\nA tiny and fast (600B <sup>[unpkg](https://unpkg.com/stable-hash-x@latest/lib/index.js)</sup>) lib for \"stably hashing\" a JavaScript value, works with cross-realm objects. Originally created for [SWR](https://github.com/vercel/swr) by [Shu Ding][] at [`stable-hash`](https://github.com/shuding/stable-hash), we forked it because the original one is a bit out of maintenance for a long time.\n\nIt's similar to `JSON.stringify(value)`, but:\n\n1. Supports any JavaScript value (`BigInt`, `NaN`, `Symbol`, `function`, `class`, ...)\n2. Sorts object keys (stable)\n3. Supports circular objects\n\n## TOC <!-- omit in toc -->\n\n- [Use](#use)\n- [Examples](#examples)\n  - [Primitive Value](#primitive-value)\n  - [Regex](#regex)\n  - [Date](#date)\n  - [Array](#array)\n  - [Object](#object)\n  - [`Function`, `Class`, `Set`, `Map`, `Buffer`...](#function-class-set-map-buffer)\n  - [Cross-realm](#cross-realm)\n- [Benchmark](#benchmark)\n- [Notes](#notes)\n- [Sponsors and Backers](#sponsors-and-backers)\n  - [Sponsors](#sponsors)\n  - [Backers](#backers)\n- [Changelog](#changelog)\n- [License](#license)\n\n## Use\n\n```bash\nyarn add stable-hash-x\n```\n\n```js\nimport { hash } from 'stable-hash-x'\n\nhash(anyJavaScriptValueHere) // returns a string\n\nhash(anyJavaScriptValueHere, true) // if you're running in cross-realm environment, it's disabled by default for performance\n```\n\n## Examples\n\n### Primitive Value\n\n```js\nhash(1)\nhash('foo')\nhash(true)\nhash(undefined)\nhash(null)\nhash(NaN)\n```\n\nBigInt:\n\n```js\nhash(1) === hash(1n)\nhash(1) !== hash(2n)\n```\n\nSymbol:\n\n```js\nhash(Symbol.for('foo')) === hash(Symbol.for('foo'))\nhash(Symbol.for('foo')) === hash(Symbol('foo'))\nhash(Symbol('foo')) === hash(Symbol('foo'))\nhash(Symbol('foo')) !== hash(Symbol('bar'))\n```\n\n_Since `Symbol`s cannot be serialized, `stable-hash-x` simply uses its description as the hash._\n\n### Regex\n\n```js\nhash(/foo/) === hash(/foo/)\nhash(/foo/) !== hash(/bar/)\n```\n\n### Date\n\n```js\nhash(new Date(1)) === hash(new Date(1))\n```\n\n### Array\n\n```js\nhash([1, '2', [new Date(3)]]) === hash([1, '2', [new Date(3)]])\nhash([1, 2]) !== hash([2, 1])\n```\n\nCircular:\n\n```js\nconst foo = []\nfoo.push(foo)\nhash(foo) === hash(foo)\n```\n\n### Object\n\n```js\nhash({ foo: 'bar' }) === hash({ foo: 'bar' })\nhash({ foo: { bar: 1 } }) === hash({ foo: { bar: 1 } })\n```\n\nStable:\n\n```js\nhash({ a: 1, b: 2, c: 3 }) === hash({ c: 3, b: 2, a: 1 })\n```\n\nCircular:\n\n```js\nconst foo = {}\nfoo.foo = foo\nhash(foo) === hash(foo)\n```\n\n### `Function`, `Class`, `Set`, `Map`, `Buffer`...\n\n`stable-hash-x` guarantees reference consistency (`===`) for objects that the constructor isn't `Object`.\n\n```js\nconst foo = () => {}\nhash(foo) === hash(foo)\nhash(foo) !== hash(() => {})\n```\n\n```js\nclass Foo {}\nhash(Foo) === hash(Foo)\nhash(Foo) !== hash(class {})\n```\n\n```js\nconst foo = new Set([1])\nhash(foo) === hash(foo)\nhash(foo) !== hash(new Set([1]))\n```\n\n### Cross-realm\n\n```js\nimport { runInNewContext } from 'node:vm'\n\nconst obj1 = {\n  a: 1,\n  b: new Date('2022-06-25T01:55:27.743Z'),\n  c: /test/,\n  f: Symbol('test'),\n}\nconst obj2 = runInNewContext(`({\n  a: 1,\n  b: new Date('2022-06-25T01:55:27.743Z'),\n  c: /test/,\n  f: Symbol('test'),\n})`)\n\nobj1 === obj2 // false\nhash(obj1) === hash(obj2, true) // true\n```\n\n## Benchmark\n\n```log\n┌─────────┬────────────────────────────────┬──────────────────┬───────────────────┬────────────────────────┬────────────────────────┬─────────┐\n│ (index) │ Task name                      │ Latency avg (ns) │ Latency med (ns)  │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │\n├─────────┼────────────────────────────────┼──────────────────┼───────────────────┼────────────────────────┼────────────────────────┼─────────┤\n│ 0       │ 'stable-hash-x'                │ '7877.4 ± 1.57%' │ '7042.0 ± 167.00' │ '138708 ± 0.05%'       │ '142005 ± 3449'        │ 126975  │\n│ 1       │ 'hash-object'                  │ '17632 ± 0.73%'  │ '16708 ± 458.00'  │ '58820 ± 0.07%'        │ '59852 ± 1600'         │ 56716   │\n│ 2       │ 'json-stringify-deterministic' │ '10901 ± 0.83%'  │ '10250 ± 250.00'  │ '95860 ± 0.05%'        │ '97561 ± 2439'         │ 91739   │\n│ 3       │ 'stable-hash'                  │ '8318.5 ± 3.27%' │ '7042.0 ± 208.00' │ '138347 ± 0.06%'       │ '142005 ± 4074'        │ 120214  │\n└─────────┴────────────────────────────────┴──────────────────┴───────────────────┴────────────────────────┴────────────────────────┴─────────┘\n```\n\n## Notes\n\nThis function does something similar to `JSON.stringify`, but more than it. It doesn't generate a secure checksum, which usually has a fixed length and is hard to be reversed. With `stable-hash-x` it's still possible to get the original data. Also, the output might include any charaters, not just alphabets and numbers like other hash algorithms. So:\n\n- Use another encoding layer on top of it if you want to display the output.\n- Use another crypto layer on top of it if you want to have a secure and fixed length hash.\n\n```js\nimport crypto from 'node:crypto'\n\nimport { hash } from 'stable-hash-x'\n\nconst weakHash = hash(anyJavaScriptValueHere)\nconst encodedHash = Buffer.from(weakHash).toString('base64')\nconst safeHash = crypto.createHash('MD5').update(weakHash).digest('hex')\n```\n\nAlso, the consistency of this lib is sometimes guaranteed by the singularity of the WeakMap instance. So it might not generate the consistent results when running in different runtimes, e.g. server/client or parent/worker scenarios.\n\n## Sponsors and Backers\n\n[![Sponsors](https://raw.githubusercontent.com/1stG/static/master/sponsors.svg)](https://github.com/sponsors/JounQin)\n\n### Sponsors\n\n| 1stG                                                                                                                   | RxTS                                                                                                                   | UnRS                                                                                                                   | UnTS                                                                                                                   |\n| ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |\n| [![1stG Open Collective sponsors](https://opencollective.com/1stG/organizations.svg)](https://opencollective.com/1stG) | [![RxTS Open Collective sponsors](https://opencollective.com/rxts/organizations.svg)](https://opencollective.com/rxts) | [![UnRS Open Collective sponsors](https://opencollective.com/unrs/organizations.svg)](https://opencollective.com/unrs) | [![UnTS Open Collective sponsors](https://opencollective.com/unts/organizations.svg)](https://opencollective.com/unts) |\n\n### Backers\n\n| 1stG                                                                                                                | RxTS                                                                                                                | UnRS                                                                                                                | UnTS                                                                                                                |\n| ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |\n| [![1stG Open Collective backers](https://opencollective.com/1stG/individuals.svg)](https://opencollective.com/1stG) | [![RxTS Open Collective backers](https://opencollective.com/rxts/individuals.svg)](https://opencollective.com/rxts) | [![UnRS Open Collective backers](https://opencollective.com/unrs/individuals.svg)](https://opencollective.com/unrs) | [![UnTS Open Collective backers](https://opencollective.com/unts/individuals.svg)](https://opencollective.com/unts) |\n\n## Changelog\n\nDetailed changes for each release are documented in [CHANGELOG.md](./CHANGELOG.md).\n\n## License\n\nOriginally created by [Shu Ding].\n\n[MIT][] © [JounQin][]@[1stG.me][]\n\n[1stG.me]: https://www.1stG.me\n[MIT]: http://opensource.org/licenses/MIT\n[JounQin]: https://github.com/JounQin\n[Shu Ding]: https://github.com/shuding\n","readmeFilename":"README.md"}