"use strict"; 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 */