pseudonym-mcp 0.2.5 → 0.3.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/README.md +53 -15
- package/dist/language/detect-language.d.ts +15 -0
- package/dist/language/detect-language.d.ts.map +1 -0
- package/dist/language/detect-language.js +45 -0
- package/dist/language/detect-language.js.map +1 -0
- package/dist/language/language-map.d.ts +7 -0
- package/dist/language/language-map.d.ts.map +1 -0
- package/dist/language/language-map.js +9 -0
- package/dist/language/language-map.js.map +1 -0
- package/dist/language/types.d.ts +14 -0
- package/dist/language/types.d.ts.map +1 -0
- package/dist/language/types.js +2 -0
- package/dist/language/types.js.map +1 -0
- package/dist/languages/en/rules.d.ts.map +1 -1
- package/dist/languages/en/rules.js +6 -66
- package/dist/languages/en/rules.js.map +1 -1
- package/dist/languages/pl/rules.d.ts.map +1 -1
- package/dist/languages/pl/rules.js +6 -41
- package/dist/languages/pl/rules.js.map +1 -1
- package/dist/patterns/engines/balanced.d.ts +4 -0
- package/dist/patterns/engines/balanced.d.ts.map +1 -0
- package/dist/patterns/engines/balanced.js +4 -0
- package/dist/patterns/engines/balanced.js.map +1 -0
- package/dist/patterns/engines/paranoid.d.ts +4 -0
- package/dist/patterns/engines/paranoid.d.ts.map +1 -0
- package/dist/patterns/engines/paranoid.js +4 -0
- package/dist/patterns/engines/paranoid.js.map +1 -0
- package/dist/patterns/engines/strict.d.ts +4 -0
- package/dist/patterns/engines/strict.d.ts.map +1 -0
- package/dist/patterns/engines/strict.js +4 -0
- package/dist/patterns/engines/strict.js.map +1 -0
- package/dist/patterns/global/email.d.ts +3 -0
- package/dist/patterns/global/email.d.ts.map +1 -0
- package/dist/patterns/global/email.js +9 -0
- package/dist/patterns/global/email.js.map +1 -0
- package/dist/patterns/global/iban.d.ts +3 -0
- package/dist/patterns/global/iban.d.ts.map +1 -0
- package/dist/patterns/global/iban.js +11 -0
- package/dist/patterns/global/iban.js.map +1 -0
- package/dist/patterns/global/ip.d.ts +4 -0
- package/dist/patterns/global/ip.d.ts.map +1 -0
- package/dist/patterns/global/ip.js +20 -0
- package/dist/patterns/global/ip.js.map +1 -0
- package/dist/patterns/global/phone.d.ts +3 -0
- package/dist/patterns/global/phone.d.ts.map +1 -0
- package/dist/patterns/global/phone.js +11 -0
- package/dist/patterns/global/phone.js.map +1 -0
- package/dist/patterns/global/url.d.ts +3 -0
- package/dist/patterns/global/url.d.ts.map +1 -0
- package/dist/patterns/global/url.js +10 -0
- package/dist/patterns/global/url.js.map +1 -0
- package/dist/patterns/index.d.ts +18 -0
- package/dist/patterns/index.d.ts.map +1 -0
- package/dist/patterns/index.js +50 -0
- package/dist/patterns/index.js.map +1 -0
- package/dist/patterns/locale/en/credit-card.d.ts +3 -0
- package/dist/patterns/locale/en/credit-card.d.ts.map +1 -0
- package/dist/patterns/locale/en/credit-card.js +34 -0
- package/dist/patterns/locale/en/credit-card.js.map +1 -0
- package/dist/patterns/locale/en/phone.d.ts +3 -0
- package/dist/patterns/locale/en/phone.d.ts.map +1 -0
- package/dist/patterns/locale/en/phone.js +11 -0
- package/dist/patterns/locale/en/phone.js.map +1 -0
- package/dist/patterns/locale/en/ssn.d.ts +3 -0
- package/dist/patterns/locale/en/ssn.d.ts.map +1 -0
- package/dist/patterns/locale/en/ssn.js +30 -0
- package/dist/patterns/locale/en/ssn.js.map +1 -0
- package/dist/patterns/locale/en/zip-code.d.ts +3 -0
- package/dist/patterns/locale/en/zip-code.d.ts.map +1 -0
- package/dist/patterns/locale/en/zip-code.js +10 -0
- package/dist/patterns/locale/en/zip-code.js.map +1 -0
- package/dist/patterns/locale/pl/iban.d.ts +3 -0
- package/dist/patterns/locale/pl/iban.d.ts.map +1 -0
- package/dist/patterns/locale/pl/iban.js +11 -0
- package/dist/patterns/locale/pl/iban.js.map +1 -0
- package/dist/patterns/locale/pl/nip.d.ts +3 -0
- package/dist/patterns/locale/pl/nip.d.ts.map +1 -0
- package/dist/patterns/locale/pl/nip.js +26 -0
- package/dist/patterns/locale/pl/nip.js.map +1 -0
- package/dist/patterns/locale/pl/pesel.d.ts +3 -0
- package/dist/patterns/locale/pl/pesel.d.ts.map +1 -0
- package/dist/patterns/locale/pl/pesel.js +25 -0
- package/dist/patterns/locale/pl/pesel.js.map +1 -0
- package/dist/patterns/locale/pl/phone.d.ts +3 -0
- package/dist/patterns/locale/pl/phone.d.ts.map +1 -0
- package/dist/patterns/locale/pl/phone.js +13 -0
- package/dist/patterns/locale/pl/phone.js.map +1 -0
- package/dist/patterns/locale/pl/postal-code.d.ts +3 -0
- package/dist/patterns/locale/pl/postal-code.d.ts.map +1 -0
- package/dist/patterns/locale/pl/postal-code.js +10 -0
- package/dist/patterns/locale/pl/postal-code.js.map +1 -0
- package/dist/patterns/types.d.ts +21 -0
- package/dist/patterns/types.d.ts.map +1 -0
- package/dist/patterns/types.js +9 -0
- package/dist/patterns/types.js.map +1 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ Sits between your application and any cloud LLM (Claude, GPT-4, Gemini…). Repl
|
|
|
13
13
|
|
|
14
14
|
## What you get
|
|
15
15
|
|
|
16
|
-
- **Multi-language PII detection**: Built-in support for English (SSN, credit cards, US phone) and Polish (PESEL, IBAN, Polish phone).
|
|
16
|
+
- **Multi-language PII detection**: Built-in support for English (SSN, credit cards, US phone) and Polish (PESEL, IBAN, Polish phone). New **heuristic language detection** (`detectLanguage()`) infers the language from text content — `--lang` remains the authoritative override but is no longer the only input.
|
|
17
17
|
- **Hybrid NER engine**: Regex for structured PII (SSN, credit cards, IBAN, email, phone) + local Ollama LLM for unstructured entities (names, organizations).
|
|
18
18
|
- **Zero-trust architecture**: All detection and substitution happens on your machine. No PII reaches a third-party API.
|
|
19
19
|
- **Session-keyed mapping store**: Tokens like `[PERSON:1]` map back to originals in an isolated, per-request session. Multiple round-trips preserve token coherence.
|
|
@@ -364,6 +364,16 @@ Add to `~/.cursor/mcp.json`:
|
|
|
364
364
|
|
|
365
365
|
## Supported PII types
|
|
366
366
|
|
|
367
|
+
### Global (all languages)
|
|
368
|
+
|
|
369
|
+
| Tag | Pattern | Validation |
|
|
370
|
+
| ------- | ------------------------------------ | ------------ |
|
|
371
|
+
| `EMAIL` | RFC 5321-compatible | Format match |
|
|
372
|
+
| `IBAN` | Generic IBAN (`CC` + 2 check + BBAN) | Format match |
|
|
373
|
+
| `IP` | IPv4 (all octets 0–255) | Format match |
|
|
374
|
+
| `URL` | `http://` / `https://` URLs | Format match |
|
|
375
|
+
| `PHONE` | International `+CC` prefix format | Format match |
|
|
376
|
+
|
|
367
377
|
### English (`--lang en`, default)
|
|
368
378
|
|
|
369
379
|
| Tag | Pattern | Validation |
|
|
@@ -372,19 +382,46 @@ Add to `~/.cursor/mcp.json`:
|
|
|
372
382
|
| `CREDIT_CARD` | 13–19 digits (Visa, Mastercard, Amex, Discover) | Luhn checksum |
|
|
373
383
|
| `EMAIL` | RFC 5321-compatible | Format match |
|
|
374
384
|
| `PHONE` | `+1 (XXX) XXX-XXXX`, `XXX-XXX-XXXX`, `XXX.XXX.XXXX` | Format match |
|
|
385
|
+
| `ZIP_CODE` | `XXXXX` or `XXXXX-XXXX` (paranoid mode only) | Format match |
|
|
375
386
|
| `PERSON` | Full names | Ollama NER (hybrid / llm engines) |
|
|
376
387
|
| `ORG` | Company / organization names | Ollama NER (hybrid / llm engines) |
|
|
377
388
|
|
|
378
389
|
### Polish (`--lang pl`)
|
|
379
390
|
|
|
380
|
-
| Tag
|
|
381
|
-
|
|
|
382
|
-
| `PESEL`
|
|
383
|
-
| `IBAN`
|
|
384
|
-
| `EMAIL`
|
|
385
|
-
| `PHONE`
|
|
386
|
-
| `
|
|
387
|
-
| `
|
|
391
|
+
| Tag | Pattern | Validation |
|
|
392
|
+
| ------------- | ---------------------------------------------------------------- | ----------------------------------------------- |
|
|
393
|
+
| `PESEL` | 11-digit national ID | Full checksum (weights `[1,3,7,9,1,3,7,9,1,3]`) |
|
|
394
|
+
| `IBAN` | `PL` + 26 digits, compact or spaced | Format match |
|
|
395
|
+
| `EMAIL` | RFC 5321-compatible | Format match |
|
|
396
|
+
| `PHONE` | `+48` / `0048` prefix, 9-digit mobile, landline `(XX) XXX-XX-XX` | Format match |
|
|
397
|
+
| `NIP` | 10-digit tax ID (strict / paranoid modes) | Checksum (weights `[6,5,7,2,3,4,5,6,7]`) |
|
|
398
|
+
| `POSTAL_CODE` | `XX-XXX` (paranoid mode only) | Format match |
|
|
399
|
+
| `PERSON` | Full names | Ollama NER (hybrid / llm engines) |
|
|
400
|
+
| `ORG` | Company / organization names | Ollama NER (hybrid / llm engines) |
|
|
401
|
+
|
|
402
|
+
## Language Detection
|
|
403
|
+
|
|
404
|
+
pseudonym-mcp includes a lightweight heuristic language detector based on [`franc`](https://github.com/wooorm/franc).
|
|
405
|
+
It infers the language from text content and returns a structured result:
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
detectLanguage('Umowa zostaje zawarta na czas nieokreślony')
|
|
409
|
+
// → { detected: 'pl', source: 'text', raw: 'pol', confidence: 0.94 }
|
|
410
|
+
|
|
411
|
+
detectLanguage('Hello')
|
|
412
|
+
// → { detected: 'unknown', source: 'fallback', raw: null, confidence: null }
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
| Field | Description |
|
|
416
|
+
| ------------ | -------------------------------------------------------------------------------------- |
|
|
417
|
+
| `detected` | `'pl'`, `'en'`, or `'unknown'` |
|
|
418
|
+
| `source` | `'text'` — franc ran and mapped successfully; `'fallback'` — too short or undetermined |
|
|
419
|
+
| `raw` | Raw ISO 639-3 code from franc (e.g. `'pol'`), or `null` |
|
|
420
|
+
| `confidence` | Score 0–1 from franc, or `null` when franc was not called |
|
|
421
|
+
|
|
422
|
+
Texts shorter than 20 characters or with low confidence return `detected: 'unknown'`.
|
|
423
|
+
The detector does not affect the current pseudonymization pipeline — `--lang` config remains authoritative.
|
|
424
|
+
It is a building block for future multi-language and auto-select modes.
|
|
388
425
|
|
|
389
426
|
## Engine modes
|
|
390
427
|
|
|
@@ -411,19 +448,20 @@ git clone https://github.com/woladi/pseudonym-mcp
|
|
|
411
448
|
cd pseudonym-mcp
|
|
412
449
|
npm install
|
|
413
450
|
npm run build # tsc compile
|
|
414
|
-
npm test # vitest (
|
|
451
|
+
npm test # vitest (134 tests, no Ollama required)
|
|
415
452
|
```
|
|
416
453
|
|
|
417
454
|
The test suite runs fully offline — Ollama calls are injected via constructor and mocked in all tests. No live LLM required.
|
|
418
455
|
|
|
419
456
|
### Adding a new language pack
|
|
420
457
|
|
|
421
|
-
1.
|
|
422
|
-
2.
|
|
423
|
-
3.
|
|
424
|
-
4.
|
|
458
|
+
1. Add locale-specific patterns in `src/patterns/locale/<lang>/` — each file exports a `PatternRule` with `id`, `entityType`, `pattern`, `locales`, `engines`, and optional `validate`
|
|
459
|
+
2. Register them in `src/patterns/index.ts` (add to `allPatterns` array)
|
|
460
|
+
3. Create a thin adapter `src/languages/<lang>/rules.ts` that composes from the new patterns using `toPatternDef`
|
|
461
|
+
4. Register the adapter in `LANGUAGE_MAP` in `src/core/engine.ts`
|
|
462
|
+
5. Add the ISO 639-3 → short code mapping in `src/language/language-map.ts`
|
|
425
463
|
|
|
426
|
-
|
|
464
|
+
See `src/patterns/locale/pl/` and `src/languages/pl/rules.ts` for a complete example.
|
|
427
465
|
|
|
428
466
|
## Contributing
|
|
429
467
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DetectedLanguageResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Heuristically detect the language of the given text using franc.
|
|
4
|
+
*
|
|
5
|
+
* Returns 'unknown' when:
|
|
6
|
+
* - text is shorter than MIN_TEXT_LENGTH characters
|
|
7
|
+
* - franc returns 'und' (undetermined)
|
|
8
|
+
* - the detected language is not in LANGUAGE_CODE_MAP
|
|
9
|
+
* - confidence is below MIN_CONFIDENCE
|
|
10
|
+
*
|
|
11
|
+
* This is a helper heuristic — it does not affect the pseudonymization pipeline.
|
|
12
|
+
* The --lang config flag remains the authoritative language selector.
|
|
13
|
+
*/
|
|
14
|
+
export declare function detectLanguage(text: string): DetectedLanguageResult;
|
|
15
|
+
//# sourceMappingURL=detect-language.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-language.d.ts","sourceRoot":"","sources":["../../src/language/detect-language.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAYxD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,sBAAsB,CA8BnE"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { francAll } from 'franc';
|
|
2
|
+
import { LANGUAGE_CODE_MAP } from './language-map.js';
|
|
3
|
+
const MIN_TEXT_LENGTH = 20;
|
|
4
|
+
const MIN_CONFIDENCE = 0.5;
|
|
5
|
+
const FALLBACK = {
|
|
6
|
+
detected: 'unknown',
|
|
7
|
+
source: 'fallback',
|
|
8
|
+
raw: null,
|
|
9
|
+
confidence: null,
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Heuristically detect the language of the given text using franc.
|
|
13
|
+
*
|
|
14
|
+
* Returns 'unknown' when:
|
|
15
|
+
* - text is shorter than MIN_TEXT_LENGTH characters
|
|
16
|
+
* - franc returns 'und' (undetermined)
|
|
17
|
+
* - the detected language is not in LANGUAGE_CODE_MAP
|
|
18
|
+
* - confidence is below MIN_CONFIDENCE
|
|
19
|
+
*
|
|
20
|
+
* This is a helper heuristic — it does not affect the pseudonymization pipeline.
|
|
21
|
+
* The --lang config flag remains the authoritative language selector.
|
|
22
|
+
*/
|
|
23
|
+
export function detectLanguage(text) {
|
|
24
|
+
const trimmed = text.trim();
|
|
25
|
+
if (trimmed.length < MIN_TEXT_LENGTH) {
|
|
26
|
+
return FALLBACK;
|
|
27
|
+
}
|
|
28
|
+
const scores = francAll(trimmed);
|
|
29
|
+
if (!scores.length) {
|
|
30
|
+
return FALLBACK;
|
|
31
|
+
}
|
|
32
|
+
const [rawCode, score] = scores[0];
|
|
33
|
+
if (rawCode === 'und') {
|
|
34
|
+
return FALLBACK;
|
|
35
|
+
}
|
|
36
|
+
const mapped = LANGUAGE_CODE_MAP[rawCode];
|
|
37
|
+
if (!mapped) {
|
|
38
|
+
return { detected: 'unknown', source: 'text', raw: rawCode, confidence: score };
|
|
39
|
+
}
|
|
40
|
+
if (score < MIN_CONFIDENCE) {
|
|
41
|
+
return { detected: 'unknown', source: 'fallback', raw: rawCode, confidence: score };
|
|
42
|
+
}
|
|
43
|
+
return { detected: mapped, source: 'text', raw: rawCode, confidence: score };
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=detect-language.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-language.js","sourceRoot":"","sources":["../../src/language/detect-language.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAGrD,MAAM,eAAe,GAAG,EAAE,CAAA;AAC1B,MAAM,cAAc,GAAG,GAAG,CAAA;AAE1B,MAAM,QAAQ,GAA2B;IACvC,QAAQ,EAAE,SAAS;IACnB,MAAM,EAAE,UAAU;IAClB,GAAG,EAAE,IAAI;IACT,UAAU,EAAE,IAAI;CACjB,CAAA;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;IAE3B,IAAI,OAAO,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QACrC,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IAEhC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,CAAqB,CAAA;IAEtD,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;QACtB,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAA;IAEzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAA;IACjF,CAAC;IAED,IAAI,KAAK,GAAG,cAAc,EAAE,CAAC;QAC3B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAA;IACrF,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAA;AAC9E,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SupportedLang } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Maps ISO 639-3 codes (returned by franc) to supported short language codes.
|
|
4
|
+
* Only languages with a corresponding pattern set in src/patterns/ are listed here.
|
|
5
|
+
*/
|
|
6
|
+
export declare const LANGUAGE_CODE_MAP: Record<string, SupportedLang>;
|
|
7
|
+
//# sourceMappingURL=language-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language-map.d.ts","sourceRoot":"","sources":["../../src/language/language-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAG3D,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps ISO 639-3 codes (returned by franc) to supported short language codes.
|
|
3
|
+
* Only languages with a corresponding pattern set in src/patterns/ are listed here.
|
|
4
|
+
*/
|
|
5
|
+
export const LANGUAGE_CODE_MAP = {
|
|
6
|
+
pol: 'pl',
|
|
7
|
+
eng: 'en',
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=language-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language-map.js","sourceRoot":"","sources":["../../src/language/language-map.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAkC;IAC9D,GAAG,EAAE,IAAI;IACT,GAAG,EAAE,IAAI;CACV,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type SupportedLang = 'pl' | 'en';
|
|
2
|
+
export type DetectedLang = SupportedLang | 'unknown';
|
|
3
|
+
export type DetectionSource = 'text' | 'fallback';
|
|
4
|
+
export interface DetectedLanguageResult {
|
|
5
|
+
/** Detected language mapped to a supported code, or 'unknown' */
|
|
6
|
+
detected: DetectedLang;
|
|
7
|
+
/** 'text' = franc ran and returned a mappable language; 'fallback' = text too short or und */
|
|
8
|
+
source: DetectionSource;
|
|
9
|
+
/** Raw ISO 639-3 code from franc (e.g. 'pol'), or null when franc was not called */
|
|
10
|
+
raw: string | null;
|
|
11
|
+
/** Confidence score 0–1 from franc, or null when franc was not called */
|
|
12
|
+
confidence: number | null;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/language/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,IAAI,CAAA;AACvC,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,SAAS,CAAA;AACpD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,UAAU,CAAA;AAEjD,MAAM,WAAW,sBAAsB;IACrC,iEAAiE;IACjE,QAAQ,EAAE,YAAY,CAAA;IACtB,8FAA8F;IAC9F,MAAM,EAAE,eAAe,CAAA;IACvB,oFAAoF;IACpF,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,yEAAyE;IACzE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/language/types.ts"],"names":[],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/languages/en/rules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/languages/en/rules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAOhD,eAAO,MAAM,YAAY,EAAE,aAE1B,CAAA"}
|
|
@@ -1,69 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const digits = number.replace(/[\s-]/g, '');
|
|
7
|
-
if (!/^\d{13,19}$/.test(digits))
|
|
8
|
-
return false;
|
|
9
|
-
let sum = 0;
|
|
10
|
-
let double = false;
|
|
11
|
-
for (let i = digits.length - 1; i >= 0; i--) {
|
|
12
|
-
let digit = Number(digits[i]);
|
|
13
|
-
if (double) {
|
|
14
|
-
digit *= 2;
|
|
15
|
-
if (digit > 9)
|
|
16
|
-
digit -= 9;
|
|
17
|
-
}
|
|
18
|
-
sum += digit;
|
|
19
|
-
double = !double;
|
|
20
|
-
}
|
|
21
|
-
return sum % 10 === 0;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Basic SSN area-number validation.
|
|
25
|
-
* Rejects known invalid patterns: area 000, 666, 900-999.
|
|
26
|
-
*/
|
|
27
|
-
function ssnValidate(ssn) {
|
|
28
|
-
const clean = ssn.replace(/[\s-]/g, '');
|
|
29
|
-
if (!/^\d{9}$/.test(clean))
|
|
30
|
-
return false;
|
|
31
|
-
const area = parseInt(clean.substring(0, 3), 10);
|
|
32
|
-
const group = parseInt(clean.substring(3, 5), 10);
|
|
33
|
-
const serial = parseInt(clean.substring(5, 9), 10);
|
|
34
|
-
if (area === 0 || area === 666 || area >= 900)
|
|
35
|
-
return false;
|
|
36
|
-
if (group === 0)
|
|
37
|
-
return false;
|
|
38
|
-
if (serial === 0)
|
|
39
|
-
return false;
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
1
|
+
import { toPatternDef } from '../../patterns/types.js';
|
|
2
|
+
import { ssnRule } from '../../patterns/locale/en/ssn.js';
|
|
3
|
+
import { creditCardRule } from '../../patterns/locale/en/credit-card.js';
|
|
4
|
+
import { emailRule } from '../../patterns/global/email.js';
|
|
5
|
+
import { usPhoneRule } from '../../patterns/locale/en/phone.js';
|
|
42
6
|
export const EnglishRules = {
|
|
43
|
-
patterns: [
|
|
44
|
-
{
|
|
45
|
-
tag: 'SSN',
|
|
46
|
-
// US Social Security Number: XXX-XX-XXXX (with required dashes to avoid false positives)
|
|
47
|
-
regex: /\b\d{3}-\d{2}-\d{4}\b/g,
|
|
48
|
-
validate: ssnValidate,
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
tag: 'CREDIT_CARD',
|
|
52
|
-
// 13–19 digits, optionally separated by spaces or dashes in groups of 4
|
|
53
|
-
// Covers Visa (4xxx), Mastercard (5[1-5]xx, 2[2-7]xx), Amex (3[47]x), Discover (6xxx)
|
|
54
|
-
regex: /\b(?:\d[ -]*?){13,19}\b/g,
|
|
55
|
-
validate: luhnCheck,
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
tag: 'EMAIL',
|
|
59
|
-
regex: /\b[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}\b/g,
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
tag: 'PHONE',
|
|
63
|
-
// US/international phone formats:
|
|
64
|
-
// +1 (XXX) XXX-XXXX, +1-XXX-XXX-XXXX, (XXX) XXX-XXXX, XXX-XXX-XXXX, XXX.XXX.XXXX
|
|
65
|
-
regex: /(?:\+1[\s.-]?)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}\b/g,
|
|
66
|
-
},
|
|
67
|
-
],
|
|
7
|
+
patterns: [ssnRule, creditCardRule, emailRule, usPhoneRule].map(toPatternDef),
|
|
68
8
|
};
|
|
69
9
|
//# sourceMappingURL=rules.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../src/languages/en/rules.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../src/languages/en/rules.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAA;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAA;AAE/D,MAAM,CAAC,MAAM,YAAY,GAAkB;IACzC,QAAQ,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC;CAC9E,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/languages/pl/rules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/languages/pl/rules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAOhD,eAAO,MAAM,WAAW,EAAE,aAEzB,CAAA"}
|
|
@@ -1,44 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
function peselChecksum(pesel) {
|
|
7
|
-
if (!/^\d{11}$/.test(pesel))
|
|
8
|
-
return false;
|
|
9
|
-
const weights = [1, 3, 7, 9, 1, 3, 7, 9, 1, 3];
|
|
10
|
-
const digits = pesel.split('').map(Number);
|
|
11
|
-
const sum = weights.reduce((acc, w, i) => acc + w * digits[i], 0);
|
|
12
|
-
const check = (10 - (sum % 10)) % 10;
|
|
13
|
-
return check === digits[10];
|
|
14
|
-
}
|
|
1
|
+
import { toPatternDef } from '../../patterns/types.js';
|
|
2
|
+
import { peselRule } from '../../patterns/locale/pl/pesel.js';
|
|
3
|
+
import { plIbanRule } from '../../patterns/locale/pl/iban.js';
|
|
4
|
+
import { plPhoneRule } from '../../patterns/locale/pl/phone.js';
|
|
5
|
+
import { emailRule } from '../../patterns/global/email.js';
|
|
15
6
|
export const PolishRules = {
|
|
16
|
-
patterns: [
|
|
17
|
-
{
|
|
18
|
-
tag: 'PESEL',
|
|
19
|
-
// Matches exactly 11 consecutive digits NOT adjacent to another digit
|
|
20
|
-
regex: /(?<!\d)\d{11}(?!\d)/g,
|
|
21
|
-
validate: peselChecksum,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
tag: 'IBAN',
|
|
25
|
-
// Matches PL + 26 digits (2 check + 24 BBAN), optionally space-separated every 4 chars
|
|
26
|
-
// e.g. PL27114020040000300201355387 or PL 27 1140 2004 0000 3002 0135 5387
|
|
27
|
-
// Structure: PL + \d{2} (check) + (\d{4}){6} (24 BBAN) = 26 total digits
|
|
28
|
-
regex: /\bPL\s*\d{2}\s*(?:\d{4}\s*){6}\b/gi,
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
tag: 'EMAIL',
|
|
32
|
-
regex: /\b[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}\b/g,
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
tag: 'PHONE',
|
|
36
|
-
// Three alternatives:
|
|
37
|
-
// 1. International prefix: +48 or 0048, then 9 digits (with optional spaces/dashes)
|
|
38
|
-
// 2. 9-digit mobile starting with 4–8 (Polish numbering plan)
|
|
39
|
-
// 3. Landline with area code in parens: (XX) XXX-XX-XX
|
|
40
|
-
regex: /(?:\+48|0048)[\s\-]?\d{3}[\s\-]?\d{3}[\s\-]?\d{3}|\b[4-8]\d{2}[\s\-]?\d{3}[\s\-]?\d{3}\b|\(\d{2}\)[\s\-]?\d{3}[\s\-]?\d{2}[\s\-]?\d{2}/g,
|
|
41
|
-
},
|
|
42
|
-
],
|
|
7
|
+
patterns: [peselRule, plIbanRule, emailRule, plPhoneRule].map(toPatternDef),
|
|
43
8
|
};
|
|
44
9
|
//# sourceMappingURL=rules.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../src/languages/pl/rules.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../src/languages/pl/rules.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAA;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAA;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAA;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAA;AAE1D,MAAM,CAAC,MAAM,WAAW,GAAkB;IACxC,QAAQ,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC;CAC5E,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"balanced.d.ts","sourceRoot":"","sources":["../../../src/patterns/engines/balanced.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,qFAAqF;AACrF,eAAO,MAAM,gBAAgB,EAAE,WAAW,EAEzC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"balanced.js","sourceRoot":"","sources":["../../../src/patterns/engines/balanced.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGzC,qFAAqF;AACrF,MAAM,CAAC,MAAM,gBAAgB,GAAkB,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACtE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAC/B,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paranoid.d.ts","sourceRoot":"","sources":["../../../src/patterns/engines/paranoid.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,kEAAkE;AAClE,eAAO,MAAM,gBAAgB,EAAE,WAAW,EAEzC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paranoid.js","sourceRoot":"","sources":["../../../src/patterns/engines/paranoid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGzC,kEAAkE;AAClE,MAAM,CAAC,MAAM,gBAAgB,GAAkB,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACtE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAC/B,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strict.d.ts","sourceRoot":"","sources":["../../../src/patterns/engines/strict.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,0FAA0F;AAC1F,eAAO,MAAM,cAAc,EAAE,WAAW,EAA4D,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strict.js","sourceRoot":"","sources":["../../../src/patterns/engines/strict.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGzC,0FAA0F;AAC1F,MAAM,CAAC,MAAM,cAAc,GAAkB,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../../../src/patterns/global/email.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,eAAO,MAAM,SAAS,EAAE,WAOvB,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const emailRule = {
|
|
2
|
+
id: 'global.email',
|
|
3
|
+
entityType: 'EMAIL',
|
|
4
|
+
pattern: /\b[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}\b/g,
|
|
5
|
+
locales: null,
|
|
6
|
+
engines: ['balanced', 'strict', 'paranoid'],
|
|
7
|
+
description: 'Standard email address (RFC 5321-compatible)',
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=email.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email.js","sourceRoot":"","sources":["../../../src/patterns/global/email.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAgB;IACpC,EAAE,EAAE,cAAc;IAClB,UAAU,EAAE,OAAO;IACnB,OAAO,EAAE,uDAAuD;IAChE,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC;IAC3C,WAAW,EAAE,8CAA8C;CAC5D,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iban.d.ts","sourceRoot":"","sources":["../../../src/patterns/global/iban.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,eAAO,MAAM,cAAc,EAAE,WAS5B,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const globalIbanRule = {
|
|
2
|
+
id: 'global.iban',
|
|
3
|
+
entityType: 'IBAN',
|
|
4
|
+
// Generic IBAN: 2-letter country code + 2 check digits + up to 30 alphanumeric chars
|
|
5
|
+
// Covers all IBAN countries (max length 34 chars)
|
|
6
|
+
pattern: /\b[A-Z]{2}\d{2}[A-Z0-9]{1,30}\b/g,
|
|
7
|
+
locales: null,
|
|
8
|
+
engines: ['strict', 'paranoid'],
|
|
9
|
+
description: 'Generic IBAN (any country, compact format)',
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=iban.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iban.js","sourceRoot":"","sources":["../../../src/patterns/global/iban.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,EAAE,EAAE,aAAa;IACjB,UAAU,EAAE,MAAM;IAClB,qFAAqF;IACrF,kDAAkD;IAClD,OAAO,EAAE,kCAAkC;IAC3C,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC/B,WAAW,EAAE,4CAA4C;CAC1D,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ip.d.ts","sourceRoot":"","sources":["../../../src/patterns/global/ip.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,eAAO,MAAM,QAAQ,EAAE,WAStB,CAAA;AAED,eAAO,MAAM,QAAQ,EAAE,WAStB,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const ipv4Rule = {
|
|
2
|
+
id: 'global.ipv4',
|
|
3
|
+
entityType: 'IP',
|
|
4
|
+
// IPv4: four octets 0–255 separated by dots, not adjacent to other digits/dots
|
|
5
|
+
pattern: /\b(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\b/g,
|
|
6
|
+
locales: null,
|
|
7
|
+
engines: ['strict', 'paranoid'],
|
|
8
|
+
description: 'IPv4 address (0.0.0.0 – 255.255.255.255)',
|
|
9
|
+
};
|
|
10
|
+
export const ipv6Rule = {
|
|
11
|
+
id: 'global.ipv6',
|
|
12
|
+
entityType: 'IP',
|
|
13
|
+
// Full or compressed IPv6: groups of 1–4 hex digits separated by colons
|
|
14
|
+
// Handles :: abbreviation and mixed IPv4-in-IPv6 forms at a basic level
|
|
15
|
+
pattern: /\b(?:[0-9a-fA-F]{1,4}:){2,7}[0-9a-fA-F]{1,4}\b/g,
|
|
16
|
+
locales: null,
|
|
17
|
+
engines: ['paranoid'],
|
|
18
|
+
description: 'IPv6 address (basic hex-colon format)',
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=ip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ip.js","sourceRoot":"","sources":["../../../src/patterns/global/ip.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,QAAQ,GAAgB;IACnC,EAAE,EAAE,aAAa;IACjB,UAAU,EAAE,IAAI;IAChB,+EAA+E;IAC/E,OAAO,EACL,4FAA4F;IAC9F,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC/B,WAAW,EAAE,0CAA0C;CACxD,CAAA;AAED,MAAM,CAAC,MAAM,QAAQ,GAAgB;IACnC,EAAE,EAAE,aAAa;IACjB,UAAU,EAAE,IAAI;IAChB,wEAAwE;IACxE,wEAAwE;IACxE,OAAO,EAAE,iDAAiD;IAC1D,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,CAAC,UAAU,CAAC;IACrB,WAAW,EAAE,uCAAuC;CACrD,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phone.d.ts","sourceRoot":"","sources":["../../../src/patterns/global/phone.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,eAAO,MAAM,eAAe,EAAE,WAS7B,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const globalPhoneRule = {
|
|
2
|
+
id: 'global.phone',
|
|
3
|
+
entityType: 'PHONE',
|
|
4
|
+
// Generic international format: +CC followed by digits/spaces/dashes
|
|
5
|
+
// e.g. +1-800-555-1234, +44 20 7946 0958, +33 1 23 45 67 89
|
|
6
|
+
pattern: /\+\d{1,3}[\s.\-]?\(?\d{1,4}\)?(?:[\s.\-]?\d{1,4}){2,4}\b/g,
|
|
7
|
+
locales: null,
|
|
8
|
+
engines: ['strict', 'paranoid'],
|
|
9
|
+
description: 'Generic international phone number with country code prefix',
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=phone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phone.js","sourceRoot":"","sources":["../../../src/patterns/global/phone.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAgB;IAC1C,EAAE,EAAE,cAAc;IAClB,UAAU,EAAE,OAAO;IACnB,qEAAqE;IACrE,4DAA4D;IAC5D,OAAO,EAAE,2DAA2D;IACpE,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC/B,WAAW,EAAE,6DAA6D;CAC3E,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../../src/patterns/global/url.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,eAAO,MAAM,OAAO,EAAE,WAQrB,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const urlRule = {
|
|
2
|
+
id: 'global.url',
|
|
3
|
+
entityType: 'URL',
|
|
4
|
+
// http/https URLs — stops at whitespace and common delimiter characters
|
|
5
|
+
pattern: /https?:\/\/[^\s<>"{}\\|^[\]]+/g,
|
|
6
|
+
locales: null,
|
|
7
|
+
engines: ['paranoid'],
|
|
8
|
+
description: 'HTTP/HTTPS URL',
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../../src/patterns/global/url.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAgB;IAClC,EAAE,EAAE,YAAY;IAChB,UAAU,EAAE,KAAK;IACjB,wEAAwE;IACxE,OAAO,EAAE,gCAAgC;IACzC,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,CAAC,UAAU,CAAC;IACrB,WAAW,EAAE,gBAAgB;CAC9B,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PatternRule } from './types.js';
|
|
2
|
+
export * from './types.js';
|
|
3
|
+
export * from './global/email.js';
|
|
4
|
+
export * from './global/phone.js';
|
|
5
|
+
export * from './global/iban.js';
|
|
6
|
+
export * from './global/ip.js';
|
|
7
|
+
export * from './global/url.js';
|
|
8
|
+
export * from './locale/pl/pesel.js';
|
|
9
|
+
export * from './locale/pl/iban.js';
|
|
10
|
+
export * from './locale/pl/phone.js';
|
|
11
|
+
export * from './locale/pl/nip.js';
|
|
12
|
+
export * from './locale/pl/postal-code.js';
|
|
13
|
+
export * from './locale/en/ssn.js';
|
|
14
|
+
export * from './locale/en/credit-card.js';
|
|
15
|
+
export * from './locale/en/phone.js';
|
|
16
|
+
export * from './locale/en/zip-code.js';
|
|
17
|
+
export declare const allPatterns: PatternRule[];
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/patterns/index.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,cAAc,YAAY,CAAA;AAE1B,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,oBAAoB,CAAA;AAClC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AAEvC,eAAO,MAAM,WAAW,EAAE,WAAW,EAmBpC,CAAA"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { emailRule } from './global/email.js';
|
|
2
|
+
import { globalPhoneRule } from './global/phone.js';
|
|
3
|
+
import { globalIbanRule } from './global/iban.js';
|
|
4
|
+
import { ipv4Rule, ipv6Rule } from './global/ip.js';
|
|
5
|
+
import { urlRule } from './global/url.js';
|
|
6
|
+
import { peselRule } from './locale/pl/pesel.js';
|
|
7
|
+
import { plIbanRule } from './locale/pl/iban.js';
|
|
8
|
+
import { plPhoneRule } from './locale/pl/phone.js';
|
|
9
|
+
import { nipRule } from './locale/pl/nip.js';
|
|
10
|
+
import { plPostalCodeRule } from './locale/pl/postal-code.js';
|
|
11
|
+
import { ssnRule } from './locale/en/ssn.js';
|
|
12
|
+
import { creditCardRule } from './locale/en/credit-card.js';
|
|
13
|
+
import { usPhoneRule } from './locale/en/phone.js';
|
|
14
|
+
import { usZipCodeRule } from './locale/en/zip-code.js';
|
|
15
|
+
export * from './types.js';
|
|
16
|
+
export * from './global/email.js';
|
|
17
|
+
export * from './global/phone.js';
|
|
18
|
+
export * from './global/iban.js';
|
|
19
|
+
export * from './global/ip.js';
|
|
20
|
+
export * from './global/url.js';
|
|
21
|
+
export * from './locale/pl/pesel.js';
|
|
22
|
+
export * from './locale/pl/iban.js';
|
|
23
|
+
export * from './locale/pl/phone.js';
|
|
24
|
+
export * from './locale/pl/nip.js';
|
|
25
|
+
export * from './locale/pl/postal-code.js';
|
|
26
|
+
export * from './locale/en/ssn.js';
|
|
27
|
+
export * from './locale/en/credit-card.js';
|
|
28
|
+
export * from './locale/en/phone.js';
|
|
29
|
+
export * from './locale/en/zip-code.js';
|
|
30
|
+
export const allPatterns = [
|
|
31
|
+
// Global
|
|
32
|
+
emailRule,
|
|
33
|
+
globalPhoneRule,
|
|
34
|
+
globalIbanRule,
|
|
35
|
+
ipv4Rule,
|
|
36
|
+
ipv6Rule,
|
|
37
|
+
urlRule,
|
|
38
|
+
// Polish locale
|
|
39
|
+
peselRule,
|
|
40
|
+
plIbanRule,
|
|
41
|
+
plPhoneRule,
|
|
42
|
+
nipRule,
|
|
43
|
+
plPostalCodeRule,
|
|
44
|
+
// English locale
|
|
45
|
+
ssnRule,
|
|
46
|
+
creditCardRule,
|
|
47
|
+
usPhoneRule,
|
|
48
|
+
usZipCodeRule,
|
|
49
|
+
];
|
|
50
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/patterns/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAGvD,cAAc,YAAY,CAAA;AAE1B,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,oBAAoB,CAAA;AAClC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AAEvC,MAAM,CAAC,MAAM,WAAW,GAAkB;IACxC,SAAS;IACT,SAAS;IACT,eAAe;IACf,cAAc;IACd,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,gBAAgB;IAChB,SAAS;IACT,UAAU;IACV,WAAW;IACX,OAAO;IACP,gBAAgB;IAChB,iBAAiB;IACjB,OAAO;IACP,cAAc;IACd,WAAW;IACX,aAAa;CACd,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credit-card.d.ts","sourceRoot":"","sources":["../../../../src/patterns/locale/en/credit-card.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAwBjD,eAAO,MAAM,cAAc,EAAE,WAW5B,CAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Luhn algorithm for credit card number validation.
|
|
3
|
+
* Strips spaces and dashes, verifies the checksum digit.
|
|
4
|
+
*/
|
|
5
|
+
function luhnCheck(number) {
|
|
6
|
+
const digits = number.replace(/[\s\-]/g, '');
|
|
7
|
+
if (!/^\d{13,19}$/.test(digits))
|
|
8
|
+
return false;
|
|
9
|
+
let sum = 0;
|
|
10
|
+
let double = false;
|
|
11
|
+
for (let i = digits.length - 1; i >= 0; i--) {
|
|
12
|
+
let digit = Number(digits[i]);
|
|
13
|
+
if (double) {
|
|
14
|
+
digit *= 2;
|
|
15
|
+
if (digit > 9)
|
|
16
|
+
digit -= 9;
|
|
17
|
+
}
|
|
18
|
+
sum += digit;
|
|
19
|
+
double = !double;
|
|
20
|
+
}
|
|
21
|
+
return sum % 10 === 0;
|
|
22
|
+
}
|
|
23
|
+
export const creditCardRule = {
|
|
24
|
+
id: 'en.credit-card',
|
|
25
|
+
entityType: 'CREDIT_CARD',
|
|
26
|
+
// 13–19 digits, optionally separated by spaces or dashes in groups of 4
|
|
27
|
+
// Covers Visa (4xxx), Mastercard (5[1-5]xx / 2[2-7]xx), Amex (3[47]x), Discover (6xxx)
|
|
28
|
+
pattern: /\b(?:\d[ \-]*?){13,19}\b/g,
|
|
29
|
+
locales: ['en'],
|
|
30
|
+
engines: ['balanced', 'strict', 'paranoid'],
|
|
31
|
+
description: 'Credit card number (13–19 digits, Luhn checksum) — Visa, Mastercard, Amex, Discover',
|
|
32
|
+
validate: luhnCheck,
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=credit-card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credit-card.js","sourceRoot":"","sources":["../../../../src/patterns/locale/en/credit-card.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,SAAS,SAAS,CAAC,MAAc;IAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;IAC5C,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAA;IAE7C,IAAI,GAAG,GAAG,CAAC,CAAA;IACX,IAAI,MAAM,GAAG,KAAK,CAAA;IAClB,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,IAAI,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;QAC7B,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,IAAI,CAAC,CAAA;YACV,IAAI,KAAK,GAAG,CAAC;gBAAE,KAAK,IAAI,CAAC,CAAA;QAC3B,CAAC;QACD,GAAG,IAAI,KAAK,CAAA;QACZ,MAAM,GAAG,CAAC,MAAM,CAAA;IAClB,CAAC;IACD,OAAO,GAAG,GAAG,EAAE,KAAK,CAAC,CAAA;AACvB,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,EAAE,EAAE,gBAAgB;IACpB,UAAU,EAAE,aAAa;IACzB,wEAAwE;IACxE,uFAAuF;IACvF,OAAO,EAAE,2BAA2B;IACpC,OAAO,EAAE,CAAC,IAAI,CAAC;IACf,OAAO,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC;IAC3C,WAAW,EACT,qFAAqF;IACvF,QAAQ,EAAE,SAAS;CACpB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phone.d.ts","sourceRoot":"","sources":["../../../../src/patterns/locale/en/phone.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD,eAAO,MAAM,WAAW,EAAE,WASzB,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const usPhoneRule = {
|
|
2
|
+
id: 'en.phone',
|
|
3
|
+
entityType: 'PHONE',
|
|
4
|
+
// US/North America phone formats:
|
|
5
|
+
// +1 (XXX) XXX-XXXX, +1-XXX-XXX-XXXX, (XXX) XXX-XXXX, XXX-XXX-XXXX, XXX.XXX.XXXX
|
|
6
|
+
pattern: /(?:\+1[\s.\-]?)?\(?\d{3}\)?[\s.\-]\d{3}[\s.\-]\d{4}\b/g,
|
|
7
|
+
locales: ['en'],
|
|
8
|
+
engines: ['balanced', 'strict', 'paranoid'],
|
|
9
|
+
description: 'US/North America phone number in common formats',
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=phone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phone.js","sourceRoot":"","sources":["../../../../src/patterns/locale/en/phone.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAgB;IACtC,EAAE,EAAE,UAAU;IACd,UAAU,EAAE,OAAO;IACnB,kCAAkC;IAClC,iFAAiF;IACjF,OAAO,EAAE,wDAAwD;IACjE,OAAO,EAAE,CAAC,IAAI,CAAC;IACf,OAAO,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC;IAC3C,WAAW,EAAE,iDAAiD;CAC/D,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssn.d.ts","sourceRoot":"","sources":["../../../../src/patterns/locale/en/ssn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAkBjD,eAAO,MAAM,OAAO,EAAE,WASrB,CAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic SSN area-number validation.
|
|
3
|
+
* Rejects known invalid patterns: area 000, 666, 900-999.
|
|
4
|
+
*/
|
|
5
|
+
function ssnValidate(ssn) {
|
|
6
|
+
const clean = ssn.replace(/[\s\-]/g, '');
|
|
7
|
+
if (!/^\d{9}$/.test(clean))
|
|
8
|
+
return false;
|
|
9
|
+
const area = parseInt(clean.substring(0, 3), 10);
|
|
10
|
+
const group = parseInt(clean.substring(3, 5), 10);
|
|
11
|
+
const serial = parseInt(clean.substring(5, 9), 10);
|
|
12
|
+
if (area === 0 || area === 666 || area >= 900)
|
|
13
|
+
return false;
|
|
14
|
+
if (group === 0)
|
|
15
|
+
return false;
|
|
16
|
+
if (serial === 0)
|
|
17
|
+
return false;
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
export const ssnRule = {
|
|
21
|
+
id: 'en.ssn',
|
|
22
|
+
entityType: 'SSN',
|
|
23
|
+
// US Social Security Number: XXX-XX-XXXX (required dashes to avoid false positives)
|
|
24
|
+
pattern: /\b\d{3}-\d{2}-\d{4}\b/g,
|
|
25
|
+
locales: ['en'],
|
|
26
|
+
engines: ['balanced', 'strict', 'paranoid'],
|
|
27
|
+
description: 'US Social Security Number (XXX-XX-XXXX) with area-number validation',
|
|
28
|
+
validate: ssnValidate,
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=ssn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssn.js","sourceRoot":"","sources":["../../../../src/patterns/locale/en/ssn.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;IACxC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACxC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAChD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACjD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAClD,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,IAAI,GAAG;QAAE,OAAO,KAAK,CAAA;IAC3D,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IAC7B,IAAI,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IAC9B,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAgB;IAClC,EAAE,EAAE,QAAQ;IACZ,UAAU,EAAE,KAAK;IACjB,oFAAoF;IACpF,OAAO,EAAE,wBAAwB;IACjC,OAAO,EAAE,CAAC,IAAI,CAAC;IACf,OAAO,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC;IAC3C,WAAW,EAAE,qEAAqE;IAClF,QAAQ,EAAE,WAAW;CACtB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zip-code.d.ts","sourceRoot":"","sources":["../../../../src/patterns/locale/en/zip-code.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD,eAAO,MAAM,aAAa,EAAE,WAQ3B,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const usZipCodeRule = {
|
|
2
|
+
id: 'en.zip-code',
|
|
3
|
+
entityType: 'ZIP_CODE',
|
|
4
|
+
// US ZIP code: 5 digits, or ZIP+4 (XXXXX-XXXX)
|
|
5
|
+
pattern: /\b\d{5}(?:-\d{4})?\b/g,
|
|
6
|
+
locales: ['en'],
|
|
7
|
+
engines: ['paranoid'],
|
|
8
|
+
description: 'US ZIP code (XXXXX or XXXXX-XXXX)',
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=zip-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zip-code.js","sourceRoot":"","sources":["../../../../src/patterns/locale/en/zip-code.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAgB;IACxC,EAAE,EAAE,aAAa;IACjB,UAAU,EAAE,UAAU;IACtB,+CAA+C;IAC/C,OAAO,EAAE,uBAAuB;IAChC,OAAO,EAAE,CAAC,IAAI,CAAC;IACf,OAAO,EAAE,CAAC,UAAU,CAAC;IACrB,WAAW,EAAE,mCAAmC;CACjD,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iban.d.ts","sourceRoot":"","sources":["../../../../src/patterns/locale/pl/iban.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD,eAAO,MAAM,UAAU,EAAE,WASxB,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const plIbanRule = {
|
|
2
|
+
id: 'pl.iban',
|
|
3
|
+
entityType: 'IBAN',
|
|
4
|
+
// PL + 2 check digits + 24 BBAN digits, optionally space-separated every 4 chars
|
|
5
|
+
// e.g. PL27114020040000300201355387 or PL 27 1140 2004 0000 3002 0135 5387
|
|
6
|
+
pattern: /\bPL\s*\d{2}\s*(?:\d{4}\s*){6}\b/gi,
|
|
7
|
+
locales: ['pl'],
|
|
8
|
+
engines: ['balanced', 'strict', 'paranoid'],
|
|
9
|
+
description: 'Polish IBAN (PL prefix + 26 digits, compact or spaced)',
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=iban.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iban.js","sourceRoot":"","sources":["../../../../src/patterns/locale/pl/iban.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,UAAU,GAAgB;IACrC,EAAE,EAAE,SAAS;IACb,UAAU,EAAE,MAAM;IAClB,iFAAiF;IACjF,2EAA2E;IAC3E,OAAO,EAAE,oCAAoC;IAC7C,OAAO,EAAE,CAAC,IAAI,CAAC;IACf,OAAO,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC;IAC3C,WAAW,EAAE,wDAAwD;CACtE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nip.d.ts","sourceRoot":"","sources":["../../../../src/patterns/locale/pl/nip.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAiBjD,eAAO,MAAM,OAAO,EAAE,WASrB,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates a Polish NIP (Numer Identyfikacji Podatkowej — Tax ID).
|
|
3
|
+
* 10 digits, weights: [6, 5, 7, 2, 3, 4, 5, 6, 7]
|
|
4
|
+
* Check digit = weighted_sum % 11; valid if result equals last digit (and != 10)
|
|
5
|
+
*/
|
|
6
|
+
function nipChecksum(raw) {
|
|
7
|
+
const digits = raw.replace(/[\s\-]/g, '');
|
|
8
|
+
if (!/^\d{10}$/.test(digits))
|
|
9
|
+
return false;
|
|
10
|
+
const weights = [6, 5, 7, 2, 3, 4, 5, 6, 7];
|
|
11
|
+
const d = digits.split('').map(Number);
|
|
12
|
+
const sum = weights.reduce((acc, w, i) => acc + w * d[i], 0);
|
|
13
|
+
const check = sum % 11;
|
|
14
|
+
return check !== 10 && check === d[9];
|
|
15
|
+
}
|
|
16
|
+
export const nipRule = {
|
|
17
|
+
id: 'pl.nip',
|
|
18
|
+
entityType: 'NIP',
|
|
19
|
+
// 10 digits, optionally separated by spaces or dashes in groups: XXX-XXX-XX-XX or XXX-XX-XX-XXX
|
|
20
|
+
pattern: /\b\d{3}[\s\-]?\d{3}[\s\-]?\d{2}[\s\-]?\d{2}\b/g,
|
|
21
|
+
locales: ['pl'],
|
|
22
|
+
engines: ['strict', 'paranoid'],
|
|
23
|
+
description: 'Polish tax identification number (NIP) — 10 digits with checksum',
|
|
24
|
+
validate: nipChecksum,
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=nip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nip.js","sourceRoot":"","sources":["../../../../src/patterns/locale/pl/nip.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;IACzC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAA;IAC1C,MAAM,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IAC3C,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IACtC,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC5D,MAAM,KAAK,GAAG,GAAG,GAAG,EAAE,CAAA;IACtB,OAAO,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAgB;IAClC,EAAE,EAAE,QAAQ;IACZ,UAAU,EAAE,KAAK;IACjB,gGAAgG;IAChG,OAAO,EAAE,gDAAgD;IACzD,OAAO,EAAE,CAAC,IAAI,CAAC;IACf,OAAO,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC/B,WAAW,EAAE,kEAAkE;IAC/E,QAAQ,EAAE,WAAW;CACtB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pesel.d.ts","sourceRoot":"","sources":["../../../../src/patterns/locale/pl/pesel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAgBjD,eAAO,MAAM,SAAS,EAAE,WASvB,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates a Polish PESEL number using the official checksum algorithm.
|
|
3
|
+
* Weights: [1, 3, 7, 9, 1, 3, 7, 9, 1, 3]
|
|
4
|
+
* Check digit = (10 - (weighted_sum % 10)) % 10
|
|
5
|
+
*/
|
|
6
|
+
function peselChecksum(pesel) {
|
|
7
|
+
if (!/^\d{11}$/.test(pesel))
|
|
8
|
+
return false;
|
|
9
|
+
const weights = [1, 3, 7, 9, 1, 3, 7, 9, 1, 3];
|
|
10
|
+
const digits = pesel.split('').map(Number);
|
|
11
|
+
const sum = weights.reduce((acc, w, i) => acc + w * digits[i], 0);
|
|
12
|
+
const check = (10 - (sum % 10)) % 10;
|
|
13
|
+
return check === digits[10];
|
|
14
|
+
}
|
|
15
|
+
export const peselRule = {
|
|
16
|
+
id: 'pl.pesel',
|
|
17
|
+
entityType: 'PESEL',
|
|
18
|
+
// Exactly 11 consecutive digits NOT adjacent to another digit
|
|
19
|
+
pattern: /(?<!\d)\d{11}(?!\d)/g,
|
|
20
|
+
locales: ['pl'],
|
|
21
|
+
engines: ['balanced', 'strict', 'paranoid'],
|
|
22
|
+
description: 'Polish national identification number (PESEL) — 11 digits with checksum',
|
|
23
|
+
validate: peselChecksum,
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=pesel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pesel.js","sourceRoot":"","sources":["../../../../src/patterns/locale/pl/pesel.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,SAAS,aAAa,CAAC,KAAa;IAClC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACzC,MAAM,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACjE,MAAM,KAAK,GAAG,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAA;IACpC,OAAO,KAAK,KAAK,MAAM,CAAC,EAAE,CAAC,CAAA;AAC7B,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAgB;IACpC,EAAE,EAAE,UAAU;IACd,UAAU,EAAE,OAAO;IACnB,8DAA8D;IAC9D,OAAO,EAAE,sBAAsB;IAC/B,OAAO,EAAE,CAAC,IAAI,CAAC;IACf,OAAO,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC;IAC3C,WAAW,EAAE,yEAAyE;IACtF,QAAQ,EAAE,aAAa;CACxB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phone.d.ts","sourceRoot":"","sources":["../../../../src/patterns/locale/pl/phone.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD,eAAO,MAAM,WAAW,EAAE,WAYzB,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const plPhoneRule = {
|
|
2
|
+
id: 'pl.phone',
|
|
3
|
+
entityType: 'PHONE',
|
|
4
|
+
// Three alternatives:
|
|
5
|
+
// 1. International prefix: +48 or 0048, then 9 digits (with optional spaces/dashes)
|
|
6
|
+
// 2. 9-digit mobile starting with 4–8 (Polish numbering plan)
|
|
7
|
+
// 3. Landline with area code in parens: (XX) XXX-XX-XX
|
|
8
|
+
pattern: /(?:\+48|0048)[\s\-]?\d{3}[\s\-]?\d{3}[\s\-]?\d{3}|\b[4-8]\d{2}[\s\-]?\d{3}[\s\-]?\d{3}\b|\(\d{2}\)[\s\-]?\d{3}[\s\-]?\d{2}[\s\-]?\d{2}/g,
|
|
9
|
+
locales: ['pl'],
|
|
10
|
+
engines: ['balanced', 'strict', 'paranoid'],
|
|
11
|
+
description: 'Polish phone number (+48 / 0048 prefix, 9-digit mobile, landline)',
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=phone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phone.js","sourceRoot":"","sources":["../../../../src/patterns/locale/pl/phone.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAgB;IACtC,EAAE,EAAE,UAAU;IACd,UAAU,EAAE,OAAO;IACnB,sBAAsB;IACtB,oFAAoF;IACpF,8DAA8D;IAC9D,uDAAuD;IACvD,OAAO,EACL,yIAAyI;IAC3I,OAAO,EAAE,CAAC,IAAI,CAAC;IACf,OAAO,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC;IAC3C,WAAW,EAAE,mEAAmE;CACjF,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postal-code.d.ts","sourceRoot":"","sources":["../../../../src/patterns/locale/pl/postal-code.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD,eAAO,MAAM,gBAAgB,EAAE,WAQ9B,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const plPostalCodeRule = {
|
|
2
|
+
id: 'pl.postal-code',
|
|
3
|
+
entityType: 'POSTAL_CODE',
|
|
4
|
+
// Polish postal code: XX-XXX (e.g. 00-001, 80-952)
|
|
5
|
+
pattern: /\b\d{2}-\d{3}\b/g,
|
|
6
|
+
locales: ['pl'],
|
|
7
|
+
engines: ['paranoid'],
|
|
8
|
+
description: 'Polish postal code (XX-XXX format)',
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=postal-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postal-code.js","sourceRoot":"","sources":["../../../../src/patterns/locale/pl/postal-code.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,gBAAgB,GAAgB;IAC3C,EAAE,EAAE,gBAAgB;IACpB,UAAU,EAAE,aAAa;IACzB,mDAAmD;IACnD,OAAO,EAAE,kBAAkB;IAC3B,OAAO,EAAE,CAAC,IAAI,CAAC;IACf,OAAO,EAAE,CAAC,UAAU,CAAC;IACrB,WAAW,EAAE,oCAAoC;CAClD,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PatternDef } from '../languages/types.js';
|
|
2
|
+
export type EngineLevel = 'balanced' | 'strict' | 'paranoid';
|
|
3
|
+
export type SupportedLocale = 'pl' | 'en';
|
|
4
|
+
export interface PatternRule {
|
|
5
|
+
/** Unique identifier, e.g. 'global.email' or 'pl.pesel' */
|
|
6
|
+
id: string;
|
|
7
|
+
/** Token tag used in replacement, e.g. 'EMAIL', 'PESEL' */
|
|
8
|
+
entityType: string;
|
|
9
|
+
/** Regex with 'g' flag */
|
|
10
|
+
pattern: RegExp;
|
|
11
|
+
/** null = applies to all locales (global); otherwise locale-specific */
|
|
12
|
+
locales: SupportedLocale[] | null;
|
|
13
|
+
/** Which engine levels activate this rule */
|
|
14
|
+
engines: EngineLevel[];
|
|
15
|
+
description: string;
|
|
16
|
+
/** Optional post-match validator. Receives the match with whitespace stripped. */
|
|
17
|
+
validate?: (match: string) => boolean;
|
|
18
|
+
}
|
|
19
|
+
/** Adapter: converts a PatternRule to the PatternDef format used by Engine */
|
|
20
|
+
export declare function toPatternDef(rule: PatternRule): PatternDef;
|
|
21
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/patterns/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAEvD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAA;AAC5D,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,CAAA;AAEzC,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,EAAE,EAAE,MAAM,CAAA;IACV,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAA;IAClB,0BAA0B;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,wEAAwE;IACxE,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI,CAAA;IACjC,6CAA6C;IAC7C,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAA;CACtC;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,CAM1D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/patterns/types.ts"],"names":[],"mappings":"AAqBA,8EAA8E;AAC9E,MAAM,UAAU,YAAY,CAAC,IAAiB;IAC5C,OAAO;QACL,GAAG,EAAE,IAAI,CAAC,UAAU;QACpB,KAAK,EAAE,IAAI,CAAC,OAAO;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAA;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pseudonym-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"mcpName": "io.github.woladi/pseudonym-mcp",
|
|
5
5
|
"description": "MCP server for privacy-preserving pseudonymization of sensitive data before cloud LLM processing",
|
|
6
6
|
"type": "module",
|
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
"dependencies": {
|
|
85
85
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
86
86
|
"commander": "^14.0.0",
|
|
87
|
+
"franc": "^6.2.0",
|
|
87
88
|
"zod": "^3.25.0"
|
|
88
89
|
},
|
|
89
90
|
"devDependencies": {
|