mono/packages/kbot/ref/utils/hash.ts
2026-04-01 01:05:48 +02:00

47 lines
1.6 KiB
TypeScript

/**
* djb2 string hash — fast non-cryptographic hash returning a signed 32-bit int.
* Deterministic across runtimes (unlike Bun.hash which uses wyhash). Use as a
* fallback when Bun.hash isn't available, or when you need on-disk-stable
* output (e.g. cache directory names that must survive runtime upgrades).
*/
export function djb2Hash(str: string): number {
let hash = 0
for (let i = 0; i < str.length; i++) {
hash = ((hash << 5) - hash + str.charCodeAt(i)) | 0
}
return hash
}
/**
* Hash arbitrary content for change detection. Bun.hash is ~100x faster than
* sha256 and collision-resistant enough for diff detection (not crypto-safe).
*/
export function hashContent(content: string): string {
if (typeof Bun !== 'undefined') {
return Bun.hash(content).toString()
}
// eslint-disable-next-line @typescript-eslint/no-require-imports
const crypto = require('crypto') as typeof import('crypto')
return crypto.createHash('sha256').update(content).digest('hex')
}
/**
* Hash two strings without allocating a concatenated temp string. Bun path
* seed-chains wyhash (hash(a) feeds as seed to hash(b)); Node path uses
* incremental SHA-256 update. Seed-chaining naturally disambiguates
* ("ts","code") vs ("tsc","ode") so no separator is needed under Bun.
*/
export function hashPair(a: string, b: string): string {
if (typeof Bun !== 'undefined') {
return Bun.hash(b, Bun.hash(a)).toString()
}
// eslint-disable-next-line @typescript-eslint/no-require-imports
const crypto = require('crypto') as typeof import('crypto')
return crypto
.createHash('sha256')
.update(a)
.update('\0')
.update(b)
.digest('hex')
}