Create keys or hashes from javascript values, useful for memoization or cache key generation.
$ npm install @httpx/stable-hash
$ yarn add @httpx/stable-hash
$ pnpm add @httpx/stable-hash
- 👉 Works with plain objects, dates, bigint, number, null, undefined and arrays.
- 🦄 Insensitive to object keys or array parameters order.
- 🙏 Properly error if it encounters an unsupported datatype.
- 📐 Lightweight (starts at ~500B).
- 🛡️ Tested on node 18-22, browser, cloudflare workers and runtime/edge.
- 🗝️ Available in ESM and CJS formats.
👉 Official website or Github Readme
- [x] createStableKey - Create a stable key from a value as a string (result object)
- [x] createStableKeyOrThrow - Create a stable key from value a string (throws).
- [x] createStableHash - Create a stable hash from a javascript object as a SHA-256/hexa (result object)
- [x] createStableHashOrThrow - Create a stable hash from a javascript object as a SHA-256/hexa (throws)
import { createStableKey } from '@httpx/stable-hash'
const params = {
key8: 'a string',
key1: 1,
key3: true,
key2: [3, 2, 1],
key7: {
key2: true,
key1: new Date('2025-02-11T08:58:32.075Z'),
},
};
const result = createStableKey(params);
if (!result.success) {
throw result.error; // TypeError
}
const key = result.key;
// Key contains a json comptatible string with object keys sorted.
// By default it will sort arrays if they contains only strings or numbers
// including bigints.
// "{"key1":1,"key2":[1,2,3],"key3":true,"key7":{"key1":"2025-02-11T08:58:32.075Z","key2":true},"key8":"a string"}"
import { createStableKeyOrThrow } from '@httpx/stable-hash'
const params = {
key8: 'a string',
key1: 1,
key3: true,
key2: [3, 2, 1],
key7: {
key2: true,
key1: new Date('2025-02-11T08:58:32.075Z'),
},
};
const key = createStableKeyOrThrow(params);
// Key contains a json comptatible string with object keys sorted.
// By default it will sort arrays if they contains only strings or numbers
// including bigints.
// "{"key1":1,"key2":[1,2,3],"key3":true,"key7":{"key1":"2025-02-11T08:58:32.075Z","key2":true},"key8":"a string"}"
import { createStableHash } from '@httpx/stable-hash';
const value = {
key8: 'a string',
key1: 1,
key3: true,
key2: [3, 2, 1],
key7: {
key2: true,
key1: new Date('2025-02-11T08:58:32.075Z'),
},
};
const result = await createStableHash(value, {
// By default SHA-256 is used (SHA-512 available)
algorithm: 'SHA-256',
// By default the hash is encoded in hexadecimal
encoding: 'hexa',
});
if (!result.success) {
throw result.error;
}
const hash = result.hash;
// -> 'fb17a6300efcf62ae80708e2a672aee581b7f0dd7c6a9a7a748218846c679394'
import { createStableHashOrThrow } from '@httpx/stable-hash';
const params = {
key8: 'a string',
key1: 1,
key3: true,
key2: [3, 2, 1],
key7: {
key2: true,
key1: new Date('2025-02-11T08:58:32.075Z'),
},
};
try {
const hash = await createStableHashOrThrow(params, {
// By default SHA-256 is used (SHA-512 available)
algorithm: 'SHA-256',
// By default the hash is encoded in hexadecimal
encoding: 'hexa',
});
// -> 'fb17a6300efcf62ae80708e2a672aee581b7f0dd7c6a9a7a748218846c679394'
} catch (e) {
// TypeError in case of an unserializable data type
}
- [x] stable-hash. Fastest alternative. Might swallow errors though.
Performance is monitored with codspeed.io.
See bench for details.
Bundle size is tracked by a size-limit configuration
Scenario | Size with deps (compressed) |
---|---|
`import { createStableKeyOrThrow } from '@httpx/stable-hash' | ~ 480B |
`import { createStableKey } from '@httpx/stable-hash' | ~ 520B |
`import { createStableHashOrThrow } from '@httpx/stable-hash' | ~ 650B |
`import { createStableHash } from '@httpx/stable-hash' | ~ 695B |
Level | CI | Description |
---|---|---|
Node | ✅ | CI for 20.x & 22.x. |
Browser | ✅ | Tested with latest chrome (vitest/playwright) |
Browserslist | ✅ | > 95% on 01/2025. defaults, chrome >= 96, firefox >= 105, edge >= 113, safari >= 15, ios >= 15, opera >= 103, not dead |
Edge | ✅ | Ensured on CI with @vercel/edge-runtime. |
Cloudflare | ✅ | Ensured with @cloudflare/vitest-pool-workers (see wrangler.toml |
Typescript | ✅ | TS 5.0 + / are-the-type-wrong checks on CI. |
ES2022 | ✅ | Dist files checked with es-check |
Performance | ✅ | Monitored with with codspeed.io |
For older browsers: most frontend frameworks can transpile the library (ie: nextjs...)
Performance is continuously monitored thanks to codspeed.io.
RUN v3.0.5 /home/sebastien/github/httpx/packages/stable-hash
✓ bench/compare.bench.ts > Comparison 6441ms
name hz min max mean p75 p99 p995 p999 rme samples
· @httpx/stable-hash 294,773.22 0.0030 0.5363 0.0034 0.0032 0.0071 0.0094 0.0151 ±0.37% 147387 slowest
· stable-hash 13,291,407.61 0.0001 0.0766 0.0001 0.0001 0.0001 0.0001 0.0003 ±0.06% 6645705 fastest
· @tanstack/query-core (hashKey) 295,851.66 0.0031 0.4376 0.0034 0.0033 0.0042 0.0059 0.0076 ±0.50% 147926
✓ bench/create-stable-hash.bench.ts > createStableHashOrThrow 1228ms
name hz min max mean p75 p99 p995 p999 rme samples
· createStableHashOrThrow with array sorting 29,048.08 0.0263 0.2879 0.0344 0.0336 0.0729 0.1158 0.1718 ±0.49% 14525
· createStableHashOrThrow without array sorting 32,139.11 0.0245 0.9538 0.0311 0.0307 0.0459 0.0712 0.1496 ±0.55% 16070 fastest
✓ bench/create-stable-key.bench.ts > createStableKeyOrThrow 1403ms
name hz min max mean p75 p99 p995 p999 rme samples
· createStableKeyOrThrow with array sorting 203,266.13 0.0044 0.4635 0.0049 0.0048 0.0087 0.0091 0.0146 ±0.37% 101639
· createStableKeyOrThrow without array sorting 283,858.83 0.0031 0.8852 0.0035 0.0034 0.0073 0.0095 0.0149 ±0.46% 141930 fastest
BENCH Summary
stable-hash - bench/compare.bench.ts > Comparison
44.93x faster than @tanstack/query-core (hashKey)
45.09x faster than @httpx/stable-hash
createStableHashOrThrow without array sorting - bench/create-stable-hash.bench.ts > createStableHashOrThrow
1.11x faster than createStableHashOrThrow with array sorting
createStableKeyOrThrow without array sorting - bench/create-stable-key.bench.ts > createStableKeyOrThrow
1.40x faster than createStableKeyOrThrow with array sorting
See benchmark file for details.
Contributions are warmly appreciated. Have a look to the CONTRIBUTING document.
If my OSS work brightens your day, let's take it to new heights together! Sponsor, coffee, or star – any gesture of support fuels my passion to improve. Thanks for being awesome! 🙏❤️
|
|
JetBrains | Embie.be |
MIT © Sébastien Vanvelthem and contributors.