Buckets:
| ; | |
| var __defProp = Object.defineProperty; | |
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | |
| var __getOwnPropNames = Object.getOwnPropertyNames; | |
| var __hasOwnProp = Object.prototype.hasOwnProperty; | |
| var __export = (target, all) => { | |
| for (var name in all) | |
| __defProp(target, name, { get: all[name], enumerable: true }); | |
| }; | |
| var __copyProps = (to, from, except, desc) => { | |
| if (from && typeof from === "object" || typeof from === "function") { | |
| for (let key of __getOwnPropNames(from)) | |
| if (!__hasOwnProp.call(to, key) && key !== except) | |
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | |
| } | |
| return to; | |
| }; | |
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | |
| // src/index.ts | |
| var index_exports = {}; | |
| __export(index_exports, { | |
| CRC: () => CRC, | |
| Cache: () => Cache, | |
| DJB2: () => DJB2, | |
| FNV1: () => FNV1, | |
| HashProviders: () => HashProviders, | |
| Hashery: () => Hashery, | |
| Murmur: () => Murmur, | |
| WebCrypto: () => WebCrypto | |
| }); | |
| module.exports = __toCommonJS(index_exports); | |
| var import_hookified = require("hookified"); | |
| // src/cache.ts | |
| var Cache = class { | |
| _enabled = true; | |
| _maxSize = 4e3; | |
| _store = /* @__PURE__ */ new Map(); | |
| _keys = []; | |
| constructor(options) { | |
| if (options?.enabled !== void 0) { | |
| this._enabled = options.enabled; | |
| } | |
| if (options?.maxSize !== void 0) { | |
| this._maxSize = options.maxSize; | |
| } | |
| } | |
| /** | |
| * Gets whether the cache is enabled. | |
| */ | |
| get enabled() { | |
| return this._enabled; | |
| } | |
| /** | |
| * Sets whether the cache is enabled. | |
| */ | |
| set enabled(value) { | |
| this._enabled = value; | |
| } | |
| /** | |
| * Gets the maximum number of items the cache can hold. | |
| */ | |
| get maxSize() { | |
| return this._maxSize; | |
| } | |
| /** | |
| * Sets the maximum number of items the cache can hold. | |
| */ | |
| set maxSize(value) { | |
| this._maxSize = value; | |
| } | |
| /** | |
| * Gets the underlying Map store. | |
| */ | |
| get store() { | |
| return this._store; | |
| } | |
| /** | |
| * Gets the current number of items in the cache. | |
| */ | |
| get size() { | |
| return this._store.size; | |
| } | |
| /** | |
| * Gets a value from the cache. | |
| * @param key - The cache key | |
| * @returns The cached value, or undefined if not found | |
| */ | |
| get(key) { | |
| return this._store.get(key); | |
| } | |
| /** | |
| * Sets a value in the cache with FIFO eviction. | |
| * If the cache is disabled, this method does nothing. | |
| * If the cache is at capacity, the oldest entry is removed before adding the new one. | |
| * @param key - The cache key | |
| * @param value - The value to cache | |
| */ | |
| set(key, value) { | |
| if (!this._enabled) { | |
| return; | |
| } | |
| if (this._store.has(key)) { | |
| this._store.set(key, value); | |
| return; | |
| } | |
| if (this._store.size >= this._maxSize) { | |
| const oldestKey = this._keys.shift(); | |
| if (oldestKey) { | |
| this._store.delete(oldestKey); | |
| } | |
| } | |
| this._keys.push(key); | |
| this._store.set(key, value); | |
| } | |
| /** | |
| * Checks if a key exists in the cache. | |
| * @param key - The cache key | |
| * @returns True if the key exists, false otherwise | |
| */ | |
| has(key) { | |
| return this._store.has(key); | |
| } | |
| /** | |
| * Clears all entries from the cache. | |
| */ | |
| clear() { | |
| this._store.clear(); | |
| this._keys = []; | |
| } | |
| }; | |
| // src/providers/crc.ts | |
| var CRC = class { | |
| get name() { | |
| return "crc32"; | |
| } | |
| toHashSync(data) { | |
| let bytes; | |
| if (data instanceof Uint8Array) { | |
| bytes = data; | |
| } else if (data instanceof ArrayBuffer) { | |
| bytes = new Uint8Array(data); | |
| } else if (data instanceof DataView) { | |
| bytes = new Uint8Array(data.buffer, data.byteOffset, data.byteLength); | |
| } else { | |
| const view = data; | |
| bytes = new Uint8Array(view.buffer, view.byteOffset, view.byteLength); | |
| } | |
| const CRC32_POLYNOMIAL = 3988292384; | |
| let crc = 4294967295; | |
| for (let i = 0; i < bytes.length; i++) { | |
| crc = crc ^ bytes[i]; | |
| for (let j = 0; j < 8; j++) { | |
| crc = crc >>> 1 ^ CRC32_POLYNOMIAL & -(crc & 1); | |
| } | |
| } | |
| crc = (crc ^ 4294967295) >>> 0; | |
| const hashHex = crc.toString(16).padStart(8, "0"); | |
| return hashHex; | |
| } | |
| async toHash(data) { | |
| return this.toHashSync(data); | |
| } | |
| }; | |
| // src/providers/crypto.ts | |
| var WebCrypto = class { | |
| _algorithm = "SHA-256"; | |
| constructor(options) { | |
| if (options?.algorithm) { | |
| this._algorithm = options?.algorithm; | |
| } | |
| } | |
| get name() { | |
| return this._algorithm; | |
| } | |
| async toHash(data) { | |
| const hashBuffer = await crypto.subtle.digest(this._algorithm, data); | |
| const hashArray = Array.from(new Uint8Array(hashBuffer)); | |
| const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join(""); | |
| return hashHex; | |
| } | |
| }; | |
| // src/providers/djb2.ts | |
| var DJB2 = class { | |
| /** | |
| * The name identifier for this hash provider. | |
| */ | |
| get name() { | |
| return "djb2"; | |
| } | |
| /** | |
| * Computes the DJB2 hash of the provided data synchronously. | |
| * | |
| * @param data - The data to hash (Uint8Array, ArrayBuffer, or DataView) | |
| * @returns An 8-character lowercase hexadecimal string | |
| * | |
| * @example | |
| * ```typescript | |
| * const djb2 = new DJB2(); | |
| * const data = new TextEncoder().encode('hello'); | |
| * const hash = djb2.toHashSync(data); | |
| * console.log(hash); // "7c9df5ea" | |
| * ``` | |
| */ | |
| toHashSync(data) { | |
| let bytes; | |
| if (data instanceof Uint8Array) { | |
| bytes = data; | |
| } else if (data instanceof ArrayBuffer) { | |
| bytes = new Uint8Array(data); | |
| } else if (data instanceof DataView) { | |
| bytes = new Uint8Array(data.buffer, data.byteOffset, data.byteLength); | |
| } else { | |
| const view = data; | |
| bytes = new Uint8Array(view.buffer, view.byteOffset, view.byteLength); | |
| } | |
| let hash = 5381; | |
| for (let i = 0; i < bytes.length; i++) { | |
| hash = (hash << 5) + hash + bytes[i]; | |
| hash = hash >>> 0; | |
| } | |
| const hashHex = hash.toString(16).padStart(8, "0"); | |
| return hashHex; | |
| } | |
| /** | |
| * Computes the DJB2 hash of the provided data. | |
| * | |
| * @param data - The data to hash (Uint8Array, ArrayBuffer, or DataView) | |
| * @returns A Promise resolving to an 8-character lowercase hexadecimal string | |
| * | |
| * @example | |
| * ```typescript | |
| * const djb2 = new DJB2(); | |
| * const data = new TextEncoder().encode('hello'); | |
| * const hash = await djb2.toHash(data); | |
| * console.log(hash); // "7c9df5ea" | |
| * ``` | |
| */ | |
| async toHash(data) { | |
| return this.toHashSync(data); | |
| } | |
| }; | |
| // src/providers/fnv1.ts | |
| var FNV1 = class { | |
| /** | |
| * The name identifier for this hash provider. | |
| */ | |
| get name() { | |
| return "fnv1"; | |
| } | |
| /** | |
| * Computes the FNV-1 hash of the provided data synchronously. | |
| * | |
| * @param data - The data to hash (Uint8Array, ArrayBuffer, or DataView) | |
| * @returns An 8-character lowercase hexadecimal string | |
| */ | |
| toHashSync(data) { | |
| let bytes; | |
| if (data instanceof Uint8Array) { | |
| bytes = data; | |
| } else if (data instanceof ArrayBuffer) { | |
| bytes = new Uint8Array(data); | |
| } else if (data instanceof DataView) { | |
| bytes = new Uint8Array(data.buffer, data.byteOffset, data.byteLength); | |
| } else { | |
| const view = data; | |
| bytes = new Uint8Array(view.buffer, view.byteOffset, view.byteLength); | |
| } | |
| const FNV_OFFSET_BASIS = 2166136261; | |
| const FNV_PRIME = 16777619; | |
| let hash = FNV_OFFSET_BASIS; | |
| for (let i = 0; i < bytes.length; i++) { | |
| hash = hash * FNV_PRIME; | |
| hash = hash ^ bytes[i]; | |
| hash = hash >>> 0; | |
| } | |
| const hashHex = hash.toString(16).padStart(8, "0"); | |
| return hashHex; | |
| } | |
| /** | |
| * Computes the FNV-1 hash of the provided data. | |
| * | |
| * @param data - The data to hash (Uint8Array, ArrayBuffer, or DataView) | |
| * @returns A Promise resolving to an 8-character lowercase hexadecimal string | |
| */ | |
| async toHash(data) { | |
| return this.toHashSync(data); | |
| } | |
| }; | |
| // src/providers/murmur.ts | |
| var Murmur = class { | |
| _seed; | |
| /** | |
| * Creates a new Murmur instance. | |
| * | |
| * @param seed - Optional seed value for the hash (default: 0) | |
| */ | |
| constructor(seed = 0) { | |
| this._seed = seed >>> 0; | |
| } | |
| /** | |
| * The name identifier for this hash provider. | |
| */ | |
| get name() { | |
| return "murmur"; | |
| } | |
| /** | |
| * Gets the current seed value used for hashing. | |
| */ | |
| get seed() { | |
| return this._seed; | |
| } | |
| /** | |
| * Computes the Murmur 32-bit hash of the provided data synchronously. | |
| * | |
| * @param data - The data to hash (Uint8Array, ArrayBuffer, or DataView) | |
| * @returns An 8-character lowercase hexadecimal string | |
| * | |
| * @example | |
| * ```typescript | |
| * const murmur = new Murmur(); | |
| * const data = new TextEncoder().encode('hello'); | |
| * const hash = murmur.toHashSync(data); | |
| * console.log(hash); // "248bfa47" | |
| * ``` | |
| */ | |
| toHashSync(data) { | |
| let bytes; | |
| if (data instanceof Uint8Array) { | |
| bytes = data; | |
| } else if (data instanceof ArrayBuffer) { | |
| bytes = new Uint8Array(data); | |
| } else if (data instanceof DataView) { | |
| bytes = new Uint8Array(data.buffer, data.byteOffset, data.byteLength); | |
| } else { | |
| const view = data; | |
| bytes = new Uint8Array(view.buffer, view.byteOffset, view.byteLength); | |
| } | |
| const c1 = 3432918353; | |
| const c2 = 461845907; | |
| const length = bytes.length; | |
| const nblocks = Math.floor(length / 4); | |
| let h1 = this._seed; | |
| for (let i = 0; i < nblocks; i++) { | |
| const index = i * 4; | |
| let k12 = bytes[index] & 255 | (bytes[index + 1] & 255) << 8 | (bytes[index + 2] & 255) << 16 | (bytes[index + 3] & 255) << 24; | |
| k12 = this._imul(k12, c1); | |
| k12 = this._rotl32(k12, 15); | |
| k12 = this._imul(k12, c2); | |
| h1 ^= k12; | |
| h1 = this._rotl32(h1, 13); | |
| h1 = this._imul(h1, 5) + 3864292196; | |
| } | |
| const tail = nblocks * 4; | |
| let k1 = 0; | |
| switch (length & 3) { | |
| case 3: | |
| k1 ^= (bytes[tail + 2] & 255) << 16; | |
| // fallthrough | |
| case 2: | |
| k1 ^= (bytes[tail + 1] & 255) << 8; | |
| // fallthrough | |
| case 1: | |
| k1 ^= bytes[tail] & 255; | |
| k1 = this._imul(k1, c1); | |
| k1 = this._rotl32(k1, 15); | |
| k1 = this._imul(k1, c2); | |
| h1 ^= k1; | |
| } | |
| h1 ^= length; | |
| h1 ^= h1 >>> 16; | |
| h1 = this._imul(h1, 2246822507); | |
| h1 ^= h1 >>> 13; | |
| h1 = this._imul(h1, 3266489909); | |
| h1 ^= h1 >>> 16; | |
| h1 = h1 >>> 0; | |
| const hashHex = h1.toString(16).padStart(8, "0"); | |
| return hashHex; | |
| } | |
| /** | |
| * Computes the Murmur 32-bit hash of the provided data. | |
| * | |
| * @param data - The data to hash (Uint8Array, ArrayBuffer, or DataView) | |
| * @returns A Promise resolving to an 8-character lowercase hexadecimal string | |
| * | |
| * @example | |
| * ```typescript | |
| * const murmur = new Murmur(); | |
| * const data = new TextEncoder().encode('hello'); | |
| * const hash = await murmur.toHash(data); | |
| * console.log(hash); // "248bfa47" | |
| * ``` | |
| */ | |
| async toHash(data) { | |
| return this.toHashSync(data); | |
| } | |
| /** | |
| * 32-bit integer multiplication with proper overflow handling. | |
| * @private | |
| */ | |
| _imul(a, b) { | |
| if (Math.imul) { | |
| return Math.imul(a, b); | |
| } | |
| const ah = a >>> 16 & 65535; | |
| const al = a & 65535; | |
| const bh = b >>> 16 & 65535; | |
| const bl = b & 65535; | |
| return al * bl + (ah * bl + al * bh << 16 >>> 0) | 0; | |
| } | |
| /** | |
| * Left rotate a 32-bit integer. | |
| * @private | |
| */ | |
| _rotl32(x, r) { | |
| return x << r | x >>> 32 - r; | |
| } | |
| }; | |
| // src/providers.ts | |
| var HashProviders = class { | |
| _providers = /* @__PURE__ */ new Map(); | |
| _getFuzzy = true; | |
| /** | |
| * Creates a new HashProviders instance. | |
| * @param options - Optional configuration including initial providers to load | |
| * @example | |
| * ```ts | |
| * const providers = new HashProviders({ | |
| * providers: [{ name: 'custom', toHash: async (data) => '...' }] | |
| * }); | |
| * ``` | |
| */ | |
| constructor(options) { | |
| if (options?.providers) { | |
| this.loadProviders(options?.providers); | |
| } | |
| if (options?.getFuzzy !== void 0) { | |
| this._getFuzzy = Boolean(options?.getFuzzy); | |
| } | |
| } | |
| /** | |
| * Loads multiple hash providers at once. | |
| * Each provider is added to the internal map using its name as the key. | |
| * @param providers - Array of HashProvider objects to load | |
| * @example | |
| * ```ts | |
| * const providers = new HashProviders(); | |
| * providers.loadProviders([ | |
| * { name: 'md5', toHash: async (data) => '...' }, | |
| * { name: 'sha1', toHash: async (data) => '...' } | |
| * ]); | |
| * ``` | |
| */ | |
| loadProviders(providers) { | |
| for (const provider of providers) { | |
| this._providers.set(provider.name, provider); | |
| } | |
| } | |
| /** | |
| * Gets the internal Map of all registered hash providers. | |
| * @returns Map of provider names to HashProvider objects | |
| */ | |
| get providers() { | |
| return this._providers; | |
| } | |
| /** | |
| * Sets the internal Map of hash providers, replacing all existing providers. | |
| * @param providers - Map of provider names to HashProvider objects | |
| */ | |
| set providers(providers) { | |
| this._providers = providers; | |
| } | |
| /** | |
| * Gets an array of all provider names. | |
| * @returns Array of provider names | |
| * @example | |
| * ```ts | |
| * const providers = new HashProviders(); | |
| * providers.add({ name: 'sha256', toHash: async (data) => '...' }); | |
| * providers.add({ name: 'md5', toHash: async (data) => '...' }); | |
| * console.log(providers.names); // ['sha256', 'md5'] | |
| * ``` | |
| */ | |
| get names() { | |
| return Array.from(this._providers.keys()); | |
| } | |
| /** | |
| * Gets a hash provider by name with optional fuzzy matching. | |
| * | |
| * Fuzzy matching (enabled by default) attempts to find providers by: | |
| * 1. Exact match (after trimming whitespace) | |
| * 2. Case-insensitive match (lowercase) | |
| * 3. Dash-removed match (e.g., "SHA-256" matches "sha256") | |
| * | |
| * @param name - The name of the provider to retrieve | |
| * @param options - Optional configuration for the get operation | |
| * @param options.fuzzy - Enable/disable fuzzy matching (overrides constructor setting) | |
| * @returns The HashProvider if found, undefined otherwise | |
| * @example | |
| * ```ts | |
| * const providers = new HashProviders(); | |
| * providers.add({ name: 'sha256', toHash: async (data) => '...' }); | |
| * | |
| * // Exact match | |
| * const provider = providers.get('sha256'); | |
| * | |
| * // Fuzzy match (case-insensitive) | |
| * const provider2 = providers.get('SHA256'); | |
| * | |
| * // Fuzzy match (with dash) | |
| * const provider3 = providers.get('SHA-256'); | |
| * | |
| * // Disable fuzzy matching | |
| * const provider4 = providers.get('SHA256', { fuzzy: false }); // returns undefined | |
| * ``` | |
| */ | |
| get(name, options) { | |
| const getFuzzy = options?.fuzzy ?? this._getFuzzy; | |
| name = name.trim(); | |
| let result = this._providers.get(name); | |
| if (result === void 0 && getFuzzy === true) { | |
| name = name.toLowerCase(); | |
| result = this._providers.get(name); | |
| } | |
| if (result === void 0 && getFuzzy === true) { | |
| name = name.replaceAll("-", ""); | |
| result = this._providers.get(name); | |
| } | |
| return result; | |
| } | |
| /** | |
| * Adds a single hash provider to the collection. | |
| * If a provider with the same name already exists, it will be replaced. | |
| * @param provider - The HashProvider object to add | |
| * @example | |
| * ```ts | |
| * const providers = new HashProviders(); | |
| * providers.add({ | |
| * name: 'custom-hash', | |
| * toHash: async (data) => { | |
| * // Custom hashing logic | |
| * return 'hash-result'; | |
| * } | |
| * }); | |
| * ``` | |
| */ | |
| add(provider) { | |
| this._providers.set(provider.name, provider); | |
| } | |
| /** | |
| * Removes a hash provider from the collection by name. | |
| * @param name - The name of the provider to remove | |
| * @returns true if the provider was found and removed, false otherwise | |
| * @example | |
| * ```ts | |
| * const providers = new HashProviders(); | |
| * providers.add({ name: 'custom', toHash: async (data) => '...' }); | |
| * const removed = providers.remove('custom'); // returns true | |
| * const removed2 = providers.remove('nonexistent'); // returns false | |
| * ``` | |
| */ | |
| remove(name) { | |
| return this._providers.delete(name); | |
| } | |
| }; | |
| // src/index.ts | |
| var Hashery = class extends import_hookified.Hookified { | |
| _parse = JSON.parse; | |
| _stringify = JSON.stringify; | |
| _providers = new HashProviders(); | |
| _defaultAlgorithm = "SHA-256"; | |
| _defaultAlgorithmSync = "djb2"; | |
| _cache; | |
| constructor(options) { | |
| super(options); | |
| if (options?.parse) { | |
| this._parse = options.parse; | |
| } | |
| if (options?.stringify) { | |
| this._stringify = options.stringify; | |
| } | |
| if (options?.defaultAlgorithm) { | |
| this._defaultAlgorithm = options.defaultAlgorithm; | |
| } | |
| if (options?.defaultAlgorithmSync) { | |
| this._defaultAlgorithmSync = options.defaultAlgorithmSync; | |
| } | |
| this._cache = new Cache(options?.cache); | |
| this.loadProviders(options?.providers, { | |
| includeBase: options?.includeBase ?? true | |
| }); | |
| } | |
| /** | |
| * Gets the parse function used to deserialize stored values. | |
| * @returns The current parse function (defaults to JSON.parse) | |
| */ | |
| get parse() { | |
| return this._parse; | |
| } | |
| /** | |
| * Sets the parse function used to deserialize stored values. | |
| * @param value - The parse function to use for deserialization | |
| */ | |
| set parse(value) { | |
| this._parse = value; | |
| } | |
| /** | |
| * Gets the stringify function used to serialize values for storage. | |
| * @returns The current stringify function (defaults to JSON.stringify) | |
| */ | |
| get stringify() { | |
| return this._stringify; | |
| } | |
| /** | |
| * Sets the stringify function used to serialize values for storage. | |
| * @param value - The stringify function to use for serialization | |
| */ | |
| set stringify(value) { | |
| this._stringify = value; | |
| } | |
| /** | |
| * Gets the HashProviders instance used to manage hash providers. | |
| * @returns The current HashProviders instance | |
| */ | |
| get providers() { | |
| return this._providers; | |
| } | |
| /** | |
| * Sets the HashProviders instance used to manage hash providers. | |
| * @param value - The HashProviders instance to use | |
| */ | |
| set providers(value) { | |
| this._providers = value; | |
| } | |
| /** | |
| * Gets the names of all registered hash algorithm providers. | |
| * @returns An array of provider names (e.g., ['SHA-256', 'SHA-384', 'SHA-512']) | |
| */ | |
| get names() { | |
| return this._providers.names; | |
| } | |
| /** | |
| * Gets the default hash algorithm used when none is specified. | |
| * @returns The current default algorithm (defaults to 'SHA-256') | |
| */ | |
| get defaultAlgorithm() { | |
| return this._defaultAlgorithm; | |
| } | |
| /** | |
| * Sets the default hash algorithm to use when none is specified. | |
| * @param value - The default algorithm to use (e.g., 'SHA-256', 'SHA-512', 'djb2') | |
| * @example | |
| * ```ts | |
| * const hashery = new Hashery(); | |
| * hashery.defaultAlgorithm = 'SHA-512'; | |
| * | |
| * // Now toHash will use SHA-512 by default | |
| * const hash = await hashery.toHash({ data: 'example' }); | |
| * ``` | |
| */ | |
| set defaultAlgorithm(value) { | |
| this._defaultAlgorithm = value; | |
| } | |
| /** | |
| * Gets the default synchronous hash algorithm used when none is specified. | |
| * @returns The current default synchronous algorithm (defaults to 'djb2') | |
| */ | |
| get defaultAlgorithmSync() { | |
| return this._defaultAlgorithmSync; | |
| } | |
| /** | |
| * Sets the default synchronous hash algorithm to use when none is specified. | |
| * @param value - The default synchronous algorithm to use (e.g., 'djb2', 'fnv1', 'murmur', 'crc32') | |
| * @example | |
| * ```ts | |
| * const hashery = new Hashery(); | |
| * hashery.defaultAlgorithmSync = 'fnv1'; | |
| * | |
| * // Now synchronous operations will use fnv1 by default | |
| * ``` | |
| */ | |
| set defaultAlgorithmSync(value) { | |
| this._defaultAlgorithmSync = value; | |
| } | |
| /** | |
| * Gets the cache instance used to store computed hash values. | |
| * @returns The Cache instance | |
| * @example | |
| * ```ts | |
| * const hashery = new Hashery({ cache: { enabled: true } }); | |
| * | |
| * // Access the cache | |
| * hashery.cache.enabled; // true | |
| * hashery.cache.size; // number of cached items | |
| * hashery.cache.clear(); // clear all cached items | |
| * ``` | |
| */ | |
| get cache() { | |
| return this._cache; | |
| } | |
| /** | |
| * Generates a cryptographic hash of the provided data using the Web Crypto API. | |
| * The data is first stringified using the configured stringify function, then hashed. | |
| * | |
| * If an invalid algorithm is provided, a 'warn' event is emitted and the method falls back | |
| * to the default algorithm. You can listen to these warnings: | |
| * ```ts | |
| * hashery.on('warn', (message) => console.log(message)); | |
| * ``` | |
| * | |
| * @param data - The data to hash (will be stringified before hashing) | |
| * @param options - Optional configuration object | |
| * @param options.algorithm - The hash algorithm to use (defaults to 'SHA-256') | |
| * @param options.maxLength - Optional maximum length for the hash output | |
| * @returns A Promise that resolves to the hexadecimal string representation of the hash | |
| * | |
| * @example | |
| * ```ts | |
| * const hashery = new Hashery(); | |
| * const hash = await hashery.toHash({ name: 'John', age: 30 }); | |
| * console.log(hash); // "a1b2c3d4..." | |
| * | |
| * // Using a different algorithm | |
| * const hash512 = await hashery.toHash({ name: 'John' }, { algorithm: 'SHA-512' }); | |
| * ``` | |
| */ | |
| async toHash(data, options) { | |
| const context = { | |
| data, | |
| algorithm: options?.algorithm ?? this._defaultAlgorithm, | |
| maxLength: options?.maxLength | |
| }; | |
| await this.beforeHook("toHash", context); | |
| const stringified = this._stringify(context.data); | |
| const cacheKey = `${context.algorithm}:${stringified}`; | |
| if (this._cache.enabled) { | |
| const cached = this._cache.get(cacheKey); | |
| if (cached !== void 0) { | |
| let cachedHash = cached; | |
| if (options?.maxLength && cachedHash.length > options.maxLength) { | |
| cachedHash = cachedHash.substring(0, options.maxLength); | |
| } | |
| const result2 = { | |
| hash: cachedHash, | |
| data: context.data, | |
| algorithm: context.algorithm | |
| }; | |
| await this.afterHook("toHash", result2); | |
| return result2.hash; | |
| } | |
| } | |
| const encoder = new TextEncoder(); | |
| const dataBuffer = encoder.encode(stringified); | |
| let provider = this._providers.get(context.algorithm); | |
| if (!provider) { | |
| this.emit( | |
| "warn", | |
| `Invalid algorithm '${context.algorithm}' not found. Falling back to default algorithm '${this._defaultAlgorithm}'.` | |
| ); | |
| provider = new WebCrypto({ | |
| algorithm: this._defaultAlgorithm | |
| }); | |
| } | |
| let hash = await provider.toHash(dataBuffer); | |
| if (this._cache.enabled) { | |
| this._cache.set(cacheKey, hash); | |
| } | |
| if (options?.maxLength && hash.length > options?.maxLength) { | |
| hash = hash.substring(0, options.maxLength); | |
| } | |
| const result = { hash, data: context.data, algorithm: context.algorithm }; | |
| await this.afterHook("toHash", result); | |
| return result.hash; | |
| } | |
| /** | |
| * Generates a deterministic number within a specified range based on the hash of the provided data. | |
| * This method uses the toHash function to create a consistent hash, then maps it to a number | |
| * between min and max (inclusive). | |
| * | |
| * @param data - The data to hash (will be stringified before hashing) | |
| * @param options - Configuration options (optional, defaults to min: 0, max: 100) | |
| * @param options.min - The minimum value of the range (inclusive, defaults to 0) | |
| * @param options.max - The maximum value of the range (inclusive, defaults to 100) | |
| * @param options.algorithm - The hash algorithm to use (defaults to 'SHA-256') | |
| * @param options.hashLength - Number of characters from hash to use for conversion (defaults to 16) | |
| * @returns A Promise that resolves to a number between min and max (inclusive) | |
| * | |
| * @example | |
| * ```ts | |
| * const hashery = new Hashery(); | |
| * const num = await hashery.toNumber({ user: 'john' }); // Uses default min: 0, max: 100 | |
| * console.log(num); // Always returns the same number for the same input, e.g., 42 | |
| * | |
| * // Using custom range | |
| * const num2 = await hashery.toNumber({ user: 'john' }, { min: 1, max: 100 }); | |
| * | |
| * // Using a different algorithm | |
| * const num512 = await hashery.toNumber({ user: 'john' }, { min: 0, max: 255, algorithm: 'SHA-512' }); | |
| * ``` | |
| */ | |
| async toNumber(data, options = {}) { | |
| const { | |
| min = 0, | |
| max = 100, | |
| algorithm = this._defaultAlgorithm, | |
| hashLength = 16 | |
| } = options; | |
| if (min > max) { | |
| throw new Error("min cannot be greater than max"); | |
| } | |
| const hash = await this.toHash(data, { algorithm, maxLength: hashLength }); | |
| const hashNumber = Number.parseInt(hash, 16); | |
| const range = max - min + 1; | |
| const mapped = min + hashNumber % range; | |
| return mapped; | |
| } | |
| /** | |
| * Generates a hash of the provided data synchronously using a non-cryptographic hash algorithm. | |
| * The data is first stringified using the configured stringify function, then hashed. | |
| * | |
| * Note: This method only works with synchronous hash providers (djb2, fnv1, murmur, crc32). | |
| * WebCrypto algorithms (SHA-256, SHA-384, SHA-512) are not supported and will throw an error. | |
| * | |
| * If an invalid algorithm is provided, a 'warn' event is emitted and the method falls back | |
| * to the default synchronous algorithm. You can listen to these warnings: | |
| * ```ts | |
| * hashery.on('warn', (message) => console.log(message)); | |
| * ``` | |
| * | |
| * @param data - The data to hash (will be stringified before hashing) | |
| * @param options - Optional configuration object | |
| * @param options.algorithm - The hash algorithm to use (defaults to 'djb2') | |
| * @param options.maxLength - Optional maximum length for the hash output | |
| * @returns The hexadecimal string representation of the hash | |
| * | |
| * @throws {Error} If the specified algorithm does not support synchronous hashing | |
| * @throws {Error} If the default algorithm is not found | |
| * | |
| * @example | |
| * ```ts | |
| * const hashery = new Hashery(); | |
| * const hash = hashery.toHashSync({ name: 'John', age: 30 }); | |
| * console.log(hash); // "7c9df5ea..." (djb2 hash) | |
| * | |
| * // Using a different algorithm | |
| * const hashFnv1 = hashery.toHashSync({ name: 'John' }, { algorithm: 'fnv1' }); | |
| * ``` | |
| */ | |
| toHashSync(data, options) { | |
| const context = { | |
| data, | |
| algorithm: options?.algorithm ?? this._defaultAlgorithmSync, | |
| maxLength: options?.maxLength | |
| }; | |
| this.hookSync("before:toHashSync", context); | |
| const algorithm = context.algorithm; | |
| const stringified = this._stringify(context.data); | |
| const cacheKey = `${algorithm}:${stringified}`; | |
| if (this._cache.enabled) { | |
| const cached = this._cache.get(cacheKey); | |
| if (cached !== void 0) { | |
| let cachedHash = cached; | |
| if (options?.maxLength && cachedHash.length > options.maxLength) { | |
| cachedHash = cachedHash.substring(0, options.maxLength); | |
| } | |
| const result2 = { | |
| hash: cachedHash, | |
| data: context.data, | |
| algorithm | |
| }; | |
| this.hookSync("after:toHashSync", result2); | |
| return result2.hash; | |
| } | |
| } | |
| const encoder = new TextEncoder(); | |
| const dataBuffer = encoder.encode(stringified); | |
| let provider = this._providers.get(algorithm); | |
| if (!provider) { | |
| this.emit( | |
| "warn", | |
| `Invalid algorithm '${algorithm}' not found. Falling back to default algorithm '${this._defaultAlgorithmSync}'.` | |
| ); | |
| provider = this._providers.get(this._defaultAlgorithmSync); | |
| if (!provider) { | |
| throw new Error( | |
| `Hash provider '${this._defaultAlgorithmSync}' (default) not found` | |
| ); | |
| } | |
| } | |
| if (!provider.toHashSync) { | |
| throw new Error( | |
| `Hash provider '${algorithm}' does not support synchronous hashing. Use toHash() instead or choose a different algorithm (djb2, fnv1, murmur, crc32).` | |
| ); | |
| } | |
| let hash = provider.toHashSync(dataBuffer); | |
| if (this._cache.enabled) { | |
| this._cache.set(cacheKey, hash); | |
| } | |
| if (options?.maxLength && hash.length > options?.maxLength) { | |
| hash = hash.substring(0, options.maxLength); | |
| } | |
| const result = { hash, data: context.data, algorithm: context.algorithm }; | |
| this.hookSync("after:toHashSync", result); | |
| return result.hash; | |
| } | |
| /** | |
| * Generates a deterministic number within a specified range based on the hash of the provided data synchronously. | |
| * This method uses the toHashSync function to create a consistent hash, then maps it to a number | |
| * between min and max (inclusive). | |
| * | |
| * Note: This method only works with synchronous hash providers (djb2, fnv1, murmur, crc32). | |
| * | |
| * @param data - The data to hash (will be stringified before hashing) | |
| * @param options - Configuration options (optional, defaults to min: 0, max: 100) | |
| * @param options.min - The minimum value of the range (inclusive, defaults to 0) | |
| * @param options.max - The maximum value of the range (inclusive, defaults to 100) | |
| * @param options.algorithm - The hash algorithm to use (defaults to 'djb2') | |
| * @param options.hashLength - Number of characters from hash to use for conversion (defaults to 16) | |
| * @returns A number between min and max (inclusive) | |
| * | |
| * @throws {Error} If the specified algorithm does not support synchronous hashing | |
| * @throws {Error} If min is greater than max | |
| * | |
| * @example | |
| * ```ts | |
| * const hashery = new Hashery(); | |
| * const num = hashery.toNumberSync({ user: 'john' }); // Uses default min: 0, max: 100 | |
| * console.log(num); // Always returns the same number for the same input, e.g., 42 | |
| * | |
| * // Using custom range | |
| * const num2 = hashery.toNumberSync({ user: 'john' }, { min: 1, max: 100 }); | |
| * | |
| * // Using a different algorithm | |
| * const numFnv1 = hashery.toNumberSync({ user: 'john' }, { min: 0, max: 255, algorithm: 'fnv1' }); | |
| * ``` | |
| */ | |
| toNumberSync(data, options = {}) { | |
| const { | |
| min = 0, | |
| max = 100, | |
| algorithm = this._defaultAlgorithmSync, | |
| hashLength = 16 | |
| } = options; | |
| if (min > max) { | |
| throw new Error("min cannot be greater than max"); | |
| } | |
| const hash = this.toHashSync(data, { algorithm, maxLength: hashLength }); | |
| const hashNumber = Number.parseInt(hash, 16); | |
| const range = max - min + 1; | |
| const mapped = min + hashNumber % range; | |
| return mapped; | |
| } | |
| loadProviders(providers, options = { includeBase: true }) { | |
| if (providers) { | |
| for (const provider of providers) { | |
| this._providers.add(provider); | |
| } | |
| } | |
| if (options.includeBase) { | |
| this.providers.add(new WebCrypto({ algorithm: "SHA-256" })); | |
| this.providers.add(new WebCrypto({ algorithm: "SHA-384" })); | |
| this.providers.add(new WebCrypto({ algorithm: "SHA-512" })); | |
| this.providers.add(new CRC()); | |
| this.providers.add(new DJB2()); | |
| this.providers.add(new FNV1()); | |
| this.providers.add(new Murmur()); | |
| } | |
| } | |
| }; | |
| // Annotate the CommonJS export names for ESM import in node: | |
| 0 && (module.exports = { | |
| CRC, | |
| Cache, | |
| DJB2, | |
| FNV1, | |
| HashProviders, | |
| Hashery, | |
| Murmur, | |
| WebCrypto | |
| }); | |
| /* v8 ignore next -- @preserve */ | |
Xet Storage Details
- Size:
- 30.9 kB
- Xet hash:
- 0299cbe913601abb83d882b8f99a399fbfee84f6cac109a96d054a6384e6d6a8
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.