diff --git a/.taskcluster.yml b/.taskcluster.yml index 1c80e40..839cf32 100644 --- a/.taskcluster.yml +++ b/.taskcluster.yml @@ -14,18 +14,28 @@ tasks: environments: - image: node:6 description: Run tests with node v6 + command: npm test - image: node:8 description: Run tests with node v8 + command: npm test - image: node:10 description: Run tests with node v10 + command: npm test - image: node:12 description: Run tests with node v12 + command: npm test - image: node:14 description: Run tests with node v14 + command: npm test - image: node:16 description: Run tests with node v16 + command: npm test - image: node:latest description: Run tests with latest node + command: npm test + - image: node:latest + description: Run tests with latest node without Buffer + command: npm run test-nobuffer in: $if: tasks_for == "github-pull-request" && event["action"] in ["opened","reopened","synchronize"] then: @@ -57,4 +67,4 @@ tasks: git config advice.detachedHead false && git checkout --no-progress ${head_rev} && npm install --no-progress . && - npm test + ${env.command} diff --git a/package.json b/package.json index ac10519..b1683a7 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "description": "URL-safe base64 UUID encoder for generating 22 character slugs", "license": "MIT", "scripts": { - "test": "nodeunit slugid_test.js" + "test": "nodeunit slugid_test.js", + "test-nobuffer": "NO_BUFFER=1 npm test" }, "repository": { "type": "git", diff --git a/slugid.js b/slugid.js index 5d1d69f..e90ceee 100644 --- a/slugid.js +++ b/slugid.js @@ -22,13 +22,29 @@ var uuid = require('uuid'); +/** @type {(bytes: Uint8Array) => string} */ +var toBase64 = (() => { + if (typeof Buffer !== 'undefined') { + return (bytes) => Buffer.from(bytes).toString('base64'); + } + return (bytes) => btoa(String.fromCharCode(...bytes)); +})(); + +/** @type {(base64: string) => Uint8Array | Buffer} */ +var fromBase64 = (() => { + if (typeof Buffer !== 'undefined') { + return (base64) => Buffer.from(base64, 'base64'); + } + return (base64) => Uint8Array.from(atob(base64), c => c.charCodeAt(0)); +})(); + /** * Returns the given uuid as a 22 character slug. This can be a regular v4 * slug or a "nice" slug. */ exports.encode = function(uuid_) { var bytes = uuid.parse(uuid_); - var base64 = Buffer.from(bytes).toString('base64'); + var base64 = toBase64(bytes); var slug = base64 .replace(/\+/g, '-') // Replace + with - (see RFC 4648, sec. 5) .replace(/\//g, '_') // Replace / with _ (see RFC 4648, sec. 5) @@ -44,15 +60,15 @@ exports.decode = function(slug) { .replace(/-/g, '+') .replace(/_/g, '/') + '=='; - return uuid.stringify(Buffer.from(base64, 'base64')); + return uuid.stringify(fromBase64(base64)); }; /** * Returns a randomly generated uuid v4 compliant slug */ exports.v4 = function() { - var bytes = uuid.v4(null, Buffer.alloc(16)); - var base64 = bytes.toString('base64'); + var bytes = uuid.v4(null, new Uint8Array(16)); + var base64 = toBase64(bytes); var slug = base64 .replace(/\+/g, '-') // Replace + with - (see RFC 4648, sec. 5) .replace(/\//g, '_') // Replace / with _ (see RFC 4648, sec. 5) @@ -72,9 +88,9 @@ exports.v4 = function() { * restrict the range of potential uuids that may be generated. */ exports.nice = function() { - var bytes = uuid.v4(null, Buffer.alloc(16)); + var bytes = uuid.v4(null, new Uint8Array(16)); bytes[0] = bytes[0] & 0x7f; // unset first bit to ensure [A-Za-f] first char - var base64 = bytes.toString('base64'); + var base64 = toBase64(bytes); var slug = base64 .replace(/\+/g, '-') // Replace + with - (see RFC 4648, sec. 5) .replace(/\//g, '_') // Replace / with _ (see RFC 4648, sec. 5) diff --git a/slugid_test.js b/slugid_test.js index 00ae745..c555af7 100644 --- a/slugid_test.js +++ b/slugid_test.js @@ -20,6 +20,12 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Allows the tests to be run in environments with and without `Buffer`. +if (process.env.NO_BUFFER === "1") { + delete global.Buffer; + console.log('\x1b[33m' + 'Removed `Buffer` from globalThis.' + '\x1b[0m'); +} + var slugid = require('./slugid'); var uuidv4 = require('uuid').v4;