README
stable-hash
A small (496b) lib for stable hashing a JavaScript value. Originally created for SWR.
It's similar to JSON.stringify(value)
, but:
value
can be any JavaScript value- It sorts object keys
Use
yarn add stable-hash
import stableHash from 'stable-hash'
stableHash(anyJavaScriptValueHere) // returns a string
Examples
Primitive Value
stableHash(1)
stableHash('foo')
stableHash(true)
stableHash(undefined)
stableHash(null)
stableHash(NaN)
BigInt:
stableHash(1) === stableHash(1n)
stableHash(1) !== stableHash(2n)
Symbol:
stableHash(Symbol.for('foo')) === stableHash(Symbol.for('foo'))
stableHash(Symbol.for('foo')) === stableHash(Symbol('foo'))
stableHash(Symbol('foo')) === stableHash(Symbol('foo'))
stableHash(Symbol('foo')) !== stableHash(Symbol('bar'))
Since Symbols cannot be serialized, stable-hash simply uses its description as the hash.
Regex
stableHash(/foo/) === stableHash(/foo/)
stableHash(/foo/) !== stableHash(/bar/)
Date
stableHash(new Date(1)) === stableHash(new Date(1))
Array
stableHash([1, '2', [new Date(3)]]) === stableHash([1, '2', [new Date(3)]])
stableHash([1, 2]) !== stableHash([2, 1])
Circular:
const foo = []
foo.push(foo)
stableHash(foo) === stableHash(foo)
Object
stableHash({ foo: 'bar' }) === stableHash({ foo: 'bar' })
stableHash({ foo: { bar: 1 } }) === stableHash({ foo: { bar: 1 } })
Stable:
stableHash({ a: 1, b: 2, c: 3 }) === stableHash({ c: 3, b: 2, a: 1 })
Circular:
const foo = {}
foo.foo = foo
stableHash(foo) === stableHash(foo)
Function, Class, Set, Map, Buffer...
stable-hash
guarantees reference consistency (===
) for objects that the constructor isn't Object
.
const foo = () => {}
stableHash(foo) === stableHash(foo)
stableHash(foo) !== stableHash(() => {})
class Foo {}
stableHash(Foo) === stableHash(Foo)
stableHash(Foo) !== stableHash(class {})
const foo = new Set([1])
stableHash(foo) === stableHash(foo)
stableHash(foo) !== stableHash(new Set([1]))
Notice
This function does something similar to serialization. It doesn't generate a secure checksum or digest, which usually has a fixed length and is hard to be reversed. With stable-hash
it's likely possible to get the original data. Also, the output might include any charaters, not just alphabets and numbers like other hash algorithm. So:
- Use another encoding layer on top of it if you want to display the output.
- Use another crypto layer on top of it if you want to have a secure and fixed length hash.
import crypto from 'crypto'
import stableHash from 'stable-hash'
const hash = stableHash(anyJavaScriptValueHere)
const encodedHash = Buffer.from(hash).toString('base64')
const safeHash = crypto.createHash('MD5').update(hash).digest('hex')
License
Created by Shu Ding. Released under the MIT License.