@regexto/validators 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +142 -0
- package/dist/chunk-DL6DNLHZ.mjs +117 -0
- package/dist/index.d.mts +107 -0
- package/dist/index.d.ts +107 -0
- package/dist/index.js +154 -0
- package/dist/index.mjs +28 -0
- package/dist/zod.d.mts +29 -0
- package/dist/zod.d.ts +29 -0
- package/dist/zod.js +81 -0
- package/dist/zod.mjs +27 -0
- package/package.json +62 -0
- package/patterns/au-abn.json +15 -0
- package/patterns/base64.json +14 -0
- package/patterns/bech32-address.json +14 -0
- package/patterns/bitcoin-address.json +14 -0
- package/patterns/br-cnpj.json +15 -0
- package/patterns/br-cpf.json +15 -0
- package/patterns/cn-resident-id.json +15 -0
- package/patterns/coordinates.json +14 -0
- package/patterns/credit-card.json +14 -0
- package/patterns/crypto-mnemonic-word.json +17 -0
- package/patterns/date-eu.json +14 -0
- package/patterns/date-us.json +14 -0
- package/patterns/datetime-iso.json +14 -0
- package/patterns/de-plz.json +15 -0
- package/patterns/de-steuerid.json +15 -0
- package/patterns/domain.json +14 -0
- package/patterns/email.json +14 -0
- package/patterns/ens-name.json +14 -0
- package/patterns/es-nif.json +15 -0
- package/patterns/ethereum-address.json +14 -0
- package/patterns/fr-postal.json +15 -0
- package/patterns/fr-siren.json +15 -0
- package/patterns/fr-siret.json +15 -0
- package/patterns/git-sha.json +14 -0
- package/patterns/hashtag.json +14 -0
- package/patterns/hex-color.json +14 -0
- package/patterns/hsl-color.json +14 -0
- package/patterns/html-tag.json +14 -0
- package/patterns/iban.json +14 -0
- package/patterns/in-pan.json +15 -0
- package/patterns/ipfs-cid.json +17 -0
- package/patterns/ipv4.json +14 -0
- package/patterns/ipv6.json +14 -0
- package/patterns/iso-date.json +14 -0
- package/patterns/it-codice-fiscale.json +15 -0
- package/patterns/jwt.json +14 -0
- package/patterns/latitude.json +14 -0
- package/patterns/lightning-invoice.json +17 -0
- package/patterns/longitude.json +14 -0
- package/patterns/mac-address.json +14 -0
- package/patterns/markdown-blockquote.json +14 -0
- package/patterns/markdown-bold.json +14 -0
- package/patterns/markdown-code-inline.json +14 -0
- package/patterns/markdown-heading.json +14 -0
- package/patterns/markdown-hr.json +14 -0
- package/patterns/markdown-image.json +14 -0
- package/patterns/markdown-italic.json +14 -0
- package/patterns/markdown-link.json +14 -0
- package/patterns/markdown-list-item.json +14 -0
- package/patterns/markdown-table-row.json +14 -0
- package/patterns/md5.json +14 -0
- package/patterns/mention.json +14 -0
- package/patterns/monero-address.json +14 -0
- package/patterns/password-strong.json +14 -0
- package/patterns/phone-e164.json +14 -0
- package/patterns/phone-uk.json +15 -0
- package/patterns/phone-us.json +15 -0
- package/patterns/pl-nip.json +15 -0
- package/patterns/pl-pesel.json +15 -0
- package/patterns/pl-regon.json +15 -0
- package/patterns/port-number.json +14 -0
- package/patterns/rgb-color.json +14 -0
- package/patterns/ru-inn.json +15 -0
- package/patterns/semver.json +14 -0
- package/patterns/sha256.json +17 -0
- package/patterns/slug.json +14 -0
- package/patterns/solana-address.json +14 -0
- package/patterns/swift-bic.json +14 -0
- package/patterns/time-24h.json +14 -0
- package/patterns/txhash-eth.json +17 -0
- package/patterns/uk-nino.json +15 -0
- package/patterns/uk-postcode.json +15 -0
- package/patterns/url.json +14 -0
- package/patterns/us-ein.json +15 -0
- package/patterns/us-ssn.json +15 -0
- package/patterns/us-zip.json +15 -0
- package/patterns/username.json +14 -0
- package/patterns/uuid.json +14 -0
- package/patterns/youtube-url.json +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lukasz Oleniuk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# @regexto/validators
|
|
2
|
+
|
|
3
|
+
A curated collection of battle-tested regex patterns with TypeScript types, Zod v4 integration, and multi-language code generation.
|
|
4
|
+
|
|
5
|
+
**Patterns live in `/patterns/*.json`** — the single source of truth used by both this package and the [regex.to](https://regex.to) website.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@regexto/validators)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @regexto/validators
|
|
14
|
+
# with Zod v4 integration:
|
|
15
|
+
npm install @regexto/validators zod
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { test, validate, getRegex, getAllPatterns } from '@regexto/validators';
|
|
22
|
+
|
|
23
|
+
// Quick boolean test (partial match — use validate() for full-string validation)
|
|
24
|
+
test('email', 'user@example.com'); // → true
|
|
25
|
+
test('email', 'invalid'); // → false
|
|
26
|
+
|
|
27
|
+
// Full-string validation with anchors
|
|
28
|
+
const { valid } = validate('ipv4', '192.168.1.1'); // → { valid: true, ... }
|
|
29
|
+
const { valid: no } = validate('ipv4', '999.0.0.0'); // → { valid: false, ... }
|
|
30
|
+
|
|
31
|
+
// Get the compiled RegExp
|
|
32
|
+
const re = getRegex('email'); // → /[a-zA-Z0-9...]+@.../i
|
|
33
|
+
|
|
34
|
+
// All patterns as an array
|
|
35
|
+
const all = getAllPatterns(); // → PatternData[]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Zod v4 Integration
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { zodSchema, zodObjectSchema } from '@regexto/validators/zod';
|
|
42
|
+
import { z } from 'zod';
|
|
43
|
+
|
|
44
|
+
// Single-field schema
|
|
45
|
+
const emailSchema = zodSchema('email');
|
|
46
|
+
emailSchema.parse('user@example.com'); // ✓
|
|
47
|
+
emailSchema.parse('invalid'); // ✗ ZodError
|
|
48
|
+
|
|
49
|
+
// Object schema from a field map
|
|
50
|
+
const contactSchema = zodObjectSchema({
|
|
51
|
+
email: 'email',
|
|
52
|
+
website: 'url',
|
|
53
|
+
});
|
|
54
|
+
type ContactForm = z.infer<typeof contactSchema>;
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### detect() — Auto-detect string type
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { detect } from '@regexto/validators';
|
|
61
|
+
|
|
62
|
+
detect('user@example.com');
|
|
63
|
+
// → [{ pattern: { slug: 'email', ... }, matchType: 'full', coverage: 1 }]
|
|
64
|
+
|
|
65
|
+
detect('+14155552671');
|
|
66
|
+
// → [{ pattern: { slug: 'phone-e164', ... }, matchType: 'full', coverage: 1 }]
|
|
67
|
+
|
|
68
|
+
detect('0x742d35Cc6634C0532925a3b844Bc454e4438f44e');
|
|
69
|
+
// → [{ pattern: { slug: 'eth-address', ... }, matchType: 'full', coverage: 1 }]
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Available Patterns
|
|
73
|
+
|
|
74
|
+
| Slug | Name | Category |
|
|
75
|
+
|------|------|----------|
|
|
76
|
+
| `email` | Email Address | Internet |
|
|
77
|
+
| `url` | URL (HTTP/HTTPS) | Internet |
|
|
78
|
+
| `ipv4` | IPv4 Address | Network |
|
|
79
|
+
| `ipv6` | IPv6 Address | Network |
|
|
80
|
+
| `hex-color` | Hex Color | Design |
|
|
81
|
+
| `rgb-color` | RGB Color | Design |
|
|
82
|
+
| `iso-date` | ISO 8601 Date | Date & Time |
|
|
83
|
+
| `semver` | Semantic Version | Dev |
|
|
84
|
+
| `slug` | URL Slug | Web |
|
|
85
|
+
| `uuid` | UUID | Dev |
|
|
86
|
+
| `credit-card` | Credit Card Number | Finance |
|
|
87
|
+
| `iban` | IBAN | Finance |
|
|
88
|
+
| `jwt` | JSON Web Token | Security |
|
|
89
|
+
| `sha256` | SHA-256 Hash | Crypto |
|
|
90
|
+
| `ethereum-address` | Ethereum Address | Crypto |
|
|
91
|
+
| `bitcoin-address` | Bitcoin Address | Crypto |
|
|
92
|
+
| `pl-nip` | Polish NIP (Tax ID) | Finance |
|
|
93
|
+
| `pl-pesel` | Polish PESEL | Identity |
|
|
94
|
+
| `pl-regon` | Polish REGON | Finance |
|
|
95
|
+
| `us-ssn` | US Social Security Number | Identity |
|
|
96
|
+
| `us-zip` | US ZIP Code | Address |
|
|
97
|
+
| `uk-postcode` | UK Postcode | Address |
|
|
98
|
+
| … | 79 patterns total | [Browse all](https://regex.to/patterns) |
|
|
99
|
+
|
|
100
|
+
## API
|
|
101
|
+
|
|
102
|
+
| Function | Description |
|
|
103
|
+
|----------|-------------|
|
|
104
|
+
| `test(slug, value)` | Quick boolean — partial match (substring) |
|
|
105
|
+
| `validate(slug, value)` | Full-string match with anchors, returns result object |
|
|
106
|
+
| `getRegex(slug)` | Returns the compiled `RegExp` |
|
|
107
|
+
| `detect(input)` | Auto-detect type of an unknown string |
|
|
108
|
+
| `getAllPatterns()` | Returns all patterns as `PatternData[]` |
|
|
109
|
+
| `getPattern(slug)` | Returns a single `PatternData` or `null` |
|
|
110
|
+
| `getByCategory(category)` | Filter by category |
|
|
111
|
+
| `getByTags(tags[])` | Filter by tags |
|
|
112
|
+
| `getSlugs()` | All available slugs |
|
|
113
|
+
| `getCategories()` | All available category names |
|
|
114
|
+
| `zodSchema(slug)` | Zod string schema *(zod import)* |
|
|
115
|
+
| `zodObjectSchema(fieldMap)` | Zod object schema *(zod import)* |
|
|
116
|
+
|
|
117
|
+
## Adding a Pattern
|
|
118
|
+
|
|
119
|
+
Create a JSON file in `patterns/` and open a Pull Request:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"slug": "my-pattern",
|
|
124
|
+
"name": "My Pattern",
|
|
125
|
+
"description": "What it validates",
|
|
126
|
+
"category": "Internet",
|
|
127
|
+
"pattern": "your[regex]+",
|
|
128
|
+
"flags": "i",
|
|
129
|
+
"examples": ["valid"],
|
|
130
|
+
"counterExamples": ["invalid"],
|
|
131
|
+
"tags": ["tag1"],
|
|
132
|
+
"useCases": ["Use case description"]
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The JSON file is automatically picked up by both the npm package and the regex.to website at build time — no code changes needed.
|
|
137
|
+
|
|
138
|
+
See the full [contribution guide](https://regex.to/docs#contributing).
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
MIT © [regex.to](https://regex.to)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// node_modules/tsup/assets/esm_shims.js
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
var getFilename = () => fileURLToPath(import.meta.url);
|
|
5
|
+
var getDirname = () => path.dirname(getFilename());
|
|
6
|
+
var __dirname = /* @__PURE__ */ getDirname();
|
|
7
|
+
|
|
8
|
+
// src/index.ts
|
|
9
|
+
import fs from "fs";
|
|
10
|
+
import path2 from "path";
|
|
11
|
+
|
|
12
|
+
// src/detect.ts
|
|
13
|
+
function detect(input) {
|
|
14
|
+
if (!input || !input.trim()) return [];
|
|
15
|
+
const all = Object.values(PATTERNS);
|
|
16
|
+
const results = [];
|
|
17
|
+
for (const p of all) {
|
|
18
|
+
try {
|
|
19
|
+
const baseFlags = p.flags.replace(/[gm]/g, "");
|
|
20
|
+
try {
|
|
21
|
+
const fullRe = new RegExp(`^(?:${p.pattern})$`, baseFlags);
|
|
22
|
+
if (fullRe.test(input)) {
|
|
23
|
+
results.push({ pattern: p, matchType: "full", matchedText: input, coverage: 1 });
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
} catch {
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
const partialRe = new RegExp(p.pattern, baseFlags);
|
|
30
|
+
const m = partialRe.exec(input);
|
|
31
|
+
if (m?.[0] && m[0].length >= 4 && m[0].length / input.length >= 0.2) {
|
|
32
|
+
results.push({
|
|
33
|
+
pattern: p,
|
|
34
|
+
matchType: "partial",
|
|
35
|
+
matchedText: m[0],
|
|
36
|
+
coverage: m[0].length / input.length
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
41
|
+
} catch {
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return results.sort((a, b) => {
|
|
45
|
+
if (a.matchType !== b.matchType) return a.matchType === "full" ? -1 : 1;
|
|
46
|
+
if (Math.abs(b.coverage - a.coverage) > 0.05) return b.coverage - a.coverage;
|
|
47
|
+
return b.pattern.pattern.length - a.pattern.pattern.length;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/index.ts
|
|
52
|
+
function loadPatterns() {
|
|
53
|
+
const dir = path2.join(__dirname, "..", "patterns");
|
|
54
|
+
const result = {};
|
|
55
|
+
try {
|
|
56
|
+
const files = fs.readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
57
|
+
for (const file of files) {
|
|
58
|
+
const raw = fs.readFileSync(path2.join(dir, file), "utf-8");
|
|
59
|
+
const p = JSON.parse(raw);
|
|
60
|
+
result[p.slug] = p;
|
|
61
|
+
}
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
var PATTERNS = loadPatterns();
|
|
67
|
+
function getRegex(slug) {
|
|
68
|
+
const p = PATTERNS[slug];
|
|
69
|
+
if (!p) throw new Error(`Pattern "${slug}" not found in @regex.to/validators`);
|
|
70
|
+
return new RegExp(p.pattern, p.flags);
|
|
71
|
+
}
|
|
72
|
+
function test(slug, value) {
|
|
73
|
+
return getRegex(slug).test(value);
|
|
74
|
+
}
|
|
75
|
+
function validate(slug, value) {
|
|
76
|
+
const p = PATTERNS[slug];
|
|
77
|
+
if (!p) throw new Error(`Pattern "${slug}" not found`);
|
|
78
|
+
const regex = new RegExp(`^(?:${p.pattern})$`, p.flags);
|
|
79
|
+
const matches = value.match(regex);
|
|
80
|
+
return { valid: matches !== null, pattern: p, matches };
|
|
81
|
+
}
|
|
82
|
+
function getAllPatterns() {
|
|
83
|
+
return Object.values(PATTERNS);
|
|
84
|
+
}
|
|
85
|
+
function getByCategory(category) {
|
|
86
|
+
return Object.values(PATTERNS).filter((p) => p.category === category);
|
|
87
|
+
}
|
|
88
|
+
function getByTags(tags) {
|
|
89
|
+
return Object.values(PATTERNS).filter(
|
|
90
|
+
(p) => tags.some((t) => p.tags.includes(t))
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
function getPattern(slug) {
|
|
94
|
+
return PATTERNS[slug] ?? null;
|
|
95
|
+
}
|
|
96
|
+
function getCategories() {
|
|
97
|
+
return [...new Set(Object.values(PATTERNS).map((p) => p.category))].sort();
|
|
98
|
+
}
|
|
99
|
+
function getSlugs() {
|
|
100
|
+
return Object.keys(PATTERNS);
|
|
101
|
+
}
|
|
102
|
+
var index_default = PATTERNS;
|
|
103
|
+
|
|
104
|
+
export {
|
|
105
|
+
detect,
|
|
106
|
+
PATTERNS,
|
|
107
|
+
getRegex,
|
|
108
|
+
test,
|
|
109
|
+
validate,
|
|
110
|
+
getAllPatterns,
|
|
111
|
+
getByCategory,
|
|
112
|
+
getByTags,
|
|
113
|
+
getPattern,
|
|
114
|
+
getCategories,
|
|
115
|
+
getSlugs,
|
|
116
|
+
index_default
|
|
117
|
+
};
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
type MatchType = "full" | "partial";
|
|
2
|
+
interface DetectResult {
|
|
3
|
+
/** The matching pattern */
|
|
4
|
+
pattern: PatternData;
|
|
5
|
+
/** "full" = entire string matches; "partial" = substring matches */
|
|
6
|
+
matchType: MatchType;
|
|
7
|
+
/** The substring that was matched (equals input for full matches) */
|
|
8
|
+
matchedText: string;
|
|
9
|
+
/** Ratio of matchedText.length / input.length (1.0 for full matches) */
|
|
10
|
+
coverage: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Detects the type(s) of an unknown string by testing it against all
|
|
14
|
+
* available patterns. Returns results sorted by confidence — full matches
|
|
15
|
+
* first, then by coverage ratio.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* detect("user@example.com")
|
|
19
|
+
* // → [{ pattern: { slug: "email", ... }, matchType: "full", coverage: 1 }]
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* detect("+14155552671")
|
|
23
|
+
* // → [{ slug: "phone-e164", matchType: "full" }, { slug: "phone-us", matchType: "partial" }, ...]
|
|
24
|
+
*/
|
|
25
|
+
declare function detect(input: string): DetectResult[];
|
|
26
|
+
|
|
27
|
+
type PatternFlavor = "javascript" | "golang" | "php" | "python";
|
|
28
|
+
interface PatternData {
|
|
29
|
+
/** Unique slug used in URLs, e.g. "email", "pl-nip" */
|
|
30
|
+
slug: string;
|
|
31
|
+
/** Human-readable name */
|
|
32
|
+
name: string;
|
|
33
|
+
/** Short description */
|
|
34
|
+
description: string;
|
|
35
|
+
/** Category for catalog grouping */
|
|
36
|
+
category: string;
|
|
37
|
+
/** The raw regex source (no delimiters) */
|
|
38
|
+
pattern: string;
|
|
39
|
+
/** Regex flags, e.g. "gi" */
|
|
40
|
+
flags: string;
|
|
41
|
+
/** Example strings that should match */
|
|
42
|
+
examples: string[];
|
|
43
|
+
/** Example strings that should NOT match */
|
|
44
|
+
counterExamples: string[];
|
|
45
|
+
/** Named capture groups (if any) */
|
|
46
|
+
groups?: Record<string, string>;
|
|
47
|
+
/** ISO 639-1 locale codes this pattern is designed for */
|
|
48
|
+
locales?: string[];
|
|
49
|
+
/** Tags for search */
|
|
50
|
+
tags: string[];
|
|
51
|
+
/** Use-case descriptions */
|
|
52
|
+
useCases?: string[];
|
|
53
|
+
/** SEO page title override */
|
|
54
|
+
seoTitle?: string;
|
|
55
|
+
/** SEO meta description override */
|
|
56
|
+
seoDescription?: string;
|
|
57
|
+
}
|
|
58
|
+
/** @deprecated Use PatternData instead */
|
|
59
|
+
type RegexPattern = PatternData;
|
|
60
|
+
/**
|
|
61
|
+
* All available regex patterns, keyed by slug.
|
|
62
|
+
* Loaded at module initialisation from the /patterns JSON files.
|
|
63
|
+
*/
|
|
64
|
+
declare const PATTERNS: Readonly<Record<string, PatternData>>;
|
|
65
|
+
/**
|
|
66
|
+
* Returns a compiled RegExp for the given pattern slug.
|
|
67
|
+
* Throws if the slug is not found.
|
|
68
|
+
*/
|
|
69
|
+
declare function getRegex(slug: string): RegExp;
|
|
70
|
+
/**
|
|
71
|
+
* Tests a value against a named pattern.
|
|
72
|
+
*/
|
|
73
|
+
declare function test(slug: string, value: string): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Validates a value and returns a typed result.
|
|
76
|
+
*/
|
|
77
|
+
declare function validate(slug: string, value: string): {
|
|
78
|
+
valid: boolean;
|
|
79
|
+
pattern: PatternData;
|
|
80
|
+
matches: RegExpMatchArray | null;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Returns all patterns as an array, optionally filtered.
|
|
84
|
+
*/
|
|
85
|
+
declare function getAllPatterns(): PatternData[];
|
|
86
|
+
/**
|
|
87
|
+
* Returns all patterns belonging to a category.
|
|
88
|
+
*/
|
|
89
|
+
declare function getByCategory(category: string): PatternData[];
|
|
90
|
+
/**
|
|
91
|
+
* Returns all patterns matching one or more tags.
|
|
92
|
+
*/
|
|
93
|
+
declare function getByTags(tags: string[]): PatternData[];
|
|
94
|
+
/**
|
|
95
|
+
* Returns a single pattern by slug, or null if not found.
|
|
96
|
+
*/
|
|
97
|
+
declare function getPattern(slug: string): PatternData | null;
|
|
98
|
+
/**
|
|
99
|
+
* Returns all available category names (sorted).
|
|
100
|
+
*/
|
|
101
|
+
declare function getCategories(): string[];
|
|
102
|
+
/**
|
|
103
|
+
* Returns all pattern slugs.
|
|
104
|
+
*/
|
|
105
|
+
declare function getSlugs(): string[];
|
|
106
|
+
|
|
107
|
+
export { type DetectResult, type MatchType, PATTERNS, type PatternData, type PatternFlavor, type RegexPattern, PATTERNS as default, detect, getAllPatterns, getByCategory, getByTags, getCategories, getPattern, getRegex, getSlugs, test, validate };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
type MatchType = "full" | "partial";
|
|
2
|
+
interface DetectResult {
|
|
3
|
+
/** The matching pattern */
|
|
4
|
+
pattern: PatternData;
|
|
5
|
+
/** "full" = entire string matches; "partial" = substring matches */
|
|
6
|
+
matchType: MatchType;
|
|
7
|
+
/** The substring that was matched (equals input for full matches) */
|
|
8
|
+
matchedText: string;
|
|
9
|
+
/** Ratio of matchedText.length / input.length (1.0 for full matches) */
|
|
10
|
+
coverage: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Detects the type(s) of an unknown string by testing it against all
|
|
14
|
+
* available patterns. Returns results sorted by confidence — full matches
|
|
15
|
+
* first, then by coverage ratio.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* detect("user@example.com")
|
|
19
|
+
* // → [{ pattern: { slug: "email", ... }, matchType: "full", coverage: 1 }]
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* detect("+14155552671")
|
|
23
|
+
* // → [{ slug: "phone-e164", matchType: "full" }, { slug: "phone-us", matchType: "partial" }, ...]
|
|
24
|
+
*/
|
|
25
|
+
declare function detect(input: string): DetectResult[];
|
|
26
|
+
|
|
27
|
+
type PatternFlavor = "javascript" | "golang" | "php" | "python";
|
|
28
|
+
interface PatternData {
|
|
29
|
+
/** Unique slug used in URLs, e.g. "email", "pl-nip" */
|
|
30
|
+
slug: string;
|
|
31
|
+
/** Human-readable name */
|
|
32
|
+
name: string;
|
|
33
|
+
/** Short description */
|
|
34
|
+
description: string;
|
|
35
|
+
/** Category for catalog grouping */
|
|
36
|
+
category: string;
|
|
37
|
+
/** The raw regex source (no delimiters) */
|
|
38
|
+
pattern: string;
|
|
39
|
+
/** Regex flags, e.g. "gi" */
|
|
40
|
+
flags: string;
|
|
41
|
+
/** Example strings that should match */
|
|
42
|
+
examples: string[];
|
|
43
|
+
/** Example strings that should NOT match */
|
|
44
|
+
counterExamples: string[];
|
|
45
|
+
/** Named capture groups (if any) */
|
|
46
|
+
groups?: Record<string, string>;
|
|
47
|
+
/** ISO 639-1 locale codes this pattern is designed for */
|
|
48
|
+
locales?: string[];
|
|
49
|
+
/** Tags for search */
|
|
50
|
+
tags: string[];
|
|
51
|
+
/** Use-case descriptions */
|
|
52
|
+
useCases?: string[];
|
|
53
|
+
/** SEO page title override */
|
|
54
|
+
seoTitle?: string;
|
|
55
|
+
/** SEO meta description override */
|
|
56
|
+
seoDescription?: string;
|
|
57
|
+
}
|
|
58
|
+
/** @deprecated Use PatternData instead */
|
|
59
|
+
type RegexPattern = PatternData;
|
|
60
|
+
/**
|
|
61
|
+
* All available regex patterns, keyed by slug.
|
|
62
|
+
* Loaded at module initialisation from the /patterns JSON files.
|
|
63
|
+
*/
|
|
64
|
+
declare const PATTERNS: Readonly<Record<string, PatternData>>;
|
|
65
|
+
/**
|
|
66
|
+
* Returns a compiled RegExp for the given pattern slug.
|
|
67
|
+
* Throws if the slug is not found.
|
|
68
|
+
*/
|
|
69
|
+
declare function getRegex(slug: string): RegExp;
|
|
70
|
+
/**
|
|
71
|
+
* Tests a value against a named pattern.
|
|
72
|
+
*/
|
|
73
|
+
declare function test(slug: string, value: string): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Validates a value and returns a typed result.
|
|
76
|
+
*/
|
|
77
|
+
declare function validate(slug: string, value: string): {
|
|
78
|
+
valid: boolean;
|
|
79
|
+
pattern: PatternData;
|
|
80
|
+
matches: RegExpMatchArray | null;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Returns all patterns as an array, optionally filtered.
|
|
84
|
+
*/
|
|
85
|
+
declare function getAllPatterns(): PatternData[];
|
|
86
|
+
/**
|
|
87
|
+
* Returns all patterns belonging to a category.
|
|
88
|
+
*/
|
|
89
|
+
declare function getByCategory(category: string): PatternData[];
|
|
90
|
+
/**
|
|
91
|
+
* Returns all patterns matching one or more tags.
|
|
92
|
+
*/
|
|
93
|
+
declare function getByTags(tags: string[]): PatternData[];
|
|
94
|
+
/**
|
|
95
|
+
* Returns a single pattern by slug, or null if not found.
|
|
96
|
+
*/
|
|
97
|
+
declare function getPattern(slug: string): PatternData | null;
|
|
98
|
+
/**
|
|
99
|
+
* Returns all available category names (sorted).
|
|
100
|
+
*/
|
|
101
|
+
declare function getCategories(): string[];
|
|
102
|
+
/**
|
|
103
|
+
* Returns all pattern slugs.
|
|
104
|
+
*/
|
|
105
|
+
declare function getSlugs(): string[];
|
|
106
|
+
|
|
107
|
+
export { type DetectResult, type MatchType, PATTERNS, type PatternData, type PatternFlavor, type RegexPattern, PATTERNS as default, detect, getAllPatterns, getByCategory, getByTags, getCategories, getPattern, getRegex, getSlugs, test, validate };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
PATTERNS: () => PATTERNS,
|
|
34
|
+
default: () => index_default,
|
|
35
|
+
detect: () => detect,
|
|
36
|
+
getAllPatterns: () => getAllPatterns,
|
|
37
|
+
getByCategory: () => getByCategory,
|
|
38
|
+
getByTags: () => getByTags,
|
|
39
|
+
getCategories: () => getCategories,
|
|
40
|
+
getPattern: () => getPattern,
|
|
41
|
+
getRegex: () => getRegex,
|
|
42
|
+
getSlugs: () => getSlugs,
|
|
43
|
+
test: () => test,
|
|
44
|
+
validate: () => validate
|
|
45
|
+
});
|
|
46
|
+
module.exports = __toCommonJS(index_exports);
|
|
47
|
+
var import_fs = __toESM(require("fs"));
|
|
48
|
+
var import_path = __toESM(require("path"));
|
|
49
|
+
|
|
50
|
+
// src/detect.ts
|
|
51
|
+
function detect(input) {
|
|
52
|
+
if (!input || !input.trim()) return [];
|
|
53
|
+
const all = Object.values(PATTERNS);
|
|
54
|
+
const results = [];
|
|
55
|
+
for (const p of all) {
|
|
56
|
+
try {
|
|
57
|
+
const baseFlags = p.flags.replace(/[gm]/g, "");
|
|
58
|
+
try {
|
|
59
|
+
const fullRe = new RegExp(`^(?:${p.pattern})$`, baseFlags);
|
|
60
|
+
if (fullRe.test(input)) {
|
|
61
|
+
results.push({ pattern: p, matchType: "full", matchedText: input, coverage: 1 });
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
} catch {
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const partialRe = new RegExp(p.pattern, baseFlags);
|
|
68
|
+
const m = partialRe.exec(input);
|
|
69
|
+
if (m?.[0] && m[0].length >= 4 && m[0].length / input.length >= 0.2) {
|
|
70
|
+
results.push({
|
|
71
|
+
pattern: p,
|
|
72
|
+
matchType: "partial",
|
|
73
|
+
matchedText: m[0],
|
|
74
|
+
coverage: m[0].length / input.length
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
} catch {
|
|
78
|
+
}
|
|
79
|
+
} catch {
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return results.sort((a, b) => {
|
|
83
|
+
if (a.matchType !== b.matchType) return a.matchType === "full" ? -1 : 1;
|
|
84
|
+
if (Math.abs(b.coverage - a.coverage) > 0.05) return b.coverage - a.coverage;
|
|
85
|
+
return b.pattern.pattern.length - a.pattern.pattern.length;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/index.ts
|
|
90
|
+
function loadPatterns() {
|
|
91
|
+
const dir = import_path.default.join(__dirname, "..", "patterns");
|
|
92
|
+
const result = {};
|
|
93
|
+
try {
|
|
94
|
+
const files = import_fs.default.readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
95
|
+
for (const file of files) {
|
|
96
|
+
const raw = import_fs.default.readFileSync(import_path.default.join(dir, file), "utf-8");
|
|
97
|
+
const p = JSON.parse(raw);
|
|
98
|
+
result[p.slug] = p;
|
|
99
|
+
}
|
|
100
|
+
} catch {
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
var PATTERNS = loadPatterns();
|
|
105
|
+
function getRegex(slug) {
|
|
106
|
+
const p = PATTERNS[slug];
|
|
107
|
+
if (!p) throw new Error(`Pattern "${slug}" not found in @regex.to/validators`);
|
|
108
|
+
return new RegExp(p.pattern, p.flags);
|
|
109
|
+
}
|
|
110
|
+
function test(slug, value) {
|
|
111
|
+
return getRegex(slug).test(value);
|
|
112
|
+
}
|
|
113
|
+
function validate(slug, value) {
|
|
114
|
+
const p = PATTERNS[slug];
|
|
115
|
+
if (!p) throw new Error(`Pattern "${slug}" not found`);
|
|
116
|
+
const regex = new RegExp(`^(?:${p.pattern})$`, p.flags);
|
|
117
|
+
const matches = value.match(regex);
|
|
118
|
+
return { valid: matches !== null, pattern: p, matches };
|
|
119
|
+
}
|
|
120
|
+
function getAllPatterns() {
|
|
121
|
+
return Object.values(PATTERNS);
|
|
122
|
+
}
|
|
123
|
+
function getByCategory(category) {
|
|
124
|
+
return Object.values(PATTERNS).filter((p) => p.category === category);
|
|
125
|
+
}
|
|
126
|
+
function getByTags(tags) {
|
|
127
|
+
return Object.values(PATTERNS).filter(
|
|
128
|
+
(p) => tags.some((t) => p.tags.includes(t))
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
function getPattern(slug) {
|
|
132
|
+
return PATTERNS[slug] ?? null;
|
|
133
|
+
}
|
|
134
|
+
function getCategories() {
|
|
135
|
+
return [...new Set(Object.values(PATTERNS).map((p) => p.category))].sort();
|
|
136
|
+
}
|
|
137
|
+
function getSlugs() {
|
|
138
|
+
return Object.keys(PATTERNS);
|
|
139
|
+
}
|
|
140
|
+
var index_default = PATTERNS;
|
|
141
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
142
|
+
0 && (module.exports = {
|
|
143
|
+
PATTERNS,
|
|
144
|
+
detect,
|
|
145
|
+
getAllPatterns,
|
|
146
|
+
getByCategory,
|
|
147
|
+
getByTags,
|
|
148
|
+
getCategories,
|
|
149
|
+
getPattern,
|
|
150
|
+
getRegex,
|
|
151
|
+
getSlugs,
|
|
152
|
+
test,
|
|
153
|
+
validate
|
|
154
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PATTERNS,
|
|
3
|
+
detect,
|
|
4
|
+
getAllPatterns,
|
|
5
|
+
getByCategory,
|
|
6
|
+
getByTags,
|
|
7
|
+
getCategories,
|
|
8
|
+
getPattern,
|
|
9
|
+
getRegex,
|
|
10
|
+
getSlugs,
|
|
11
|
+
index_default,
|
|
12
|
+
test,
|
|
13
|
+
validate
|
|
14
|
+
} from "./chunk-DL6DNLHZ.mjs";
|
|
15
|
+
export {
|
|
16
|
+
PATTERNS,
|
|
17
|
+
index_default as default,
|
|
18
|
+
detect,
|
|
19
|
+
getAllPatterns,
|
|
20
|
+
getByCategory,
|
|
21
|
+
getByTags,
|
|
22
|
+
getCategories,
|
|
23
|
+
getPattern,
|
|
24
|
+
getRegex,
|
|
25
|
+
getSlugs,
|
|
26
|
+
test,
|
|
27
|
+
validate
|
|
28
|
+
};
|