diff --git a/index.esm.js b/index.esm.js new file mode 100644 index 0000000..efa197b --- /dev/null +++ b/index.esm.js @@ -0,0 +1,21 @@ +/** + * cuid.js + * Collision-resistant UID generator for browsers and node. + * Sequential for fast db lookups and recency sorting. + * Safe for element IDs and server-side lookups. + * + * Extracted from CLCTR + * + * Copyright (c) Eric Elliott 2012 + * MIT License + */ + +import fingerprint from '#fingerprint'; +import createCuid from './lib/cuid'; +import isCuid from './lib/is-cuid'; + +const cuid = createCuid(fingerprint); + +export { fingerprint, isCuid }; + +export default cuid; diff --git a/index.js b/index.js index 609c515..4e16a47 100644 --- a/index.js +++ b/index.js @@ -10,52 +10,9 @@ * MIT License */ -var fingerprint = require('./lib/fingerprint.js'); -var isCuid = require('./lib/is-cuid.js'); -var pad = require('./lib/pad.js'); +import fingerprint from './lib/fingerprint'; +import createCuid from './lib/cuid'; -var c = 0, - blockSize = 4, - base = 36, - discreteValues = Math.pow(base, blockSize); +const cuid = createCuid(fingerprint); -function randomBlock () { - return pad((Math.random() * - discreteValues << 0) - .toString(base), blockSize); -} - -function safeCounter () { - c = c < discreteValues ? c : 0; - c++; // this is not subliminal - return c - 1; -} - -function cuid () { - // Starting with a lowercase letter makes - // it HTML element ID friendly. - var letter = 'c', // hard-coded allows for sequential access - - // timestamp - // warning: this exposes the exact date and time - // that the uid was created. - timestamp = new Date().getTime().toString(base), - - // Prevent same-machine collisions. - counter = pad(safeCounter().toString(base), blockSize), - - // A few chars to generate distinct ids for different - // clients (so different computers are far less - // likely to generate the same id) - print = fingerprint(), - - // Grab some more chars from Math.random() - random = randomBlock() + randomBlock(); - - return letter + timestamp + counter + print + random; -} - -cuid.fingerprint = fingerprint; -cuid.isCuid = isCuid; - -module.exports = cuid; +export default cuid; diff --git a/lib/cuid.js b/lib/cuid.js new file mode 100644 index 0000000..2c539bf --- /dev/null +++ b/lib/cuid.js @@ -0,0 +1,64 @@ +/** + * cuid.js + * Collision-resistant UID generator for browsers and node. + * Sequential for fast db lookups and recency sorting. + * Safe for element IDs and server-side lookups. + * + * Extracted from CLCTR + * + * Copyright (c) Eric Elliott 2012 + * MIT License + */ + +import isCuid from './is-cuid'; +import pad from './pad'; + +export default function createCuid (fingerprint) { + const blockSize = 4, + base = 36, + discreteValues = Math.pow(base, blockSize); + + let c = 0; + + function randomBlock () { + return pad((Math.random() * + discreteValues << 0) + .toString(base), blockSize); + } + + function safeCounter () { + c = c < discreteValues ? c : 0; + c++; // this is not subliminal + return c - 1; + } + + function cuid () { + // Starting with a lowercase letter makes + // it HTML element ID friendly. + var letter = 'c', // hard-coded allows for sequential access + + // timestamp + // warning: this exposes the exact date and time + // that the uid was created. + timestamp = new Date().getTime().toString(base), + + // Prevent same-machine collisions. + counter = pad(safeCounter().toString(base), blockSize), + + // A few chars to generate distinct ids for different + // clients (so different computers are far less + // likely to generate the same id) + print = fingerprint(), + + // Grab some more chars from Math.random() + random = randomBlock() + randomBlock(); + + return letter + timestamp + counter + print + random; + } + + cuid.fingerprint = fingerprint; + cuid.isCuid = isCuid; + + return cuid; +} + diff --git a/lib/fingerprint.browser.js b/lib/fingerprint.browser.js index 048874e..6702307 100644 --- a/lib/fingerprint.browser.js +++ b/lib/fingerprint.browser.js @@ -1,4 +1,4 @@ -var pad = require('./pad.js'); +import pad from './pad'; var env = typeof window === 'object' ? window : self; var globalCount = 0; @@ -10,6 +10,6 @@ var clientId = pad((mimeTypesLength + navigator.userAgent.length).toString(36) + globalCount.toString(36), 4); -module.exports = function fingerprint () { +export default function fingerprint () { return clientId; -}; +} diff --git a/lib/fingerprint.js b/lib/fingerprint.js index e467b56..5112538 100644 --- a/lib/fingerprint.js +++ b/lib/fingerprint.js @@ -1,5 +1,5 @@ -var pad = require('./pad.js'); -var os = require('os'); +import pad from './pad'; +import os from 'os'; function getHostname () { try { @@ -30,6 +30,6 @@ var padding = 2, .toString(36), padding); -module.exports = function fingerprint () { +export default function fingerprint () { return pid + hostId; -}; +} diff --git a/lib/fingerprint.react-native.js b/lib/fingerprint.react-native.js index e6bb642..9668233 100644 --- a/lib/fingerprint.react-native.js +++ b/lib/fingerprint.react-native.js @@ -1,8 +1,8 @@ -var pad = require('./pad.js'); +import pad from './pad'; var globalCount = Object.keys(global); var clientId = pad(globalCount.toString(36), 4); -module.exports = function fingerprint () { +export default function fingerprint () { return clientId; -}; +} diff --git a/lib/is-cuid.js b/lib/is-cuid.js index db7d8f4..c7218dd 100644 --- a/lib/is-cuid.js +++ b/lib/is-cuid.js @@ -3,6 +3,6 @@ * @param {unknown} value * @returns */ -module.exports = function isCuid (value) { +export default function isCuid (value) { return typeof value === 'string' && (/^c[a-z0-9]{20,32}$/).test(value); -}; +} diff --git a/lib/pad.js b/lib/pad.js index cba5716..1765436 100644 --- a/lib/pad.js +++ b/lib/pad.js @@ -1,4 +1,4 @@ -module.exports = function pad (num, size) { +export default function pad (num, size) { var s = '000000000' + num; return s.substr(s.length - size); -}; +} diff --git a/package.json b/package.json index 009efe9..5d3855f 100644 --- a/package.json +++ b/package.json @@ -6,13 +6,29 @@ "name": "Bugsnag", "url": "https://bugsnag.com" }, - "main": "index.js", + "main": "dist/index.js", "types": "cuid.d.ts", + "exports": { + ".": { + "import": "./index.esm.js", + "require": "./dist/index.js" + }, + "./lib/fingerprint": { + "browser": "./lib/fingerprint.browser.js", + "node": "./lib/fingerprint.js" + } + }, + "imports": { + "#fingerprint": { + "browser": "./lib/fingerprint.browser.js", + "node": "./lib/fingerprint.js" + } + }, "browser": { - "./lib/fingerprint.js": "./lib/fingerprint.browser.js" + "./dist/lib/fingerprint.js": "./dist/lib/fingerprint.browser.js" }, "react-native": { - "./lib/fingerprint.js": "./lib/fingerprint.react-native.js" + "./dist/lib/fingerprint.js": "./dist/lib/fingerprint.react-native.js" }, "keywords": [ "id", @@ -27,12 +43,13 @@ }, "files": [ "lib", + "dist", "cuid.d.ts", - "index.js" + "index.esm.js" ], "license": "MIT", "devDependencies": { - "browserify": "17.0.0", + "@rollup/plugin-alias": "^5.1.1", "eslint": "^8.49", "jasmine": "^2.5.0", "jasmine-core": "^2.8.0", @@ -41,12 +58,13 @@ "karma-chrome-launcher": "^2.2.0", "karma-jasmine": "^1.1.1", "mkdirp": "^0.5.1", - "uglify-js": "^2.7.4", + "rollup": "^2.76.0", "watchify": "^4.0.0", "webworkify": "^1.4.0" }, "scripts": { - "build": "mkdirp dist && browserify index.js -s cuid -o dist/cuid.js && uglifyjs dist/cuid.js -c -m -o dist/cuid.min.js", + "prebuild": "rm -rf dist", + "build": "rollup -c", "lint": "eslint index.js lib test", "test": "npm run lint && npm run test:server && npm run test:browser", "test:browser": "karma start test/karma.conf.js", diff --git a/rollup.config.mjs b/rollup.config.mjs new file mode 100644 index 0000000..efc0c0d --- /dev/null +++ b/rollup.config.mjs @@ -0,0 +1,31 @@ +const sharedOutput = { + format: 'cjs', + dir: 'dist', + preserveModules: true, + exports: 'default', + generatedCode: { + preset: 'es2015' + } +}; + +export default [ + { + external: ['os'], + input: 'index.js', + output: sharedOutput + }, + { + input: 'lib/fingerprint.browser.js', + output: { + ...sharedOutput, + dir: 'dist/lib' + } + }, + { + input: 'lib/fingerprint.react-native.js', + output: { + ...sharedOutput, + dir: 'dist/lib' + } + } +];