{"version":3,"file":"snowflake.mjs","names":[],"sources":["../src/snowflake.ts"],"sourcesContent":["/**\n * A distributed unique ID generator inspired by Twitter's Snowflake.\n *\n * ID data bits:\n * +----------------------+----------------+-----------+\n * |  delta millisecond   |   machine id   | sequence  |\n * +----------------------+----------------+-----------+\n * |        41bits        |     10bits     |   12bits  |\n * +----------------------+----------------+-----------+\n *\n */\n\nfunction getNextMillisecond(timestamp: bigint) {\n  let now = BigInt(Date.now());\n  while (now < timestamp) {\n    now = BigInt(Date.now());\n  }\n  return now;\n}\n\nexport class UidGenerator {\n  public readonly MAX = (1n << 63n) - 1n;\n  private readonly machineBits = BigInt(10);\n  private readonly sequenceBits = BigInt(12);\n  private readonly epochMillisecond = BigInt(1577808000000); // 2020-1-1 00:00:00\n  private readonly sequenceMask = ~(BigInt(-1) << this.sequenceBits);\n  private readonly maxMachineId = ~(BigInt(-1) << this.machineBits);\n  private readonly machineIdShift = this.sequenceBits;\n  private readonly timeStampShift = this.machineBits + this.sequenceBits;\n  private readonly machineId: bigint;\n  private sequence = BigInt(0);\n  private lastTimestamp = BigInt(-1);\n\n  constructor(mackineId: number) {\n    this.machineId = BigInt(mackineId) % this.maxMachineId;\n  }\n\n  public readonly next = (): bigint => {\n    let timestamp = BigInt(Date.now());\n    if (timestamp < this.lastTimestamp) {\n      console.error(`Clock moved backwards. time gap = ${this.lastTimestamp - timestamp}`);\n      timestamp = getNextMillisecond(this.lastTimestamp);\n    }\n    if (timestamp === this.lastTimestamp) {\n      this.sequence = (this.sequence + BigInt(1)) & this.sequenceMask;\n      if (this.sequence === BigInt(0)) {\n        timestamp = getNextMillisecond(timestamp);\n      }\n    } else {\n      this.sequence = BigInt(0);\n    }\n    this.lastTimestamp = timestamp;\n    return (\n      ((timestamp - this.epochMillisecond) << this.timeStampShift) |\n      (this.machineId << this.machineIdShift) |\n      this.sequence\n    );\n  };\n}\n\nconst machineId = Math.floor(Math.random() * 1024);\nexport const uid = new UidGenerator(machineId);\n"],"mappings":";;;;;;;;;;;;AAYA,SAAS,mBAAmB,WAAmB;CAC7C,IAAI,MAAM,OAAO,KAAK,IAAI,CAAC;CAC3B,OAAO,MAAM,WACX,MAAM,OAAO,KAAK,IAAI,CAAC;CAEzB,OAAO;AACT;AAEA,IAAa,eAAb,MAA0B;CACxB,OAAuB,MAAM,OAAO;CACpC,cAA+B,OAAO,EAAE;CACxC,eAAgC,OAAO,EAAE;CACzC,mBAAoC,OAAO,SAAa;CACxD,eAAgC,EAAE,OAAO,EAAE,KAAK,KAAK;CACrD,eAAgC,EAAE,OAAO,EAAE,KAAK,KAAK;CACrD,iBAAkC,KAAK;CACvC,iBAAkC,KAAK,cAAc,KAAK;CAC1D;CACA,WAAmB,OAAO,CAAC;CAC3B,gBAAwB,OAAO,EAAE;CAEjC,YAAY,WAAmB;EAC7B,KAAK,YAAY,OAAO,SAAS,IAAI,KAAK;CAC5C;CAEA,aAAqC;EACnC,IAAI,YAAY,OAAO,KAAK,IAAI,CAAC;EACjC,IAAI,YAAY,KAAK,eAAe;GAClC,QAAQ,MAAM,qCAAqC,KAAK,gBAAgB,WAAW;GACnF,YAAY,mBAAmB,KAAK,aAAa;EACnD;EACA,IAAI,cAAc,KAAK,eAAe;GACpC,KAAK,WAAY,KAAK,WAAW,OAAO,CAAC,IAAK,KAAK;GACnD,IAAI,KAAK,aAAa,OAAO,CAAC,GAC5B,YAAY,mBAAmB,SAAS;EAE5C,OACE,KAAK,WAAW,OAAO,CAAC;EAE1B,KAAK,gBAAgB;EACrB,OACI,YAAY,KAAK,oBAAqB,KAAK,iBAC5C,KAAK,aAAa,KAAK,iBACxB,KAAK;CAET;AACF;AAGA,MAAa,MAAM,IAAI,aADL,KAAK,MAAM,KAAK,OAAO,IAAI,IACT,CAAS"}