Generate CUIDs in Typescript

Resources  |  Generate CUIDs in Typescript

Generating a CUID (Collision-resistant Unique Identifier) in TypeScript involves using techniques such as the current timestamp, a counter, a machine fingerprint, and randomness. Below is an example implementation of generating a CUID in TypeScript.

Steps to Generate a CUID in TypeScript

  1. Timestamp: Get the current timestamp in milliseconds.
  2. Counter: Use a counter to handle multiple CUIDs generated in a short period.
  3. Fingerprint: Generate a machine-specific fingerprint.
  4. Randomness: Add random characters to further reduce the risk of collisions.
  5. Base36 Encoding: Encode the components using Base36 for readability.

Example Code

Here's a TypeScript implementation to generate a CUID:

import * as crypto from 'crypto';

const BASE36_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz';

function encodeBase36(value: number): string {
    if (value === 0) {
        return '0';
    }
    let result = '';
    while (value > 0) {
        result = BASE36_CHARS.charAt(value % 36) + result;
        value = Math.floor(value / 36);
    }
    return result.padStart(8, '0');
}

function getMachineFingerprint(): string {
    try {
        const hostname = require('os').hostname();
        const hash = crypto.createHash('md5').update(hostname).digest('hex');
        return hash.substring(0, 4);
    } catch (error) {
        return '0000';
    }
}

function getRandomString(length: number): string {
    let result = '';
    for (let i = 0; i < length; i++) {
        result += BASE36_CHARS.charAt(Math.floor(Math.random() * BASE36_CHARS.length));
    }
    return result;
}

function generateCUID(): string {
    const timestamp = Date.now();

    let counter = 0;
    let lastTimestamp = 0;

    if (timestamp === lastTimestamp) {
        counter++;
    } else {
        lastTimestamp = timestamp;
        counter = 0;
    }

    const timestampBase36 = encodeBase36(timestamp);
    const counterBase36 = encodeBase36(counter);
    const fingerprint = getMachineFingerprint();
    const randomString = getRandomString(4);

    return `c${timestampBase36}${counterBase36}${fingerprint}${randomString}`;
}

// Example usage
console.log(generateCUID());

Explanation

  1. Base36 Encoding:

    • The encodeBase36 function converts a number to a Base36 encoded string, ensuring it is padded to 8 characters.
  2. Timestamp:

    • Date.now() gets the current timestamp in milliseconds.
  3. Counter:

    • A counter (counter) and a variable to track the last timestamp (lastTimestamp) are used to handle multiple CUIDs generated within the same millisecond.
  4. Machine Fingerprint:

    • getMachineFingerprint fetches the machine's hostname, computes an MD5 hash, and returns the first 4 characters of the hash.
  5. Random String:

    • getRandomString generates a random string of specified length (4 characters) using characters from BASE36_CHARS.
  6. Combine Components:

    • The generateCUID function combines the timestamp, counter, fingerprint, and random parts to form the final CUID.

Summary

This TypeScript implementation of CUID generation uses built-in modules (crypto for hashing and os for hostname retrieval) and standard JavaScript functionalities to handle timestamps, hashing, randomness, and counters. This approach ensures that the generated CUIDs are unique, readable, and collision-resistant, suitable for various applications. Adjustments can be made based on specific requirements, such as handling errors when fetching the machine's hostname or modifying the length of the random string portion.