euredact 0.1.0 → 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 +366 -43
- package/dist/cjs/cache.js +2 -2
- package/dist/cjs/index.js +14 -1
- package/dist/cjs/normalizer.js +16 -18
- package/dist/cjs/rules/bicRegistry.js +239 -0
- package/dist/cjs/rules/countries/index.js +119 -2
- package/dist/cjs/rules/engine.js +180 -27
- package/dist/cjs/rules/matchers.js +8 -1
- package/dist/cjs/rules/suppressors.js +246 -9
- package/dist/cjs/rules/validators.js +92 -12
- package/dist/cjs/sdk.js +30 -6
- package/dist/cjs/types.js +19 -2
- package/dist/esm/cache.js +2 -2
- package/dist/esm/index.d.ts +4 -1
- package/dist/esm/index.js +8 -1
- package/dist/esm/normalizer.js +16 -18
- package/dist/esm/rules/bicRegistry.d.ts +50 -0
- package/dist/esm/rules/bicRegistry.js +233 -0
- package/dist/esm/rules/countries/index.js +119 -2
- package/dist/esm/rules/engine.d.ts +14 -0
- package/dist/esm/rules/engine.js +179 -27
- package/dist/esm/rules/matchers.d.ts +3 -2
- package/dist/esm/rules/matchers.js +8 -1
- package/dist/esm/rules/suppressors.js +246 -9
- package/dist/esm/rules/validators.d.ts +25 -0
- package/dist/esm/rules/validators.js +90 -11
- package/dist/esm/sdk.d.ts +10 -2
- package/dist/esm/sdk.js +30 -6
- package/dist/esm/types.d.ts +18 -3
- package/dist/esm/types.js +18 -1
- package/package.json +8 -4
|
@@ -1,21 +1,45 @@
|
|
|
1
1
|
function clean(candidate, chars = /[\s.\-]/g) {
|
|
2
2
|
return candidate.replace(chars, "");
|
|
3
3
|
}
|
|
4
|
+
/**
|
|
5
|
+
* Total IBAN length per country (ISO 13616 registry). Also used to build the
|
|
6
|
+
* country-independent IBAN pattern in rules/countries, so an IBAN is detected
|
|
7
|
+
* on its own structure rather than on the caller's `countries` setting.
|
|
8
|
+
*/
|
|
9
|
+
export const IBAN_LENGTHS = {
|
|
10
|
+
AL: 28, AD: 24, AT: 20, AZ: 28, BH: 22, BY: 28, BE: 16, BA: 20, BR: 29, BG: 22, CR: 22, HR: 21,
|
|
11
|
+
CY: 28, CZ: 24, DK: 18, DO: 28, TL: 23, EE: 20, FO: 18, FI: 18, FR: 27, GE: 22, DE: 22, GI: 23,
|
|
12
|
+
GR: 27, GL: 18, GT: 28, HU: 28, IS: 26, IQ: 23, IE: 22, IL: 23, IT: 27, JO: 30, KZ: 20, XK: 20,
|
|
13
|
+
KW: 30, LV: 21, LB: 28, LI: 21, LT: 20, LU: 20, MT: 31, MR: 27, MU: 30, MC: 27, MD: 24, ME: 22,
|
|
14
|
+
NL: 18, MK: 19, NO: 15, PK: 24, PS: 29, PL: 28, PT: 25, QA: 29, RO: 24, LC: 32, SM: 27, SA: 24,
|
|
15
|
+
RS: 22, SC: 31, SK: 24, SI: 19, ES: 24, SE: 24, CH: 21, TN: 24, TR: 26, UA: 29, AE: 23, GB: 22,
|
|
16
|
+
VA: 22, VG: 24,
|
|
17
|
+
};
|
|
18
|
+
/** ISO 3166-1 alpha-2 codes, plus XK (Kosovo, user-assigned but in banking use). */
|
|
19
|
+
export const ISO_3166_ALPHA2 = new Set([
|
|
20
|
+
"AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ",
|
|
21
|
+
"BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS",
|
|
22
|
+
"BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN",
|
|
23
|
+
"CO", "CR", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE",
|
|
24
|
+
"EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF",
|
|
25
|
+
"GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM",
|
|
26
|
+
"HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM",
|
|
27
|
+
"JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC",
|
|
28
|
+
"LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK",
|
|
29
|
+
"ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA",
|
|
30
|
+
"NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG",
|
|
31
|
+
"PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW",
|
|
32
|
+
"SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS",
|
|
33
|
+
"ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO",
|
|
34
|
+
"TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI",
|
|
35
|
+
"VN", "VU", "WF", "WS", "XK", "YE", "YT", "ZA", "ZM", "ZW",
|
|
36
|
+
]);
|
|
4
37
|
export function validateIban(candidate) {
|
|
5
38
|
const c = candidate.replace(/[\s\-]/g, "").toUpperCase();
|
|
6
39
|
if (c.length < 5 || !/^[A-Z]{2}/.test(c) || !/^\d{2}$/.test(c.slice(2, 4)))
|
|
7
40
|
return false;
|
|
8
|
-
const ibanLengths = {
|
|
9
|
-
AL: 28, AD: 24, AT: 20, AZ: 28, BH: 22, BY: 28, BE: 16, BA: 20, BR: 29, BG: 22, CR: 22, HR: 21,
|
|
10
|
-
CY: 28, CZ: 24, DK: 18, DO: 28, TL: 23, EE: 20, FO: 18, FI: 18, FR: 27, GE: 22, DE: 22, GI: 23,
|
|
11
|
-
GR: 27, GL: 18, GT: 28, HU: 28, IS: 26, IQ: 23, IE: 22, IL: 23, IT: 27, JO: 30, KZ: 20, XK: 20,
|
|
12
|
-
KW: 30, LV: 21, LB: 28, LI: 21, LT: 20, LU: 20, MT: 31, MR: 27, MU: 30, MC: 27, MD: 24, ME: 22,
|
|
13
|
-
NL: 18, MK: 19, NO: 15, PK: 24, PS: 29, PL: 28, PT: 25, QA: 29, RO: 24, LC: 32, SM: 27, SA: 24,
|
|
14
|
-
RS: 22, SC: 31, SK: 24, SI: 19, ES: 24, SE: 24, CH: 21, TN: 24, TR: 26, UA: 29, AE: 23, GB: 22,
|
|
15
|
-
VA: 22, VG: 24,
|
|
16
|
-
};
|
|
17
41
|
const country = c.slice(0, 2);
|
|
18
|
-
const expected =
|
|
42
|
+
const expected = IBAN_LENGTHS[country];
|
|
19
43
|
if (expected !== undefined && c.length !== expected)
|
|
20
44
|
return false;
|
|
21
45
|
const rearranged = c.slice(4) + c.slice(0, 4);
|
|
@@ -161,13 +185,22 @@ export function validateVin(candidate) {
|
|
|
161
185
|
return false;
|
|
162
186
|
return !/[IOQ]/.test(c);
|
|
163
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* BIC/SWIFT structural validation (ISO 9362): BBBB CC LL (PPP).
|
|
190
|
+
*
|
|
191
|
+
* Necessary but **not sufficient** — BIC has no check digit, and characters
|
|
192
|
+
* 5-6 of ordinary uppercase words are frequently valid country codes
|
|
193
|
+
* (`DRINGEND` -> `GE`, `HOSPITAL` -> `IT`). Emission additionally requires a
|
|
194
|
+
* registry hit or banking context; see `suppressBicWithoutEvidence`.
|
|
195
|
+
*/
|
|
164
196
|
export function validateBic(candidate) {
|
|
165
197
|
const c = candidate.replace(/ /g, "").toUpperCase();
|
|
166
198
|
if (c.length !== 8 && c.length !== 11)
|
|
167
199
|
return false;
|
|
168
200
|
if (!/^[A-Z]{4}/.test(c))
|
|
169
201
|
return false;
|
|
170
|
-
|
|
202
|
+
// Country code must be a real ISO 3166-1 alpha-2 code
|
|
203
|
+
if (!ISO_3166_ALPHA2.has(c.slice(4, 6)))
|
|
171
204
|
return false;
|
|
172
205
|
if (!/^[A-Z0-9]{2}$/.test(c.slice(6, 8)))
|
|
173
206
|
return false;
|
|
@@ -175,6 +208,21 @@ export function validateBic(candidate) {
|
|
|
175
208
|
return false;
|
|
176
209
|
return true;
|
|
177
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* International phone number in E.164 form: `+` then 8-15 digits.
|
|
213
|
+
*
|
|
214
|
+
* A `+` prefix makes a phone number self-identifying, so this backs a
|
|
215
|
+
* country-independent pattern: the per-country patterns each hard-code one
|
|
216
|
+
* grouping and miss the others (`+43 664 8213 907` was invisible because the
|
|
217
|
+
* Austrian pattern expects an unbroken subscriber number).
|
|
218
|
+
*/
|
|
219
|
+
export function validateE164(candidate) {
|
|
220
|
+
if (!candidate.trimStart().startsWith("+"))
|
|
221
|
+
return false;
|
|
222
|
+
// A trunk prefix written as "(0)" is not part of the E.164 digit count.
|
|
223
|
+
const digits = candidate.replace(/\(\s*0\s*\)/g, "").replace(/\D/g, "");
|
|
224
|
+
return digits.length >= 8 && digits.length <= 15;
|
|
225
|
+
}
|
|
178
226
|
export function validateKvk(candidate) {
|
|
179
227
|
const c = clean(candidate);
|
|
180
228
|
return c.length === 8 && /^\d{8}$/.test(c);
|
|
@@ -578,6 +626,35 @@ export function validateGreekAmka(candidate) {
|
|
|
578
626
|
}
|
|
579
627
|
return total % 10 === 0;
|
|
580
628
|
}
|
|
629
|
+
function validateHighEntropy(candidate) {
|
|
630
|
+
const clean = candidate.trim();
|
|
631
|
+
if (clean.length < 8)
|
|
632
|
+
return false;
|
|
633
|
+
// Short passwords (< 24 chars): require at least 1 letter, 1 digit, 1 special char
|
|
634
|
+
if (clean.length < 24) {
|
|
635
|
+
const hasLetter = /[a-zA-Z]/.test(clean);
|
|
636
|
+
const hasDigit = /\d/.test(clean);
|
|
637
|
+
const hasSpecial = /[^a-zA-Z0-9]/.test(clean);
|
|
638
|
+
if (hasLetter && hasDigit && hasSpecial)
|
|
639
|
+
return true;
|
|
640
|
+
// For short tokens without special chars, require entropy check
|
|
641
|
+
if (!hasSpecial && clean.length < 16)
|
|
642
|
+
return false;
|
|
643
|
+
}
|
|
644
|
+
const freq = new Map();
|
|
645
|
+
for (const ch of clean)
|
|
646
|
+
freq.set(ch, (freq.get(ch) ?? 0) + 1);
|
|
647
|
+
const len = clean.length;
|
|
648
|
+
let entropy = 0;
|
|
649
|
+
for (const c of freq.values()) {
|
|
650
|
+
const p = c / len;
|
|
651
|
+
entropy -= p * Math.log2(p);
|
|
652
|
+
}
|
|
653
|
+
// Hex-only strings have max ~4.0 bits entropy, use lower threshold
|
|
654
|
+
const isHex = /^[a-fA-F0-9]+$/.test(clean);
|
|
655
|
+
const threshold = isHex ? 3.0 : clean.length < 24 ? 3.0 : 3.5;
|
|
656
|
+
return entropy >= threshold;
|
|
657
|
+
}
|
|
581
658
|
export const VALIDATORS = {
|
|
582
659
|
iban: validateIban,
|
|
583
660
|
bsn: validateBsn,
|
|
@@ -592,6 +669,7 @@ export const VALIDATORS = {
|
|
|
592
669
|
french_nir: validateFrenchNir,
|
|
593
670
|
vin: validateVin,
|
|
594
671
|
bic: validateBic,
|
|
672
|
+
e164: validateE164,
|
|
595
673
|
kvk: validateKvk,
|
|
596
674
|
swedish_pnr: validateSwedishPnr,
|
|
597
675
|
norwegian_fnr: validateNorwegianFnr,
|
|
@@ -621,4 +699,5 @@ export const VALIDATORS = {
|
|
|
621
699
|
uk_nhs: validateUkNhs,
|
|
622
700
|
greek_afm: validateGreekAfm,
|
|
623
701
|
greek_amka: validateGreekAmka,
|
|
702
|
+
high_entropy: validateHighEntropy,
|
|
624
703
|
};
|
package/dist/esm/sdk.d.ts
CHANGED
|
@@ -2,14 +2,22 @@ import { type RedactResult } from "./types.js";
|
|
|
2
2
|
export interface RedactOptions {
|
|
3
3
|
countries?: string[] | null;
|
|
4
4
|
mode?: string;
|
|
5
|
-
|
|
5
|
+
referentialIntegrity?: boolean;
|
|
6
6
|
detectDates?: boolean;
|
|
7
7
|
cache?: boolean;
|
|
8
8
|
}
|
|
9
9
|
export declare class EuRedact {
|
|
10
10
|
private engine;
|
|
11
11
|
private cache;
|
|
12
|
-
private
|
|
12
|
+
private referentialMapper;
|
|
13
|
+
private maxInputLength;
|
|
14
|
+
constructor(options?: {
|
|
15
|
+
maxInputLength?: number;
|
|
16
|
+
});
|
|
17
|
+
addCustomPattern(name: string, pattern: string): void;
|
|
18
|
+
/** Clear the result cache and referential integrity mappings.
|
|
19
|
+
* Call this in long-running processes to free PII from memory. */
|
|
20
|
+
clear(): void;
|
|
13
21
|
redact(text: string, options?: RedactOptions): RedactResult;
|
|
14
22
|
redactBatch(texts: string[], options?: RedactOptions): RedactResult[];
|
|
15
23
|
}
|
package/dist/esm/sdk.js
CHANGED
|
@@ -3,10 +3,10 @@ import { normalize, mapOffsetToOriginal } from "./normalizer.js";
|
|
|
3
3
|
import { RuleEngine } from "./rules/engine.js";
|
|
4
4
|
import { EntityType } from "./types.js";
|
|
5
5
|
const DATE_TYPES = new Set([EntityType.DOB, EntityType.DATE_OF_DEATH]);
|
|
6
|
-
class
|
|
6
|
+
class ReferentialMapper {
|
|
7
7
|
counters = new Map();
|
|
8
8
|
mapping = new Map();
|
|
9
|
-
|
|
9
|
+
getLabel(text, entityType) {
|
|
10
10
|
if (!this.mapping.has(text)) {
|
|
11
11
|
const count = (this.counters.get(entityType) ?? 0) + 1;
|
|
12
12
|
this.counters.set(entityType, count);
|
|
@@ -14,13 +14,37 @@ class PseudonymMapper {
|
|
|
14
14
|
}
|
|
15
15
|
return this.mapping.get(text);
|
|
16
16
|
}
|
|
17
|
+
clear() {
|
|
18
|
+
this.counters.clear();
|
|
19
|
+
this.mapping.clear();
|
|
20
|
+
}
|
|
17
21
|
}
|
|
22
|
+
const DEFAULT_MAX_INPUT_LENGTH = 10_485_760; // ~10 MB of text
|
|
18
23
|
export class EuRedact {
|
|
19
24
|
engine = new RuleEngine();
|
|
20
25
|
cache = new ResultCache();
|
|
21
|
-
|
|
26
|
+
referentialMapper = new ReferentialMapper();
|
|
27
|
+
maxInputLength;
|
|
28
|
+
constructor(options) {
|
|
29
|
+
this.maxInputLength = options?.maxInputLength ?? DEFAULT_MAX_INPUT_LENGTH;
|
|
30
|
+
}
|
|
31
|
+
addCustomPattern(name, pattern) {
|
|
32
|
+
this.engine.addCustomPattern(name, pattern);
|
|
33
|
+
this.cache.clear();
|
|
34
|
+
}
|
|
35
|
+
/** Clear the result cache and referential integrity mappings.
|
|
36
|
+
* Call this in long-running processes to free PII from memory. */
|
|
37
|
+
clear() {
|
|
38
|
+
this.cache.clear();
|
|
39
|
+
this.referentialMapper.clear();
|
|
40
|
+
}
|
|
22
41
|
redact(text, options = {}) {
|
|
23
|
-
|
|
42
|
+
if (text.length > this.maxInputLength) {
|
|
43
|
+
throw new Error(`Input text length (${text.length.toLocaleString()} chars) exceeds the maximum ` +
|
|
44
|
+
`(${this.maxInputLength.toLocaleString()} chars). Split the input or ` +
|
|
45
|
+
`increase maxInputLength when constructing EuRedact.`);
|
|
46
|
+
}
|
|
47
|
+
const { countries = null, mode = "rules", referentialIntegrity = false, detectDates = false, cache = true, } = options;
|
|
24
48
|
const [normalizedText, offsetMapping] = normalize(text);
|
|
25
49
|
const countriesTuple = countries
|
|
26
50
|
? countries.map(c => c.toUpperCase()).sort()
|
|
@@ -48,8 +72,8 @@ export class EuRedact {
|
|
|
48
72
|
let redacted = text;
|
|
49
73
|
for (let i = detections.length - 1; i >= 0; i--) {
|
|
50
74
|
const det = detections[i];
|
|
51
|
-
const replacement =
|
|
52
|
-
? this.
|
|
75
|
+
const replacement = referentialIntegrity
|
|
76
|
+
? this.referentialMapper.getLabel(det.text, det.entityType)
|
|
53
77
|
: `[${det.entityType}]`;
|
|
54
78
|
redacted = redacted.slice(0, det.start) + replacement + redacted.slice(det.end);
|
|
55
79
|
}
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
export declare enum EntityType {
|
|
2
2
|
NAME = "NAME",
|
|
3
3
|
ADDRESS = "ADDRESS",
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Canonical name for a bank account identifier. `IBAN` is kept below as a
|
|
6
|
+
* legacy alias with the same value, so `EntityType.IBAN === EntityType.BANK_ACCOUNT`
|
|
7
|
+
* and existing code keeps working — but the emitted value, and therefore the
|
|
8
|
+
* `[BANK_ACCOUNT]` placeholder written into redacted text, is canonical.
|
|
9
|
+
*/
|
|
10
|
+
BANK_ACCOUNT = "BANK_ACCOUNT",
|
|
11
|
+
/** @deprecated legacy alias of {@link EntityType.BANK_ACCOUNT} */
|
|
12
|
+
IBAN = "BANK_ACCOUNT",
|
|
5
13
|
BIC = "BIC",
|
|
6
14
|
CREDIT_CARD = "CREDIT_CARD",
|
|
7
15
|
PHONE = "PHONE",
|
|
@@ -28,14 +36,21 @@ export declare enum EntityType {
|
|
|
28
36
|
GPS_COORDINATES = "GPS_COORDINATES",
|
|
29
37
|
UUID = "UUID",
|
|
30
38
|
SOCIAL_HANDLE = "SOCIAL_HANDLE",
|
|
39
|
+
SECRET = "SECRET",
|
|
31
40
|
OTHER = "OTHER"
|
|
32
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Legacy type names accepted on input and mapped to their canonical form.
|
|
44
|
+
* Kept in sync with the pipeline canon (config/entity_types.json →
|
|
45
|
+
* legacy_aliases). The engine never *emits* these names.
|
|
46
|
+
*/
|
|
47
|
+
export declare const LEGACY_TYPE_ALIASES: Record<string, string>;
|
|
33
48
|
export declare enum DetectionSource {
|
|
34
49
|
RULES = "rules",
|
|
35
50
|
CLOUD = "cloud"
|
|
36
51
|
}
|
|
37
52
|
export interface Detection {
|
|
38
|
-
entityType: EntityType;
|
|
53
|
+
entityType: EntityType | string;
|
|
39
54
|
start: number;
|
|
40
55
|
end: number;
|
|
41
56
|
text: string;
|
|
@@ -50,7 +65,7 @@ export interface RedactResult {
|
|
|
50
65
|
degraded: boolean;
|
|
51
66
|
}
|
|
52
67
|
export interface PatternDef {
|
|
53
|
-
entityType: EntityType;
|
|
68
|
+
entityType: EntityType | string;
|
|
54
69
|
pattern: string;
|
|
55
70
|
validator: string | null;
|
|
56
71
|
description: string;
|
package/dist/esm/types.js
CHANGED
|
@@ -2,7 +2,15 @@ export var EntityType;
|
|
|
2
2
|
(function (EntityType) {
|
|
3
3
|
EntityType["NAME"] = "NAME";
|
|
4
4
|
EntityType["ADDRESS"] = "ADDRESS";
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Canonical name for a bank account identifier. `IBAN` is kept below as a
|
|
7
|
+
* legacy alias with the same value, so `EntityType.IBAN === EntityType.BANK_ACCOUNT`
|
|
8
|
+
* and existing code keeps working — but the emitted value, and therefore the
|
|
9
|
+
* `[BANK_ACCOUNT]` placeholder written into redacted text, is canonical.
|
|
10
|
+
*/
|
|
11
|
+
EntityType["BANK_ACCOUNT"] = "BANK_ACCOUNT";
|
|
12
|
+
/** @deprecated legacy alias of {@link EntityType.BANK_ACCOUNT} */
|
|
13
|
+
EntityType["IBAN"] = "BANK_ACCOUNT";
|
|
6
14
|
EntityType["BIC"] = "BIC";
|
|
7
15
|
EntityType["CREDIT_CARD"] = "CREDIT_CARD";
|
|
8
16
|
EntityType["PHONE"] = "PHONE";
|
|
@@ -29,8 +37,17 @@ export var EntityType;
|
|
|
29
37
|
EntityType["GPS_COORDINATES"] = "GPS_COORDINATES";
|
|
30
38
|
EntityType["UUID"] = "UUID";
|
|
31
39
|
EntityType["SOCIAL_HANDLE"] = "SOCIAL_HANDLE";
|
|
40
|
+
EntityType["SECRET"] = "SECRET";
|
|
32
41
|
EntityType["OTHER"] = "OTHER";
|
|
33
42
|
})(EntityType || (EntityType = {}));
|
|
43
|
+
/**
|
|
44
|
+
* Legacy type names accepted on input and mapped to their canonical form.
|
|
45
|
+
* Kept in sync with the pipeline canon (config/entity_types.json →
|
|
46
|
+
* legacy_aliases). The engine never *emits* these names.
|
|
47
|
+
*/
|
|
48
|
+
export const LEGACY_TYPE_ALIASES = {
|
|
49
|
+
IBAN: "BANK_ACCOUNT",
|
|
50
|
+
};
|
|
34
51
|
export var DetectionSource;
|
|
35
52
|
(function (DetectionSource) {
|
|
36
53
|
DetectionSource["RULES"] = "rules";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "euredact",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "European PII redaction SDK -- fast, zero-dependency, rule-based detection and redaction of personal data across 31 European countries",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -46,15 +46,19 @@
|
|
|
46
46
|
],
|
|
47
47
|
"repository": {
|
|
48
48
|
"type": "git",
|
|
49
|
-
"url": "https://github.com/
|
|
49
|
+
"url": "git+https://github.com/euredact/euredact.git"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"build:esm": "tsc",
|
|
53
53
|
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
54
54
|
"postbuild:cjs": "echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json",
|
|
55
55
|
"build": "rm -rf dist && npm run build:esm && npm run build:cjs",
|
|
56
|
-
"test": "
|
|
57
|
-
"
|
|
56
|
+
"test": "npm run test:spec",
|
|
57
|
+
"benchmark": "node --import tsx src/__tests__/benchmark.ts",
|
|
58
|
+
"prepublishOnly": "npm run build",
|
|
59
|
+
"test:spec": "node --import tsx src/__tests__/spec.ts",
|
|
60
|
+
"test:eval": "node --import tsx src/__tests__/run.ts",
|
|
61
|
+
"test:eval:full": "node --max-old-space-size=8192 --import tsx src/__tests__/evalFull.ts"
|
|
58
62
|
},
|
|
59
63
|
"devDependencies": {
|
|
60
64
|
"typescript": "^5.4.0",
|