Repository: validatorjs/validator.js (js)

Issue:
Extend isUUID to support UUID-like values
**Describe the bug**

Since version 13.15.0 `isUUID` only supports UUID v1 through v8: https://github.com/validatorjs/validator.js/pull/2421 

But there are systems that generate random hex values in the UUID format that do not correspond to UUID versions. Example: [FileMaker Get(UUID)](https://help.claris.com/en/pro-help/content/get-uuid.html).

These UUID-like values should also be (optional) recognized as valid to allow for more flexibility in usage. It would be awesome to allow them if "isUUID" is called with "all" or maybe there can be added a new version-string "like" or "hex"?

**Examples**

Example of a randomly generated hex value in the UUID format:

`04C5CA5B-BA81-964D-9097-88343F39FAED `

**Reproductions**

```
const validator = require('validator');
console.log(validator.isUUID('04C5CA5B-BA81-964D-9097-88343F39FAED')); // false
console.log(validator.isUUID('04C5CA5B-BA81-964D-9097-88343F39FAED', 'all')); // false
```

**Additional context**

Validator.js version: 13.15.0
Node.js version: 22
OS platform: linux, macOS


Pull request description:
feat: add isUUID 'loose' option to validate UUID-like hexadecimal str…
Closes #2546

<!--
Add a descriptive title textbox above, e.g.
feat(validatorName): brief title of what has been done
-->

<!--- briefly describe what you have done in this PR --->

<!--- provide some (credible) references showing the structure of the data to be validated, if applicable --->

## Checklist

- [x] PR contains only changes related; no stray files, etc.
- [x] README updated (where applicable)
- [x] Tests written (where applicable)
- [x] References provided in PR (where applicable)

Patch:
diff --git a/README.md b/README.md
index e1661b5..a98ec86 100644
--- a/README.md
+++ b/README.md
@@ -169,7 +169,7 @@ Validator                               | Description
 **isTaxID(str, locale)**                | check if the string is a valid Tax Identification Number. Default locale is `en-US`.<br/><br/>More info about exact TIN support can be found in `src/lib/isTaxID.js`.<br/><br/>Supported locales: `[ 'bg-BG', 'cs-CZ', 'de-AT', 'de-DE', 'dk-DK', 'el-CY', 'el-GR', 'en-CA', 'en-GB', 'en-IE', 'en-US', 'es-AR', 'es-ES', 'et-EE', 'fi-FI', 'fr-BE', 'fr-CA', 'fr-FR', 'fr-LU', 'hr-HR', 'hu-HU', 'it-IT', 'lb-LU', 'lt-LT', 'lv-LV', 'mt-MT', 'nl-BE', 'nl-NL', 'pl-PL', 'pt-BR', 'pt-PT', 'ro-RO', 'sk-SK', 'sl-SI', 'sv-SE', 'uk-UA']`.
 **isURL(str [, options])**              | check if the string is a URL.<br/><br/>`options` is an object which defaults to `{ protocols: ['http','https','ftp'], require_tld: true, require_protocol: false, require_host: true, require_port: false, require_valid_protocol: true, allow_underscores: false, host_whitelist: false, host_blacklist: false, allow_trailing_dot: false, allow_protocol_relative_urls: false, allow_fragments: true, allow_query_components: true, disallow_auth: false, validate_length: true }`.<br/><br/>`require_protocol` - if set to true isURL will return false if protocol is not present in the URL.<br/>`require_valid_protocol` - isURL will check if the URL's protocol is present in the protocols option.<br/>`protocols` - valid protocols can be modified with this option.<br/>`require_host` - if set to false isURL will not check if host is present in the URL.<br/>`require_port` - if set to true isURL will check if port is present in the URL.<br/>`allow_protocol_relative_urls` - if set to true protocol relative URLs will be allowed.<br/>`allow_fragments` - if set to false isURL will return false if fragments are present.<br/>`allow_query_components` - if set to false isURL will return false if query components are present.<br/>`validate_length` - if set to false isURL will skip string length validation. `max_allowed_length` will be ignored if this is set as `false`.<br/>`max_allowed_length` - if set isURL will not allow URLs longer than the specified value (default is 2084 that IE maximum URL length).
 **isULID(str)**                         | check if the string is a [ULID](https://github.com/ulid/spec).
-**isUUID(str [, version])**             | check if the string is an RFC9562 UUID.<br/>`version` is one of `'1'`-`'8'`, `'nil'`, `'max'`, or `'all'`.
+**isUUID(str [, version])**             | check if the string is an RFC9562 UUID.<br/>`version` is one of `'1'`-`'8'`, `'nil'`, `'max'`, `'all'` or `'loose'`. The `'loose'` option checks if the string is a UUID-like string with hexadecimal values, ignoring RFC9565.
 **isVariableWidth(str)**                | check if the string contains a mixture of full and half-width chars.
 **isVAT(str, countryCode)**             | check if the string is a [valid VAT number][VAT Number] if validation is available for the given country code matching [ISO 3166-1 alpha-2][ISO 3166-1 alpha-2]. <br/><br/>`countryCode` is one of `['AL', 'AR', 'AT', 'AU', 'BE', 'BG', 'BO', 'BR', 'BY', 'CA', 'CH', 'CL', 'CO', 'CR', 'CY', 'CZ', 'DE', 'DK', 'DO', 'EC', 'EE', 'EL', 'ES', 'FI', 'FR', 'GB', 'GT', 'HN', 'HR', 'HU', 'ID', 'IE', 'IL', 'IN', 'IS', 'IT', 'KZ', 'LT', 'LU', 'LV', 'MK', 'MT', 'MX', 'NG', 'NI', 'NL', 'NO', 'NZ', 'PA', 'PE', 'PH', 'PL', 'PT', 'PY', 'RO', 'RS', 'RU', 'SA', 'SE', 'SI', 'SK', 'SM', 'SV', 'TR', 'UA', 'UY', 'UZ', 'VE']`.
 **isWhitelisted(str, chars)**           | check if the string consists only of characters that appear in the whitelist `chars`.
diff --git a/src/lib/isUUID.js b/src/lib/isUUID.js
index 786af00..9d6040f 100644
--- a/src/lib/isUUID.js
+++ b/src/lib/isUUID.js
@@ -12,6 +12,7 @@ const uuid = {
 
   nil: /^00000000-0000-0000-0000-000000000000$/i,
   max: /^ffffffff-ffff-ffff-ffff-ffffffffffff$/i,
+  loose: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i,
 
   // From https://github.com/uuidjs/uuid/blob/main/src/regex.js
   all: /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i,


Test patch:
diff --git a/test/validators.test.js b/test/validators.test.js
index 59be2d0..734a2a2 100644
--- a/test/validators.test.js
+++ b/test/validators.test.js
@@ -5662,6 +5662,33 @@ describe('Validators', () => {
         '00000000-0000-0000-0000-000000000000',
       ],
     });
+    test({
+      validator: 'isUUID',
+      args: ['loose'],
+      valid: [
+        '9deb20fe-a6e0-355c-81ea-288b009e4f6d',
+        'A987FBC9-4BED-3078-CF07-9141BA07C9F3',
+        'A987FBC9-4BED-4078-8F07-9141BA07C9F3',
+        'A987FBC9-4BED-5078-AF07-9141BA07C9F3',
+        'A987FBC9-4BED-6078-AF07-9141BA07C9F3',
+        '018C544A-D384-7000-BB74-3B1738ABE43C',
+        'A987FBC9-4BED-8078-AF07-9141BA07C9F3',
+        'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
+        'AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA',
+        'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee',
+        'EEEEEEEE-EEEE-EEEE-EEEE-EEEEEEEEEEEE',
+        '99999999-9999-9999-9999-999999999999',
+      ],
+      invalid: [
+        '',
+        'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',
+        'A987FBC9-4BED-3078-CF07-9141BA07C9F3xxx',
+        'A987FBC94BED3078CF079141BA07C9F3',
+        '987FBC9-4BED-3078-CF07A-9141BA07C9F3',
+        '934859',
+        'AAAAAAAA-1111-1111-AAAG-111111111111',
+      ],
+    });
     test({
       validator: 'isUUID',
       args: ['all'],