From f9f5d4556ca3f6ef9b8c6a939b05a5fcf7a556ce Mon Sep 17 00:00:00 2001 From: "Jean M. Lescure" Date: Mon, 29 Apr 2024 16:22:47 -0600 Subject: [PATCH] feat: add ability to validate uuid --- README.md | 18 ++++++++++++++++++ src/index.ts | 19 ++++++++++++++++--- src/test.ts | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0744705..bb57df7 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,24 @@ console.log(result); // Time: 63d5e631 ID: 0b-aaab ``` +Ability to validate UUIDs against the instance dictionary or a provided dictionary for improved data integrity and consistency. + +Example of using .validate() method: + +```js +// Instantiate using one of the default dictionary strings +const uid = new ShortUniqueId({ + dictionary: 'hex', +}); + +const uuid = uid.stamp(32); // Generate a UUID + +// Validate the generated UUID against the instance dictionary +const isValid = uid.validate(uuid); + +console.log(`Is the UUID valid? ${isValid}`); +`` + ### Use in CLI ```sh diff --git a/src/index.ts b/src/index.ts index b3d616e..b8e33b8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -208,8 +208,7 @@ export default class ShortUniqueId { }; /* tslint:enable consistent-return */ - /** Change the dictionary after initialization. */ - setDictionary = (dictionary: string[] | ShortUniqueIdDefaultDictionaries, shuffle?: boolean): void => { + protected _normalizeDictionary = (dictionary: string[] | ShortUniqueIdDefaultDictionaries, shuffle?: boolean): string[] => { let finalDict: string[]; if (dictionary && Array.isArray(dictionary) && dictionary.length > 1) { @@ -248,7 +247,12 @@ export default class ShortUniqueId { finalDict = finalDict.sort(() => Math.random() - PROBABILITY); } - this.dict = finalDict; + return finalDict; + } + + /** Change the dictionary after initialization. */ + setDictionary = (dictionary: string[] | ShortUniqueIdDefaultDictionaries, shuffle?: boolean): void => { + this.dict = this._normalizeDictionary(dictionary, shuffle); // Cache Dictionary Length for future usage. this.dictLength = this.dict.length; @@ -587,6 +591,15 @@ export default class ShortUniqueId { this.counter = counter; }; + /** + * Validate given UID contains only characters from the instanced dictionary or optionally provided dictionary. + */ + validate = (uid: string, dictionary?: string[] | ShortUniqueIdDefaultDictionaries): boolean => { + const finalDictionary = dictionary ? this._normalizeDictionary(dictionary) : this.dict; + + return uid.split('').every((c) => finalDictionary.includes(c)); + }; + constructor(argOptions: Partial = {}) { const options: ShortUniqueIdOptions = { ...DEFAULT_OPTIONS, diff --git a/src/test.ts b/src/test.ts index a5f91af..18f9498 100644 --- a/src/test.ts +++ b/src/test.ts @@ -359,3 +359,55 @@ test({ assert(+parsedStamp === nowStamp); }, }); + +test({ + name: 'ability to validate UUID against instance dictionary', + fn(): void { + const { validate, fmt } = new ShortUniqueId({ + dictionary: ['a', 'b'], + }); + + assert(validate('ab')); + + assert(validate('b')); + + assert(validate('abba')); + + assert(!validate('abc')); + + // Formatted UIDs are custom, thus user should implement their own validation + assert(!validate(fmt('$r2-$t12'))); + }, +}); + +test({ + name: 'ability to validate UUID against custom dictionary', + fn(): void { + const { validate } = new ShortUniqueId({ + dictionary: ['a', 'b'], + }); + + assert(validate('dc', ['c', 'd'])); + + assert(validate('dccd', ['c', 'd'])); + + assert(!validate('dccb', ['c', 'd'])); + }, +}); + +test({ + name: 'ability to validate UUID against internal dictionary', + fn(): void { + const { validate, stamp } = new ShortUniqueId({ + dictionary: ['a', 'b'], + }); + + assert(validate(stamp(32), 'hex')); + + assert(!validate(stamp(32))); + + assert(validate('0987654321fedcba', 'hex')); + + assert(!validate('0987654321fedcbag', 'hex')); + }, +});