@tldraw/utils
Version:
tldraw infinite canvas SDK (private utilities).
8 lines (7 loc) • 5.33 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../src/lib/id.ts"],
"sourcesContent": ["/*!\n * MIT License: https://github.com/ai/nanoid/blob/main/LICENSE\n * Modified code originally from <https://github.com/ai/nanoid>\n * Copyright 2017 Andrey Sitnik <andrey@sitnik.ru>\n *\n * `nanoid` is currently only distributed as an ES module. Some tools (jest, playwright) don't\n * properly support ESM-only code yet, and tldraw itself is distributed as both an ES module and a\n * CommonJS module. By including nanoid here, we can make sure it works well in every environment\n * where tldraw is used. We can also remove some unused features like custom alphabets.\n */\n\n// all environments that tldraw runs in (browser, workers, recent node versions) have global\n// `crypto`\nconst crypto = globalThis.crypto\n\n// This alphabet uses `A-Za-z0-9_-` symbols.\n// The order of characters is optimized for better gzip and brotli compression.\n// Same as in non-secure/index.js\nconst urlAlphabet = 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\n\n// It is best to make fewer, larger requests to the crypto module to\n// avoid system call overhead. So, random numbers are generated in a\n// pool. The pool is a Buffer that is larger than the initial random\n// request size by this multiplier. The pool is enlarged if subsequent\n// requests exceed the maximum buffer size.\nconst POOL_SIZE_MULTIPLIER = 128\nlet pool: Uint8Array, poolOffset: number\n\nfunction fillPool(bytes: number) {\n\tif (!pool || pool.length < bytes) {\n\t\tpool = new Uint8Array(bytes * POOL_SIZE_MULTIPLIER)\n\t\tcrypto.getRandomValues(pool)\n\t\tpoolOffset = 0\n\t} else if (poolOffset + bytes > pool.length) {\n\t\tcrypto.getRandomValues(pool)\n\t\tpoolOffset = 0\n\t}\n\tpoolOffset += bytes\n}\n\nfunction nanoid(size = 21) {\n\t// `-=` convert `size` to number to prevent `valueOf` abusing\n\tfillPool((size -= 0))\n\tlet id = ''\n\t// We are reading directly from the random pool to avoid creating new array\n\tfor (let i = poolOffset - size; i < poolOffset; i++) {\n\t\t// It is incorrect to use bytes exceeding the alphabet size.\n\t\t// The following mask reduces the random byte in the 0-255 value\n\t\t// range to the 0-63 value range. Therefore, adding hacks, such\n\t\t// as empty string fallback or magic numbers, is unnecessary because\n\t\t// the bitmask trims bytes down to the alphabet size.\n\t\tid += urlAlphabet[pool[i] & 63]\n\t}\n\treturn id\n}\n\nlet impl = nanoid\n/**\n * Mock the unique ID generator with a custom implementation for testing.\n *\n * Replaces the internal ID generation function with a custom one. This is useful\n * for testing scenarios where you need predictable or deterministic IDs.\n *\n * @param fn - The mock function that should return a string ID. Takes optional size parameter.\n * @example\n * ```ts\n * // Mock with predictable IDs for testing\n * mockUniqueId((size = 21) => 'test-id-' + size)\n * console.log(uniqueId()) // 'test-id-21'\n * console.log(uniqueId(10)) // 'test-id-10'\n *\n * // Restore original implementation when done\n * restoreUniqueId()\n * ```\n * @internal\n */\nexport function mockUniqueId(fn: (size?: number) => string) {\n\timpl = fn\n}\n\n/**\n * Restore the original unique ID generator after mocking.\n *\n * Resets the ID generation function back to the original nanoid implementation.\n * This should be called after testing to restore normal ID generation behavior.\n *\n * @example\n * ```ts\n * // After mocking for tests\n * mockUniqueId(() => 'mock-id')\n *\n * // Restore original behavior\n * restoreUniqueId()\n * console.log(uniqueId()) // Now generates real random IDs again\n * ```\n * @internal\n */\nexport function restoreUniqueId() {\n\timpl = nanoid\n}\n\n/**\n * Generate a unique ID using a modified nanoid algorithm.\n *\n * Generates a cryptographically secure random string ID using URL-safe characters.\n * The default size is 21 characters, which provides a good balance of uniqueness\n * and brevity. Uses the global crypto API for secure random number generation.\n *\n * @param size - Optional length of the generated ID (defaults to 21 characters)\n * @returns A unique string identifier\n * @example\n * ```ts\n * // Generate default 21-character ID\n * const id = uniqueId()\n * console.log(id) // 'V1StGXR8_Z5jdHi6B-myT'\n *\n * // Generate shorter ID\n * const shortId = uniqueId(10)\n * console.log(shortId) // 'V1StGXR8_Z'\n *\n * // Generate longer ID\n * const longId = uniqueId(32)\n * console.log(longId) // 'V1StGXR8_Z5jdHi6B-myTVKahvjdx...'\n * ```\n * @public\n */\nexport function uniqueId(size?: number): string {\n\treturn impl(size)\n}\n"],
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAaA,MAAM,SAAS,WAAW;AAK1B,MAAM,cAAc;AAOpB,MAAM,uBAAuB;AAC7B,IAAI,MAAkB;AAEtB,SAAS,SAAS,OAAe;AAChC,MAAI,CAAC,QAAQ,KAAK,SAAS,OAAO;AACjC,WAAO,IAAI,WAAW,QAAQ,oBAAoB;AAClD,WAAO,gBAAgB,IAAI;AAC3B,iBAAa;AAAA,EACd,WAAW,aAAa,QAAQ,KAAK,QAAQ;AAC5C,WAAO,gBAAgB,IAAI;AAC3B,iBAAa;AAAA,EACd;AACA,gBAAc;AACf;AAEA,SAAS,OAAO,OAAO,IAAI;AAE1B,WAAU,QAAQ,CAAE;AACpB,MAAI,KAAK;AAET,WAAS,IAAI,aAAa,MAAM,IAAI,YAAY,KAAK;AAMpD,UAAM,YAAY,KAAK,CAAC,IAAI,EAAE;AAAA,EAC/B;AACA,SAAO;AACR;AAEA,IAAI,OAAO;AAoBJ,SAAS,aAAa,IAA+B;AAC3D,SAAO;AACR;AAmBO,SAAS,kBAAkB;AACjC,SAAO;AACR;AA2BO,SAAS,SAAS,MAAuB;AAC/C,SAAO,KAAK,IAAI;AACjB;",
"names": []
}