From b3931a73ff2f53355a47472810eb5b49cec23f69 Mon Sep 17 00:00:00 2001 From: Samuel Rouse Date: Tue, 30 Apr 2024 13:37:27 -0400 Subject: [PATCH 1/5] Implement uuid25 support --- README.md | 12 ++++--- index.d.ts | 7 ++-- index.js | 14 ++++---- test/index.js | 27 ++++++++++++--- test/uuid25examples.js | 74 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 115 insertions(+), 19 deletions(-) create mode 100644 test/uuid25examples.js diff --git a/README.md b/README.md index b0e6f0d..e72d6a6 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ Generate and translate standard UUIDs into shorter - or just *different* - formats and back. - -## v5.0.1 -5.0.1 corrects node support in the `engine` section of `package.json`. +## v5.1.0 +5.1.0 adds translation support for the [uuid25](https://github.com/uuid25/javascript) (Base36) format +with the `uuid25Base36` constant. ### Major Changes in 5.0.0 - 🛑 5.0.0 drops support for Node 10 and 12. @@ -61,8 +61,9 @@ translator.alphabet; translator.maxLength; // View the constants -short.constants.flickrBase58; // Avoids similar characters (0/O, 1/I/l, etc.) short.constants.cookieBase90; // Safe for HTTP cookies values for smaller IDs. +short.constants.flickrBase58; // Avoids similar characters (0/O, 1/I/l, etc.) +short.constants.uuid25Base36; // The uuid25 (string length 25) format ``` ### Options @@ -86,7 +87,7 @@ translator.new(); // mhvXdrZT4jP5T8vBxuvm75 ## Support -short-uuid [5.0.0](https://github.com/oculus42/short-uuid/blob/v5.0.0/README.md) +short-uuid [5.x](https://github.com/oculus42/short-uuid/blob/v5.1.0/README.md) and later is tested on Node 14.x and later. short-uuid [4.x](https://github.com/oculus42/short-uuid/blob/v3.2.2/README.md) @@ -106,6 +107,7 @@ TypeScript definitions are included, thanks to [alexturek](https://github.com/alexturek). ## Previous Release Note Highlights +5.0.0 drops support for Node 12 and below. 4.1.0 adds a maxLength value to translators for reference 4.0.1 adds consistent length translation and throws an error if provided an invalid alphabet. 3.1.1 removed Node 4.x tests. Last included Browserify distribution. diff --git a/index.d.ts b/index.d.ts index 2c23313..50eae89 100644 --- a/index.d.ts +++ b/index.d.ts @@ -7,12 +7,13 @@ declare module 'short-uuid' { namespace shortUUID { export const constants: { - flickrBase58: string; cookieBase90: string; + flickrBase58: string; + uuid25Base36: string; }; - export type UUID = string & { _guidBrand: 'short-uuid' }; - export type SUUID = string & { _guidBrand: 'uuid' }; + export type UUID = string & { _guidBrand: 'uuid' }; + export type SUUID = string & { _guidBrand: 'short-uuid' }; /** Generate a new regular UUID. */ export function uuid(): UUID; diff --git a/index.js b/index.js index c52e7b4..d915ff1 100644 --- a/index.js +++ b/index.js @@ -3,11 +3,12 @@ * Simple wrapper functions to produce shorter UUIDs for cookies, maybe everything? */ -const { v4: uuidv4 } = require('uuid'); +const { v4: uuidV4 } = require('uuid'); const anyBase = require('any-base'); -const flickrBase58 = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'; const cookieBase90 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&'()*+-./:<=>?@[]^_`{|}~"; +const flickrBase58 = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'; +const uuid25Base36 = '0123456789abcdefghijklmnopqrstuvwxyz'; const baseOptions = { consistentLength: true, @@ -89,12 +90,12 @@ module.exports = (() => { // UUIDs are in hex, so we translate to and from. const fromHex = anyBase(anyBase.HEX, useAlphabet); const toHex = anyBase(useAlphabet, anyBase.HEX); - const generate = () => shortenUUID(uuidv4(), fromHex, paddingParams); + const generate = () => shortenUUID(uuidV4(), fromHex, paddingParams); const translator = { new: generate, generate, - uuid: uuidv4, + uuid: uuidV4, fromUUID: (uuid) => shortenUUID(uuid, fromHex, paddingParams), toUUID: (shortUuid) => enlargeUUID(shortUuid, toHex), alphabet: useAlphabet, @@ -108,12 +109,13 @@ module.exports = (() => { // Expose the constants for other purposes. makeConvertor.constants = { - flickrBase58, cookieBase90, + flickrBase58, + uuid25Base36, }; // Expose the generic v4 UUID generator for convenience - makeConvertor.uuid = uuidv4; + makeConvertor.uuid = uuidV4; // Provide a generic generator makeConvertor.generate = () => { diff --git a/test/index.js b/test/index.js index 1e05c23..5352111 100644 --- a/test/index.js +++ b/test/index.js @@ -6,15 +6,19 @@ const test = require('tape'); const uuid = require('uuid'); const short = require('../index'); +const uuid25Tests = require('./uuid25examples'); + const b90 = short(short.constants.cookieBase90); const b58 = short(short.constants.flickrBase58); +const b36 = short(short.constants.uuid25Base36); -const cycle = (testcb) => { +const cycle = (testCallback) => { const uu = short.uuid(); const f58 = b58.fromUUID(uu); const f90 = b90.fromUUID(uu); + const f36 = b36.fromUUID(uu); - testcb(uu, f58, f90); + testCallback(uu, f58, f90, f36); }; test('short-uuid setup', (t) => { @@ -45,10 +49,11 @@ test('short-uuid setup', (t) => { }); test('constants', (t) => { - t.plan(3); + t.plan(4); t.ok(Object.prototype.hasOwnProperty.call(short, 'constants') && typeof short.constants === 'object', 'should contain a "constants" object'); t.equal(short.constants.flickrBase58, '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ', 'should contain flicker58 constant'); t.equal(short.constants.cookieBase90, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&'()*+-./:<=>?@[]^_`{|}~", 'should contain cookie90 constant'); + t.equal(short.constants.uuid25Base36, '0123456789abcdefghijklmnopqrstuvwxyz', 'should contain uuid25 constant'); }); // Operations @@ -65,14 +70,17 @@ test('should generate valid UUIDs', (t) => { }); test('should translate back from multiple bases', (t) => { - t.plan(40); + t.plan(60); - const action = (uu, f58, f90) => { + const action = (uu, f58, f90, f36) => { t.equal(b58.toUUID(f58), uu, 'Translated b58 matches original'); t.ok(uuid.validate(b58.toUUID(f58)), 'Translated UUID is valid'); t.equal(b90.toUUID(f90), uu, 'Translated b90 matches original'); t.ok(uuid.validate(b90.toUUID(f90)), 'Translated UUID is valid'); + + t.equal(b36.toUUID(f36), uu, 'Translated b36 matches original'); + t.ok(uuid.validate(b36.toUUID(f36)), 'Translated UUID is valid'); }; for (let i = 0; i < 10; i += 1) { @@ -252,6 +260,15 @@ test('generate should generate an ID with the Flickr set', (t) => { t.ok(val2, 'Generate should reuse the default translator successfully'); }); +// Test examples from https://github.com/uuid25/test_cases/blob/main/examples +test('uuid25 should be compatible with uuid25 examples', (t) => { + t.plan(uuid25Tests.length * 2); + uuid25Tests.forEach(({ uuid25, hyphenated }) => { + t.equal(b36.toUUID(uuid25), hyphenated); + t.equal(b36.fromUUID(hyphenated), uuid25); + }); +}); + test('Default generate quantity tests', (t) => { t.plan(1); let underLength = 0; diff --git a/test/uuid25examples.js b/test/uuid25examples.js new file mode 100644 index 0000000..b5d1fe1 --- /dev/null +++ b/test/uuid25examples.js @@ -0,0 +1,74 @@ +module.exports = [ + { + uuid25: '0000000000000000000000000', + hyphenated: '00000000-0000-0000-0000-000000000000', + }, + { + uuid25: 'f5lxx1zz5pnorynqglhzmsp33', + hyphenated: 'ffffffff-ffff-ffff-ffff-ffffffffffff', + }, + { + uuid25: '8j7qcpk2yebp9ouobnujfc312', + hyphenated: '90252ae1-bdee-b5e6-4549-83a13e69d556', + }, + { + uuid25: '1ixkdgkqeu8wln1vfrw6csla3', + hyphenated: '19c63717-dd78-907f-153d-c2d12a357ebb', + }, + { + uuid25: '1rt96u8g5mehk7anquaf5v0yd', + hyphenated: '1df0de92-3543-c988-6d44-6b0ef75df795', + }, + { + uuid25: '18hye57ickp5c2mg8x9w4o1ji', + hyphenated: '14e0fa56-29c7-0c0d-663f-5d326e51f1ce', + }, + { + uuid25: 'b7b5eir8qxbgpe8ofpfx0jmk4', + hyphenated: 'bd3ba1d1-ed92-4804-b900-4b6f96124cf4', + }, + { + uuid25: 'dsc6tknluzhcyoh0wbdhtfm91', + hyphenated: 'e8e1d087-617c-3a88-e8f4-789ab4a7cf65', + }, + { + uuid25: 'edzg3t2pm0tzkjolrcmvlyhtx', + hyphenated: 'f309d5b0-2bf3-a736-7400-75948ad1ffc5', + }, + { + uuid25: '1da9001w3ld329fiyf574wuk2', + hyphenated: '171fd840-f315-e732-2796-dea092d372b2', + }, + { + uuid25: 'bvdc0zy20yoipgda8sb65tczv', + hyphenated: 'c885af25-4a61-954a-1687-c08e41f9940b', + }, + { + uuid25: '3mll19wjhi37qe68vtgobt04h', + hyphenated: '3d46fe79-7828-7d4f-f1e5-7bdf80ab30e1', + }, + { + uuid25: 'dlut3j4j5hudfwua508w8h25v', + hyphenated: 'e5d7215d-6e2c-3299-1506-498b84b32d33', + }, + { + uuid25: 'bi0ifb9jmm2tig1hsdb9uol2v', + hyphenated: 'c2416789-944c-b584-e886-ac162d9112b7', + }, + { + uuid25: '0js3yf434vbqa069pkebbly89', + hyphenated: '0947fa84-3806-088a-77aa-1b1ed69b7789', + }, + { + uuid25: '42ur2gf0i7xgtnlislvutk5fq', + hyphenated: '44e76ce2-1f2e-77bd-badb-64850026fd86', + }, + { + uuid25: '6ry55bbvow6mllk9nvfsd4w5f', + hyphenated: '7275ea47-7628-0fa8-2afb-0c4b47f148c3', + }, + { + uuid25: '1xl7tld67nekvdlrp0pkvsut5', + hyphenated: '20a6bdda-fff4-faa1-4e8f-c0eb75a169f9', + }, +]; From cac43d3f6a96b4c9ff7d872acd1f965b86583e71 Mon Sep 17 00:00:00 2001 From: Samuel Rouse Date: Wed, 1 May 2024 07:47:36 -0400 Subject: [PATCH 2/5] updated CHANGELOG --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8105a18..56dfb70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [5.1.0] - 2024-04-30 +### Added +- Added `uuid25Base36` constant to support uuid25 style + ## [5.0.1] - 2024-04-30 ### Changed - Updated `engines` in `package.json` to reflect correct support (Node >=14) From 9ad09b1c7a0113437dc37bbdb4284bafaae14dc0 Mon Sep 17 00:00:00 2001 From: Samuel Rouse Date: Wed, 1 May 2024 07:52:15 -0400 Subject: [PATCH 3/5] refactor: Move constants to object --- index.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/index.js b/index.js index d915ff1..09483b1 100644 --- a/index.js +++ b/index.js @@ -6,9 +6,11 @@ const { v4: uuidV4 } = require('uuid'); const anyBase = require('any-base'); -const cookieBase90 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&'()*+-./:<=>?@[]^_`{|}~"; -const flickrBase58 = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'; -const uuid25Base36 = '0123456789abcdefghijklmnopqrstuvwxyz'; +const constants = { + cookieBase90: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&'()*+-./:<=>?@[]^_`{|}~", + flickrBase58: '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ', + uuid25Base36: '0123456789abcdefghijklmnopqrstuvwxyz', +}; const baseOptions = { consistentLength: true, @@ -68,7 +70,7 @@ module.exports = (() => { */ const makeConvertor = (toAlphabet, options) => { // Default to Flickr 58 - const useAlphabet = toAlphabet || flickrBase58; + const useAlphabet = toAlphabet || constants.flickrBase58; // Default to baseOptions const selectedOptions = { ...baseOptions, ...options }; @@ -108,11 +110,7 @@ module.exports = (() => { }; // Expose the constants for other purposes. - makeConvertor.constants = { - cookieBase90, - flickrBase58, - uuid25Base36, - }; + makeConvertor.constants = constants; // Expose the generic v4 UUID generator for convenience makeConvertor.uuid = uuidV4; @@ -121,7 +119,7 @@ module.exports = (() => { makeConvertor.generate = () => { if (!toFlickr) { // Generate on first use; - toFlickr = makeConvertor(flickrBase58).generate; + toFlickr = makeConvertor(constants.flickrBase58).generate; } return toFlickr(); }; From 7d8f970f51eaed41a4fc1fa45f511cc3c772658b Mon Sep 17 00:00:00 2001 From: Samuel Rouse Date: Wed, 1 May 2024 07:55:12 -0400 Subject: [PATCH 4/5] test: Add maxLength validation test for uuid25 --- test/index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/index.js b/test/index.js index 5352111..ea7db1e 100644 --- a/test/index.js +++ b/test/index.js @@ -269,6 +269,11 @@ test('uuid25 should be compatible with uuid25 examples', (t) => { }); }); +test('uuid25 translator should provide maxLength 25', (t) => { + t.plan(1); + t.equal(b36.maxLength, 25); +}); + test('Default generate quantity tests', (t) => { t.plan(1); let underLength = 0; From 17a5d79cda05e4a4707e6cf2573882c2bbc01298 Mon Sep 17 00:00:00 2001 From: Samuel Rouse Date: Wed, 1 May 2024 07:56:19 -0400 Subject: [PATCH 5/5] 5.1.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7010bb2..29faa27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "short-uuid", - "version": "5.0.1", + "version": "5.1.0", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index 5696526..2faea7d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "short-uuid", - "version": "5.0.1", + "version": "5.1.0", "description": "Create and translate standard UUIDs with shorter formats.", "main": "index.js", "typings": "index.d.ts",