Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide regular expressions and JSON schemas for UUIDs #498

Closed
goloroden opened this issue Jul 28, 2020 · 11 comments
Closed

Provide regular expressions and JSON schemas for UUIDs #498

goloroden opened this issue Jul 28, 2020 · 11 comments

Comments

@goloroden
Copy link

Hi 👋

I'm one of the authors of the uuidv4 module.

With the new 8.3 version of uuid there is almost everything there that is needed from our POV, and we are planning to deprecate uuidv4 in favor of this module.

However, there are two very small things missing, before we can do this:

First, it would be awesome to have regular expressions for UUIDs.
In uuidv4 we use the following ones:

const regex = {
  v4: /(?:^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}$)|(?:^0{8}-0{4}-0{4}-0{4}-0{12}$)/u,
  v5: /(?:^[a-f0-9]{8}-[a-f0-9]{4}-5[a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}$)|(?:^0{8}-0{4}-0{4}-0{4}-0{12}$)/u
};

Besides, it would be great to have JSON schemas for UUIDs. Again, we're using this code here, which builds on top of the aforementioned regexs:

const jsonSchema = {
  v4: { type: 'string', pattern: regex.v4.toString().slice(1, -2) },
  v5: { type: 'string', pattern: regex.v5.toString().slice(1, -2) }
};

Unfortunately, we are missing the time to update the uuid module ourselves, however this should be fairly easy to integrate.

@ctavan
Copy link
Member

ctavan commented Jul 28, 2020

Thank you for coming back here @goloroden! We're definitely interested in covering your use cases in order to reduce the number of uuid libraries in the JS ecosystem.

To make progress here I would like to understand your use cases for the above two features a bit better.

Regarding the regexes: Applying e.g. the v4 regex would be more or less equivalent to the following code:

import { version } from 'uuid';

let isV4 = false;
try {
  isV4 = version('SOME_UUID') === 4;
} catch (e) {}

If you want to avoid the error handling you could do:

import { validate, version } from 'uuid';

const isV4 = validate(SOME_UUID) && version(SOME_UUID) === 4;

That said we have discussed exposing the plain regex(es) in the past so this might definitely be an option, I would just like to understand the benefits over the existing APIs like validate() and version().

Regarding the JSON schema to be honest that looks like a pretty niche requirement that might be better suited for a dedicated module, have you considered that option already? Again, I would love to understand the use cases around this one a bit better.

@goloroden
Copy link
Author

Hey @ctavan 😊

Regarding regular expressions, I can provide an example of where we use them: In a solution for one of our customers we have an admin CLI which can be used to add, edit, and delete entities from the command-line. To identify these entities, you have to provide their ID (which, obviously, is a UUID). To provide these IDs there are two options: The user can use a flag, or enter them in interactive mode.

For the former, the validate call as you described it is fine, but for the latter we have a special requirement: The library that takes the user input interactively accepts a regular expression and only accepts user input if the input matches the regex. Otherwise the user is not even allowed to press <Enter>. For that, having the raw regex is very helpful.

Regarding the JSON schema case: It's basically once again about validating user input, but this time in an HTTP API where we check the entire request body. We use JSON schema for this anyway, so it would be helpful to not have to define the schema over and over again. Of course it's possible to define this elsewhere, but TBH an extra module just for this sounds annoying… and I think having it as part of the uuid module would be the most natural place for this.

Does this help?

@ctavan
Copy link
Member

ctavan commented Jul 28, 2020

Thanks for the explanation. I understand that providing regex(es) comes in handy for interop with validation libraries.

@broofa do you see any drawbacks of exposing the regexes (apart from the fact that we'd have to expose different regexps for the different versions, which we don't have internally yet)?

Regarding JSON schema I'm still reluctant. If we add something this framework/technology specific, it would create a precedent for exposing whatever other framework-specific validation formats might come up in the future (e.g. a GraphQL Type and the likes) and I don't think that this is something that this general-purpose library should support.

