31 lines
742 B
TypeScript
31 lines
742 B
TypeScript
import { randomBytes } from 'node:crypto';
|
|
|
|
const ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
|
|
|
export function generateId(): string {
|
|
const now = Date.now();
|
|
const time = encodeBase32(now, 10);
|
|
let random = '';
|
|
const bytes = randomBytes(16);
|
|
let value = 0;
|
|
let bits = 0;
|
|
for (const byte of bytes) {
|
|
value = (value << 8) | byte;
|
|
bits += 8;
|
|
while (bits >= 5 && random.length < 16) {
|
|
random += ENCODING[(value >>> (bits - 5)) & 31];
|
|
bits -= 5;
|
|
}
|
|
}
|
|
return time + random.padEnd(16, '0');
|
|
}
|
|
|
|
function encodeBase32(num: number, length: number): string {
|
|
let out = '';
|
|
for (let i = length - 1; i >= 0; i--) {
|
|
out = ENCODING[num % 32] + out;
|
|
num = Math.floor(num / 32);
|
|
}
|
|
return out;
|
|
}
|