deno.land / x / uuid7@v0.0.1 / mod.ts
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156/** * Generate a UUIDv7. * * ## Options * * To generate a UUID at a specific time, you can pass a `number` timestamp or * `Date` object to this function. * * You can also further customize UUID generation by providing * {@link GenerateOptions an object} with your preferences: * * - `time`: Generate with this time instead of the current system time. You can * provide a `number` millisecond-precision UNIX timestamp (as `Date.now` * returns), a Date object, or a function returning a `number` timestamp. * - `dashes`: `true` to include `-` characters in the generated UUID string; * `false` to omit them. (default: `true`) * - `upper`: Capitalize the A-F characters in the UUID. (default: `false`) * - `version`: The value of the UUID `version` field (default: `7`) * - `entropy`: A function to generate the random part of the UUID. Must return * a `Uint8Array` containing 10 bytes. * (default: uses `crypto.getRandomValues`) */export const v7: Generator = (opt?: Clock | Time | GenerateOptions | null): string => { const time = getTime(opt); let dashes = true; let upper = false; let version = 7 << 4; let rand: () => Uint8Array = defaultEntropy;
if (typeof opt === 'object' && opt !== null && !(opt instanceof Date)) { if (opt.dashes != null) dashes = opt.dashes; if (opt.version != null) version = (opt.version & 0x0f) << 4; if (opt.upper != null) upper = opt.upper; if (opt.entropy != null) rand = opt.entropy; }
let timestamp = hex(time, 12); if (dashes) timestamp = timestamp.slice(0, 8) + '-' + timestamp.slice(8);
const suffixBytes: string[] = Array(10); rand().forEach((b, i) => { if (i === 0) { b = version | (b & 0x0f); } else if (i === 2) { b = variant | (b & 0x3f); } suffixBytes[i] = hex(b); });
const suffix = suffixBytes.join('');
const id = dashes ? `${timestamp}-${suffix.slice(0, 4)}-${suffix.slice(4, 8)}-${suffix.slice(8)}` : timestamp + suffix;
return upper ? id.toUpperCase() : id;};
export default v7;
/** * Return the timestamp portion of the UUID (a millisecond-precision UNIX * timestamp, as returned by `Date.now`). * * Throws a {@link ParseError} if no timestamp can be extracted. */export const timestamp = (uuid: string): number => { const match = pattern.exec(uuid); if (match == null) throw new ParseError('Invalid v7 UUID; cannot determine timestamp');
const ts = match[1].replace('-', ''); return parseInt(ts, 16);};
/** * A regular expression that recognizes UUID's generated by this package. * * Capture group `1` is the timestamp portion, and `2` is the random portion * (including the 2-bit constant UUID variant field). */export const pattern = /^([0-9a-f]{8}-?[0-9a-f]{4})-?7([0-9a-f]{3}-?[0-9a-f]{4}-?[0-9a-f]{12})$/i;
/** The type of {@link v7 the UUID function} of this package. */export interface Generator { /** Generate a UUIDv7 with default options. */ (): string;
/** Generate a UUIDv7 using the given time as its timestamp. */ (time: Clock | Time | null | undefined): string;
/** Generate a UUIDv7 using the given {@link GenerateOptions options}. */ (options: GenerateOptions): string;}
/** * A function that returns a millisecond-precision UNIX timestamp, like * `Date.now`. */export type Clock = typeof Date['now'];
/** A `Date` object or millisecond-precision UNIX timestamp. */export type Time = number | Date;
/** {@link v7 UUID generation} options. */export interface GenerateOptions { /** * Set the timestamp portion of the UUID to the given `Date`, UNIX timestamp * (as returned by `Date.now`), or the timestamp returned by the given * {@link Clock clock function}. */ time?: Clock | Time;
/** * `true` to include dashes in the UUID; `false` to omit them. * (default: `true`) */ dashes?: boolean;
/** Capitalize the A-F characters in the UUID. (default: `false`) */ upper?: boolean;
/** Set the version field of the UUID. (default: `8`) */ version?: 7 | 8;
/** * Generate the random part of the UUID. The returned `Uint8Array` must be at * least 10 bytes long. */ entropy?: () => Uint8Array;}
/** The exception thrown by {@link timestamp} if UUID parsing fails. */export class ParseError extends Error { public readonly name = 'ParseError';}
const getTime = (time: Clock | Time | GenerateOptions | null | undefined): number => { if (time == null) return Date.now(); if (typeof time === 'number') return time; if (time instanceof Date) return +time; if (typeof time === 'function') return time(); return getTime(time.time);};
const hex = (n: number, width = 2) => pad(n.toString(16), width);
const pad = (text: string, width: number) => { const remainder = width - text.length; return remainder > 0 ? '0'.repeat(remainder) + text : text;};
const defaultEntropy = (): Uint8Array => crypto.getRandomValues(new Uint8Array(10));
const variant = 2 << 6;
Version Info