@broofa
Copy link
Member

broofa commented Jul 28, 2020

The library that takes the user input interactively accepts a regular expression and only accepts user input if the input matches the regex

This sounds like the pattern attribute. I've mentioned this previously as a possible rationale for exposing the regex we currently use for validate().

However, as I think this issue shows, the problem is going to be that each use case will likely need subtly different incantations of the regex. Should the regex be limited to specific versions? Require strict upper/lower casing only? Allow leading/trailing whitespace? Allow omission of hyphens? Accept the nil UUID? Include a capture group? Include the g flag (and match word boundaries)? Include the ^ and $ assertions?

The permutations quickly become unmanageable. And the more I think about it, the more I'm of the mind that exposing the validate() regex is probably a bad idea. Not only does it make tweaking that regex more difficult if we need to adjust validate() behavior, there will be a constant stream of issues requesting "tweaks" related to various permutations I just mentioned.

Another option would be to provide a regex generator/helper method, createRegex(options = {...}), that allows users to compose uuid regexs to suit their needs. I'm a little leery of how convoluted the code for this might become given the number of options possible, but it'd be interesting to see someone take a pass at this.

@broofa
Copy link
Member

broofa commented Jul 28, 2020

Regarding schemas, I agree with @ctavan. Not a business we should be in. Also suffers from the same permutation issues as regexs. Also, JSON-Schema now supports the uuid type (Not specific versions, however, but that does suggest the incremental value of providing schemas here is pretty low.)

@ctavan
Copy link
Member

ctavan commented Jul 29, 2020

@goloroden does the built-in JSON-Schema support for uuid, that @broofa linked to, solve the JSON schema part of things for you?

@goloroden
Copy link
Author

goloroden commented Jul 29, 2020

@ctavan Theoretically it would, if the JSON schema validator we're using did support this… 🙄

However, this should not be your problem, this is our problem.
So yes, I could live without the JSON schema thing.

However, the regular expression would still be useful.
But I understand why you don't want to do this (although I could think of a function here which returns the regex according to your needs).

OTOH this means that you can't use the validate function if e.g. you want to enforce lowercase / uppercase / … UUIDs. Then you are again left to your own devices.

@ctavan
Copy link
Member

ctavan commented Jul 29, 2020

@ctavan Theoretically it would, if the JSON schema validator we're using did support this… 🙄

However, this should not be your problem, this is our problem.
So yes, I could live without the JSON schema thing.

Cool!

OTOH this means that you can't use the validate function if e.g. you want to enforce lowercase / uppercase / … UUIDs. Then you are again left to your own devices.

You are totally right, the validate function as it stands has the same flaws as exposing the underlying regex would have… Maybe we should provide a separate package with just various UUID regexps? On the other hand people might also argue that you can just copy & paste the regex you need instead of adding an npm dependency for that. After all once you have the correct regexp, it won't change… I think this is really a tricky question and requires some further thought.

@broofa
Copy link
Member

broofa commented Jul 29, 2020

if the JSON schema validator we're using did support this

@goloroden Out of curiousity, which validator are you using? I know AJV supports format: 'uuid'.

@goloroden
Copy link
Author

@broofa We used ajv historically, but it is huge (which makes it a bad use case for the frontend), and its error messages are… well, they could better 😉

Hence we switched to jjv, which is way smaller (compare https://bundlephobia.com/result?p=ajv@6.12.3 to https://bundlephobia.com/result?p=jjv@1.0.2), and which produces – when combined with jjve – nice, human-readable error messages.

Unfortunately, its last release has been 6 years ago, which is probably the main reason why it doesn't support UUIDs.

So, not that you get this wrong: ajv is a great module, it's just too large for small client-side bundles.

@broofa
Copy link
Member

broofa commented Aug 11, 2022

Closing, as it doesn't seem like a compelling enough argument has been made to add this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants