{"version":3,"sources":["../src/simpleflakes.ts"],"names":["SIMPLEFLAKE_EPOCH","SIMPLEFLAKE_TIMESTAMP_MAX","SIMPLEFLAKE_RANDOM_MAX","UNSIGNED_64BIT_MAX","randomBuffer","Uint32Array","randomBufferIndex","toBigInt","value","label","BigInt","TypeError","assertInRange","minValue","maxValue","RangeError","getRandomSource","globalCrypto","globalThis","crypto","require","webcrypto","Error","refillRandomBuffer","getRandomValues","random23","simpleflake","timestamp","Date","now","randomBits","epoch","timestampOffset","timestampValue","resolvedRandomBits","binary","padding","binValue","toString","length","CACHE_64_BIT_ZEROS","substr","extractBits","data","shift","shiftN","lengthN","SimpleflakeStruct","parseSimpleflake","flake","flakeValue","epochValue"],"mappings":"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","file":"simpleflakes.mjs","sourcesContent":["const SIMPLEFLAKE_EPOCH = 946684800000n; // Date.UTC(2000, 0, 1)\nconst UNSIGNED_23BIT_MAX = 8388607;\nconst RANDOM_BUFFER_SIZE = 1024;\n\nconst SIMPLEFLAKE_TIMESTAMP_LENGTH = 41n;\nconst SIMPLEFLAKE_RANDOM_LENGTH = 23n;\nconst SIMPLEFLAKE_TIMESTAMP_MAX = (1n << SIMPLEFLAKE_TIMESTAMP_LENGTH) - 1n;\nconst SIMPLEFLAKE_RANDOM_MAX = (1n << SIMPLEFLAKE_RANDOM_LENGTH) - 1n;\nconst UNSIGNED_64BIT_MAX = (1n << 64n) - 1n;\n\nconst SIMPLEFLAKE_RANDOM_SHIFT = 0n;\nconst SIMPLEFLAKE_TIMESTAMP_SHIFT = 23n;\n\nconst CACHE_64_BIT_ZEROS =\n  \"0000000000000000000000000000000000000000000000000000000000000000\";\n\ninterface RandomSource {\n  getRandomValues<T extends ArrayBufferView>(array: T): T;\n}\n\ndeclare const require: ((moduleName: string) => unknown) | undefined;\n\nconst randomBuffer = new Uint32Array(RANDOM_BUFFER_SIZE);\nlet randomBufferIndex = RANDOM_BUFFER_SIZE;\n\nfunction toBigInt(value: bigint | number | string, label: string): bigint {\n  try {\n    return typeof value === \"bigint\" ? value : BigInt(value);\n  } catch {\n    throw new TypeError(`${label} must be an integer representable as a BigInt.`);\n  }\n}\n\nfunction assertInRange(\n  value: bigint,\n  minValue: bigint,\n  maxValue: bigint,\n  label: string\n): void {\n  if (value < minValue || value > maxValue) {\n    throw new RangeError(\n      `${label} must be between ${minValue} and ${maxValue}.`\n    );\n  }\n}\n\nfunction getRandomSource(): RandomSource {\n  const globalCrypto = (globalThis as typeof globalThis & {\n    crypto?: RandomSource;\n  }).crypto;\n\n  if (globalCrypto) return globalCrypto;\n\n  try {\n    return (require as (moduleName: string) => { webcrypto: RandomSource })(\n      [\"node\", \"crypto\"].join(\":\")\n    ).webcrypto;\n  } catch {\n    throw new Error(\n      \"Cryptographically secure random values are unavailable in this environment.\"\n    );\n  }\n}\n\nfunction refillRandomBuffer(): void {\n  getRandomSource().getRandomValues(randomBuffer);\n  randomBufferIndex = 0;\n}\n\nfunction random23(): bigint {\n  if (randomBufferIndex >= RANDOM_BUFFER_SIZE) {\n    refillRandomBuffer();\n  }\n  const value = randomBuffer[randomBufferIndex]!;\n\n  randomBufferIndex += 1;\n  return BigInt(value & UNSIGNED_23BIT_MAX);\n}\n\n/**\n * Generates a simpleflake ID\n * @param timestamp - Timestamp in milliseconds (defaults to current time)\n * @param randomBits - Random bits for the ID (defaults to a cryptographically secure random value)\n * @param epoch - Epoch timestamp in milliseconds (defaults to SIMPLEFLAKE_EPOCH)\n * @returns Generated simpleflake as a BigInt\n */\nexport function simpleflake(\n  timestamp: number | bigint = Date.now(),\n  randomBits?: number | bigint,\n  epoch: number | bigint = SIMPLEFLAKE_EPOCH\n): bigint {\n  const timestampValue = toBigInt(timestamp, \"timestamp\");\n  const epochValue = toBigInt(epoch, \"epoch\");\n  const timestampOffset = timestampValue - epochValue;\n  const resolvedRandomBits =\n    randomBits == null ? random23() : toBigInt(randomBits, \"randomBits\");\n\n  assertInRange(\n    timestampOffset,\n    0n,\n    SIMPLEFLAKE_TIMESTAMP_MAX,\n    \"timestamp - epoch\"\n  );\n  assertInRange(resolvedRandomBits, 0n, SIMPLEFLAKE_RANDOM_MAX, \"randomBits\");\n\n  // Use bitwise OR instead of addition since bit ranges don't overlap\n\n  return (\n    (timestampOffset << SIMPLEFLAKE_TIMESTAMP_SHIFT) |\n    resolvedRandomBits\n  );\n}\n\n/**\n * Converts a value to binary representation\n * @param value - The value to convert to binary\n * @param padding - Whether to pad to 64 bits (defaults to true)\n * @returns Binary string representation\n */\nexport function binary(\n  value: bigint | number | string,\n  padding: boolean = true\n): string {\n  const binValue = toBigInt(value, \"value\").toString(2);\n  return padding && binValue.length < 64\n    ? CACHE_64_BIT_ZEROS.substr(0, 64 - binValue.length) + binValue\n    : binValue;\n}\n\n/**\n * Extracts bits from a data value\n * @param data - The data to extract bits from\n * @param shift - Number of bits to shift\n * @param length - Number of bits to extract\n * @returns Extracted bits as a BigInt\n */\nexport function extractBits(\n  data: bigint | number | string,\n  shift: bigint | number,\n  length: bigint | number\n): bigint {\n  const shiftN = toBigInt(shift, \"shift\");\n  const lengthN = toBigInt(length, \"length\");\n  // Optimize: shift right first, then mask (avoids creating large bitmask)\n  return (toBigInt(data, \"data\") >> shiftN) & ((1n << lengthN) - 1n);\n}\n\n/**\n * Structure representing a parsed simpleflake\n */\nexport class SimpleflakeStruct {\n  public declare readonly timestamp: bigint;\n  public declare readonly randomBits: bigint;\n\n  constructor(timestamp: bigint, randomBits: bigint) {\n    if (timestamp == null || randomBits == null) {\n      throw new Error(\"Missing argument for SimpleflakeStruct.\");\n    }\n    this.timestamp = timestamp;\n    this.randomBits = randomBits;\n  }\n}\n\n/**\n * Parses a simpleflake into its components\n * @param flake - The simpleflake to parse\n * @param epoch - Epoch timestamp in milliseconds used to reconstruct the absolute timestamp\n * @returns SimpleflakeStruct containing timestamp and random bits\n */\nexport function parseSimpleflake(\n  flake: bigint | number | string,\n  epoch: bigint | number = SIMPLEFLAKE_EPOCH\n): SimpleflakeStruct {\n  const flakeValue = toBigInt(flake, \"flake\");\n  const epochValue = toBigInt(epoch, \"epoch\");\n\n  assertInRange(flakeValue, 0n, UNSIGNED_64BIT_MAX, \"flake\");\n\n  return new SimpleflakeStruct(\n    extractBits(\n      flakeValue,\n      SIMPLEFLAKE_TIMESTAMP_SHIFT,\n      SIMPLEFLAKE_TIMESTAMP_LENGTH\n    ) + epochValue,\n    extractBits(\n      flakeValue,\n      SIMPLEFLAKE_RANDOM_SHIFT,\n      SIMPLEFLAKE_RANDOM_LENGTH\n    )\n  );\n}\n\n// Export constants\nexport { SIMPLEFLAKE_EPOCH };\n\n// Default export for CommonJS compatibility\nexport default {\n  binary,\n  extractBits,\n  parseSimpleflake,\n  SIMPLEFLAKE_EPOCH,\n  simpleflake,\n  SimpleflakeStruct,\n};\n"]}