Spaces:
Sleeping
Sleeping
File size: 1,294 Bytes
3c22061 7f9220c 3c22061 7f9220c 3c22061 7f9220c 3c22061 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | import { randomBytes } from 'node:crypto';
const ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
const TIME_LEN = 10;
const RANDOM_LEN = 16;
function encodeTime(ms: number): string {
let out = '';
let t = ms;
for (let i = 0; i < TIME_LEN; i++) {
out = ENCODING[t % 32] + out;
t = Math.floor(t / 32);
}
return out;
}
function randomDigits(): number[] {
const bytes = randomBytes(RANDOM_LEN);
return Array.from(bytes, (b) => b % 32);
}
function incrementDigits(digits: number[]): void {
for (let i = digits.length - 1; i >= 0; i--) {
if (digits[i] < 31) {
digits[i]++;
return;
}
digits[i] = 0;
}
throw new Error('ULID random component overflow');
}
/**
* Returns a monotonic ULID generator: ids created in the same millisecond
* strictly increase, so lexical order equals creation order within a process.
*/
export function createUlidFactory(now: () => number = Date.now): () => string {
let lastTime = -1;
let lastRandom: number[] | null = null;
return () => {
const t = Math.floor(now());
if (lastRandom !== null && t <= lastTime) {
incrementDigits(lastRandom);
} else {
lastTime = t;
lastRandom = randomDigits();
}
return encodeTime(lastTime) + lastRandom.map((d) => ENCODING[d]).join('');
};
}
export const ulid = createUlidFactory();
|