πŸ“„ File detail

utils/hash.ts

🧩 .tsπŸ“ 47 linesπŸ’Ύ 1,683 bytesπŸ“ text
← Back to All Files

🎯 Use case

This file lives under β€œutils/”, which covers cross-cutting helpers (shell, tempfiles, settings, messages, process input, …). On the API surface it exposes djb2Hash, hashContent, and hashPair β€” mainly functions, hooks, or classes. What the file header says: 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 r.

Generated from folder role, exports, dependency roots, and inline comments β€” not hand-reviewed for every path.

🧠 Inline summary

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).

πŸ“€ Exports (heuristic)

  • djb2Hash
  • hashContent
  • hashPair

πŸ–₯️ Source preview

/**
 * 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')
}