@stll/anonymize 2.1.0 → 2.2.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 +3 -6
- package/dist/constants.mjs +3 -3
- package/dist/constants.mjs.map +1 -1
- package/dist/constants2.d.mts +3 -3
- package/dist/native-node2.mjs +26 -10
- package/dist/native-node2.mjs.map +1 -1
- package/dist/native.d.mts +3 -13
- package/native-pipeline.cs.stlanonpkg +0 -0
- package/native-pipeline.de.stlanonpkg +0 -0
- package/native-pipeline.en.stlanonpkg +0 -0
- package/native-pipeline.stlanonpkg +0 -0
- package/package.json +11 -17
package/README.md
CHANGED
|
@@ -298,16 +298,13 @@ export default {
|
|
|
298
298
|
- Native architecture and extension guidance:
|
|
299
299
|
[`ARCHITECTURE.md`](ARCHITECTURE.md).
|
|
300
300
|
- `labels: []` disables deterministic label filtering.
|
|
301
|
-
-
|
|
302
|
-
|
|
303
|
-
|
|
301
|
+
- Model-produced (NER) spans are not part of `PipelineConfig`; supply
|
|
302
|
+
deterministic custom rules today and use the caller-detection API for
|
|
303
|
+
model-produced spans.
|
|
304
304
|
- `enableNameCorpus` also controls whether first names, surnames, and titles are injected into deny-list matching when `enableDenyList` is enabled.
|
|
305
305
|
- The optional `@stll/anonymize-data` package carries the published dictionary and trigger data used when building prepared packages.
|
|
306
306
|
- `customDenyList` and `customRegexes` are part of the prepared package input and should be regenerated when they change.
|
|
307
|
-
- The old TypeScript pipeline is kept only as temporary internal migration/test scaffolding under `src/legacy.ts`; it is not the product runtime.
|
|
308
307
|
|
|
309
308
|
## Built on
|
|
310
309
|
|
|
311
|
-
- `@stll/text-search`
|
|
312
|
-
- `@stll/stdnum`
|
|
313
310
|
- `@stll/anonymize-data`
|
package/dist/constants.mjs
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Runtime-free constants for the anonymization pipeline.
|
|
4
4
|
*
|
|
5
5
|
* This module is the SSR-safe / browser-safe entrypoint:
|
|
6
|
-
* importing it must not pull in `@stll/
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* importing it must not pull in `@stll/anonymize-wasm`
|
|
7
|
+
* or any other runtime-bearing module.
|
|
8
|
+
* Consumers that only need the static label list,
|
|
9
9
|
* detection-source identifiers, or operator names import
|
|
10
10
|
* from `@stll/anonymize/constants` (or
|
|
11
11
|
* `@stll/anonymize-wasm/constants`) without paying the
|
package/dist/constants.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.mjs","names":[],"sources":["../src/constants.ts"],"sourcesContent":["/**\n * Runtime-free constants for the anonymization pipeline.\n *\n * This module is the SSR-safe / browser-safe entrypoint:\n * importing it must not pull in `@stll/text-search`,\n * `@stll/anonymize-wasm`, or any other runtime-bearing\n * module. Consumers that only need the static label list,\n * detection-source identifiers, or operator names import\n * from `@stll/anonymize/constants` (or\n * `@stll/anonymize-wasm/constants`) without paying the\n * wasm / regex-set startup cost.\n *\n * `types.ts` re-exports these for back-compat, so existing\n * `import { DEFAULT_ENTITY_LABELS } from \"@stll/anonymize\"`\n * call sites keep working.\n */\n\n/**\n * Source of a detected entity span.\n * Ordered by detection layer in the pipeline.\n */\nexport const DETECTION_SOURCES = {\n TRIGGER: \"trigger\",\n REGEX: \"regex\",\n DENY_LIST: \"deny-list\",\n LEGAL_FORM: \"legal-form\",\n GAZETTEER: \"gazetteer\",\n COUNTRY: \"country\",\n NER: \"ner\",\n COREFERENCE: \"coreference\",\n} as const;\n\nexport type DetectionSource =\n (typeof DETECTION_SOURCES)[keyof typeof DETECTION_SOURCES];\n\n/**\n * Priority levels for detection sources.\n * Higher = more structurally reliable. Used during\n * overlap resolution so deterministic detectors beat\n * probabilistic ones regardless of raw score.\n */\nexport const DETECTOR_PRIORITY = {\n [DETECTION_SOURCES.GAZETTEER]: 5,\n [DETECTION_SOURCES.TRIGGER]: 4,\n [DETECTION_SOURCES.LEGAL_FORM]: 3,\n [DETECTION_SOURCES.REGEX]: 3,\n [DETECTION_SOURCES.COUNTRY]: 3,\n [DETECTION_SOURCES.DENY_LIST]: 2,\n [DETECTION_SOURCES.COREFERENCE]: 2,\n [DETECTION_SOURCES.NER]: 1,\n} as const satisfies Record<DetectionSource, number>;\n\n/**\n * Anonymization operator types. Each operator defines\n * how a confirmed entity is replaced in the output.\n */\nexport const OPERATOR_TYPES = [\"replace\", \"redact\", \"keep\", \"mask\"] as const;\n\nexport type OperatorType = (typeof OPERATOR_TYPES)[number];\n\nexport const ENTITY_SELECTIONS = {\n DEFAULT: \"default\",\n OPT_IN: \"opt-in\",\n} as const;\n\nexport type EntitySelection =\n (typeof ENTITY_SELECTIONS)[keyof typeof ENTITY_SELECTIONS];\n\nexport type EntityCapability = {\n label: string;\n selection: EntitySelection;\n detectionSources: readonly DetectionSource[];\n};\n\n/**\n * Canonical entity capabilities exposed by the deterministic native pipeline.\n * `selection` describes whether the default package requests the label; opt-in\n * labels have built-in detection rules but must be requested explicitly.\n *\n * These labels are ephemeral: entities are regenerated on\n * every pipeline run and never persisted to the database.\n * Renaming a label here requires no migration.\n */\nexport const ENTITY_CAPABILITIES = [\n {\n label: \"person\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [\n DETECTION_SOURCES.TRIGGER,\n DETECTION_SOURCES.REGEX,\n DETECTION_SOURCES.DENY_LIST,\n DETECTION_SOURCES.COREFERENCE,\n ],\n },\n {\n label: \"organization\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [\n DETECTION_SOURCES.TRIGGER,\n DETECTION_SOURCES.DENY_LIST,\n DETECTION_SOURCES.LEGAL_FORM,\n DETECTION_SOURCES.GAZETTEER,\n DETECTION_SOURCES.COREFERENCE,\n ],\n },\n {\n label: \"phone number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"address\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [\n DETECTION_SOURCES.REGEX,\n DETECTION_SOURCES.TRIGGER,\n DETECTION_SOURCES.DENY_LIST,\n ],\n },\n {\n label: \"country\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.COUNTRY],\n },\n {\n label: \"email address\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX],\n },\n {\n label: \"date\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"date of birth\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"bank account number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"iban\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"tax identification number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"identity card number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"birth number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"national identification number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"social security number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"registration number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"credit card number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX],\n },\n {\n label: \"passport number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX],\n },\n {\n label: \"crypto\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX],\n },\n {\n label: \"monetary amount\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"land parcel\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"misc\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.DENY_LIST],\n },\n {\n label: \"ip address\",\n selection: ENTITY_SELECTIONS.OPT_IN,\n detectionSources: [DETECTION_SOURCES.REGEX],\n },\n {\n label: \"mac address\",\n selection: ENTITY_SELECTIONS.OPT_IN,\n detectionSources: [DETECTION_SOURCES.REGEX],\n },\n {\n label: \"url\",\n selection: ENTITY_SELECTIONS.OPT_IN,\n detectionSources: [DETECTION_SOURCES.REGEX],\n },\n] as const satisfies readonly EntityCapability[];\n\ntype KnownEntityCapability = (typeof ENTITY_CAPABILITIES)[number];\n\nexport type EntityLabel = KnownEntityCapability[\"label\"];\n\nexport const ENTITY_LABELS: readonly EntityLabel[] = ENTITY_CAPABILITIES.map(\n ({ label }) => label,\n);\n\nconst isDefaultEntityCapability = (\n capability: KnownEntityCapability,\n): capability is Extract<\n KnownEntityCapability,\n { selection: typeof ENTITY_SELECTIONS.DEFAULT }\n> => capability.selection === ENTITY_SELECTIONS.DEFAULT;\n\nexport type DefaultEntityLabel = Extract<\n KnownEntityCapability,\n { selection: typeof ENTITY_SELECTIONS.DEFAULT }\n>[\"label\"];\n\nexport const DEFAULT_ENTITY_LABELS: readonly DefaultEntityLabel[] =\n ENTITY_CAPABILITIES.filter(isDefaultEntityCapability).map(\n ({ label }) => label,\n );\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"constants.mjs","names":[],"sources":["../src/constants.ts"],"sourcesContent":["/**\n * Runtime-free constants for the anonymization pipeline.\n *\n * This module is the SSR-safe / browser-safe entrypoint:\n * importing it must not pull in `@stll/anonymize-wasm`\n * or any other runtime-bearing module.\n * Consumers that only need the static label list,\n * detection-source identifiers, or operator names import\n * from `@stll/anonymize/constants` (or\n * `@stll/anonymize-wasm/constants`) without paying the\n * wasm / regex-set startup cost.\n *\n * `types.ts` re-exports these for back-compat, so existing\n * `import { DEFAULT_ENTITY_LABELS } from \"@stll/anonymize\"`\n * call sites keep working.\n */\n\n/**\n * Source of a detected entity span.\n * Ordered by detection layer in the pipeline.\n */\nexport const DETECTION_SOURCES = {\n TRIGGER: \"trigger\",\n REGEX: \"regex\",\n DENY_LIST: \"deny-list\",\n LEGAL_FORM: \"legal-form\",\n GAZETTEER: \"gazetteer\",\n COUNTRY: \"country\",\n NER: \"ner\",\n COREFERENCE: \"coreference\",\n} as const;\n\nexport type DetectionSource =\n (typeof DETECTION_SOURCES)[keyof typeof DETECTION_SOURCES];\n\n/**\n * Priority levels for detection sources.\n * Higher = more structurally reliable. Used during\n * overlap resolution so deterministic detectors beat\n * probabilistic ones regardless of raw score.\n */\nexport const DETECTOR_PRIORITY = {\n [DETECTION_SOURCES.GAZETTEER]: 5,\n [DETECTION_SOURCES.TRIGGER]: 4,\n [DETECTION_SOURCES.LEGAL_FORM]: 3,\n [DETECTION_SOURCES.REGEX]: 3,\n [DETECTION_SOURCES.COUNTRY]: 3,\n [DETECTION_SOURCES.DENY_LIST]: 2,\n [DETECTION_SOURCES.COREFERENCE]: 2,\n [DETECTION_SOURCES.NER]: 1,\n} as const satisfies Record<DetectionSource, number>;\n\n/**\n * Anonymization operator types. Each operator defines\n * how a confirmed entity is replaced in the output.\n */\nexport const OPERATOR_TYPES = [\"replace\", \"redact\", \"keep\", \"mask\"] as const;\n\nexport type OperatorType = (typeof OPERATOR_TYPES)[number];\n\nexport const ENTITY_SELECTIONS = {\n DEFAULT: \"default\",\n OPT_IN: \"opt-in\",\n} as const;\n\nexport type EntitySelection =\n (typeof ENTITY_SELECTIONS)[keyof typeof ENTITY_SELECTIONS];\n\nexport type EntityCapability = {\n label: string;\n selection: EntitySelection;\n detectionSources: readonly DetectionSource[];\n};\n\n/**\n * Canonical entity capabilities exposed by the deterministic native pipeline.\n * `selection` describes whether the default package requests the label; opt-in\n * labels have built-in detection rules but must be requested explicitly.\n *\n * These labels are ephemeral: entities are regenerated on\n * every pipeline run and never persisted to the database.\n * Renaming a label here requires no migration.\n */\nexport const ENTITY_CAPABILITIES = [\n {\n label: \"person\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [\n DETECTION_SOURCES.TRIGGER,\n DETECTION_SOURCES.REGEX,\n DETECTION_SOURCES.DENY_LIST,\n DETECTION_SOURCES.COREFERENCE,\n ],\n },\n {\n label: \"organization\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [\n DETECTION_SOURCES.TRIGGER,\n DETECTION_SOURCES.DENY_LIST,\n DETECTION_SOURCES.LEGAL_FORM,\n DETECTION_SOURCES.GAZETTEER,\n DETECTION_SOURCES.COREFERENCE,\n ],\n },\n {\n label: \"phone number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"address\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [\n DETECTION_SOURCES.REGEX,\n DETECTION_SOURCES.TRIGGER,\n DETECTION_SOURCES.DENY_LIST,\n ],\n },\n {\n label: \"country\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.COUNTRY],\n },\n {\n label: \"email address\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX],\n },\n {\n label: \"date\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"date of birth\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"bank account number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"iban\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"tax identification number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"identity card number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"birth number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"national identification number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"social security number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"registration number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"credit card number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX],\n },\n {\n label: \"passport number\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX],\n },\n {\n label: \"crypto\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX],\n },\n {\n label: \"monetary amount\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"land parcel\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.TRIGGER],\n },\n {\n label: \"misc\",\n selection: ENTITY_SELECTIONS.DEFAULT,\n detectionSources: [DETECTION_SOURCES.REGEX, DETECTION_SOURCES.DENY_LIST],\n },\n {\n label: \"ip address\",\n selection: ENTITY_SELECTIONS.OPT_IN,\n detectionSources: [DETECTION_SOURCES.REGEX],\n },\n {\n label: \"mac address\",\n selection: ENTITY_SELECTIONS.OPT_IN,\n detectionSources: [DETECTION_SOURCES.REGEX],\n },\n {\n label: \"url\",\n selection: ENTITY_SELECTIONS.OPT_IN,\n detectionSources: [DETECTION_SOURCES.REGEX],\n },\n] as const satisfies readonly EntityCapability[];\n\ntype KnownEntityCapability = (typeof ENTITY_CAPABILITIES)[number];\n\nexport type EntityLabel = KnownEntityCapability[\"label\"];\n\nexport const ENTITY_LABELS: readonly EntityLabel[] = ENTITY_CAPABILITIES.map(\n ({ label }) => label,\n);\n\nconst isDefaultEntityCapability = (\n capability: KnownEntityCapability,\n): capability is Extract<\n KnownEntityCapability,\n { selection: typeof ENTITY_SELECTIONS.DEFAULT }\n> => capability.selection === ENTITY_SELECTIONS.DEFAULT;\n\nexport type DefaultEntityLabel = Extract<\n KnownEntityCapability,\n { selection: typeof ENTITY_SELECTIONS.DEFAULT }\n>[\"label\"];\n\nexport const DEFAULT_ENTITY_LABELS: readonly DefaultEntityLabel[] =\n ENTITY_CAPABILITIES.filter(isDefaultEntityCapability).map(\n ({ label }) => label,\n );\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAqBA,MAAa,oBAAoB;CAC/B,SAAS;CACT,OAAO;CACP,WAAW;CACX,YAAY;CACZ,WAAW;CACX,SAAS;CACT,KAAK;CACL,aAAa;AACf;;;;;;;AAWA,MAAa,oBAAoB;EAC9B,kBAAkB,YAAY;EAC9B,kBAAkB,UAAU;EAC5B,kBAAkB,aAAa;EAC/B,kBAAkB,QAAQ;EAC1B,kBAAkB,UAAU;EAC5B,kBAAkB,YAAY;EAC9B,kBAAkB,cAAc;EAChC,kBAAkB,MAAM;AAC3B;;;;;AAMA,MAAa,iBAAiB;CAAC;CAAW;CAAU;CAAQ;AAAM;AAIlE,MAAa,oBAAoB;CAC/B,SAAS;CACT,QAAQ;AACV;;;;;;;;;;AAoBA,MAAa,sBAAsB;CACjC;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB;GAChB,kBAAkB;GAClB,kBAAkB;GAClB,kBAAkB;GAClB,kBAAkB;EACpB;CACF;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB;GAChB,kBAAkB;GAClB,kBAAkB;GAClB,kBAAkB;GAClB,kBAAkB;GAClB,kBAAkB;EACpB;CACF;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO,kBAAkB,OAAO;CACvE;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB;GAChB,kBAAkB;GAClB,kBAAkB;GAClB,kBAAkB;EACpB;CACF;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO;CAC9C;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,KAAK;CAC5C;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO,kBAAkB,OAAO;CACvE;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO;CAC9C;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO,kBAAkB,OAAO;CACvE;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO,kBAAkB,OAAO;CACvE;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO,kBAAkB,OAAO;CACvE;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO,kBAAkB,OAAO;CACvE;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO,kBAAkB,OAAO;CACvE;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO,kBAAkB,OAAO;CACvE;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO,kBAAkB,OAAO;CACvE;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO,kBAAkB,OAAO;CACvE;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,KAAK;CAC5C;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,KAAK;CAC5C;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,KAAK;CAC5C;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO,kBAAkB,OAAO;CACvE;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO;CAC9C;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,OAAO,kBAAkB,SAAS;CACzE;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,KAAK;CAC5C;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,KAAK;CAC5C;CACA;EACE,OAAO;EACP,WAAW,kBAAkB;EAC7B,kBAAkB,CAAC,kBAAkB,KAAK;CAC5C;AACF;AAMA,MAAa,gBAAwC,oBAAoB,KACtE,EAAE,YAAY,KACjB;AAEA,MAAM,6BACJ,eAIG,WAAW,cAAc,kBAAkB;AAOhD,MAAa,wBACX,oBAAoB,OAAO,yBAAyB,CAAC,CAAC,KACnD,EAAE,YAAY,KACjB"}
|
package/dist/constants2.d.mts
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Runtime-free constants for the anonymization pipeline.
|
|
4
4
|
*
|
|
5
5
|
* This module is the SSR-safe / browser-safe entrypoint:
|
|
6
|
-
* importing it must not pull in `@stll/
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* importing it must not pull in `@stll/anonymize-wasm`
|
|
7
|
+
* or any other runtime-bearing module.
|
|
8
|
+
* Consumers that only need the static label list,
|
|
9
9
|
* detection-source identifiers, or operator names import
|
|
10
10
|
* from `@stll/anonymize/constants` (or
|
|
11
11
|
* `@stll/anonymize-wasm/constants`) without paying the
|
package/dist/native-node2.mjs
CHANGED
|
@@ -186,12 +186,31 @@ const pipelineConfigKey = (config, gazetteerEntries) => {
|
|
|
186
186
|
const gazFingerprint = config.enableGazetteer && gazetteerEntries.length > 0 ? gazetteerEntries.map((entry) => `${entry.id}:${entry.canonical}:${entry.label}:${[...entry.variants].sort().join(",")}`).toSorted().join(";") : "";
|
|
187
187
|
return `${config.enableDenyList}:${config.enableTriggerPhrases}:${legalFormsEnabled}:${config.enableNameCorpus}:${contentLanguageFingerprint(config)}:${config.nameCorpusLanguages?.toSorted().join(",") ?? ""}:${config.enableRegex}:${config.threshold}:${config.enableConfidenceBoost}:${config.enableHotwordRules === true}:${config.enableCoreference === true}:${config.enableZoneClassification === true}:${config.labels.toSorted().join(",")}:${config.denyListCountries?.toSorted().join(",") ?? ""}:${config.denyListRegions?.toSorted().join(",") ?? ""}:${config.denyListExcludeCategories?.toSorted().join(",") ?? ""}:${customDenyFingerprint}:${customRegexFingerprint}:${config.enableGazetteer}:${gazFingerprint}:${config.enableCountries !== false}`;
|
|
188
188
|
};
|
|
189
|
-
//#endregion
|
|
190
|
-
//#region src/native-pipeline.ts
|
|
191
189
|
const sharedPackageByDictionaries = /* @__PURE__ */ new WeakMap();
|
|
192
190
|
const sharedPackageWithoutDictionaries = /* @__PURE__ */ new Map();
|
|
193
191
|
const dictionaryCacheIds = /* @__PURE__ */ new WeakMap();
|
|
194
192
|
let nextDictionaryCacheId = 0;
|
|
193
|
+
/** Record `key` as most-recently-used in `cache`, evicting the
|
|
194
|
+
* least-recently-used entry first once the cache is at capacity. A `Map`'s
|
|
195
|
+
* insertion order doubles as recency order here: touching an existing key
|
|
196
|
+
* deletes then re-sets it to move it to the end, and eviction drops the
|
|
197
|
+
* first (oldest) key.
|
|
198
|
+
*
|
|
199
|
+
* Evicting a still-in-flight build only drops the cache's reference to its
|
|
200
|
+
* promise; the caller that started the build (and any concurrent caller that
|
|
201
|
+
* already read the promise before eviction) still resolves it correctly via
|
|
202
|
+
* the guarded `sharedCache.get(key) === promise` checks in
|
|
203
|
+
* `getCachedNativePipelinePackage`. A later caller for the same key just
|
|
204
|
+
* misses the dedupe and starts a fresh build — bounded memory takes priority
|
|
205
|
+
* over perfect dedupe under cache pressure. */
|
|
206
|
+
const touchSharedPackageCacheEntry = (cache, key, value) => {
|
|
207
|
+
cache.delete(key);
|
|
208
|
+
if (cache.size >= 32) {
|
|
209
|
+
const oldestKey = cache.keys().next().value;
|
|
210
|
+
if (oldestKey !== void 0) cache.delete(oldestKey);
|
|
211
|
+
}
|
|
212
|
+
cache.set(key, value);
|
|
213
|
+
};
|
|
195
214
|
const dictionaryCacheKey = (dictionaries) => {
|
|
196
215
|
if (dictionaries === void 0) return "none";
|
|
197
216
|
const existing = dictionaryCacheIds.get(dictionaries);
|
|
@@ -210,7 +229,7 @@ const sharedPackageCacheFor = (dictionaries) => {
|
|
|
210
229
|
};
|
|
211
230
|
const getNativePipelineCompatibility = (config) => {
|
|
212
231
|
const unsupportedFeatures = [];
|
|
213
|
-
if (config.enableNer) unsupportedFeatures.push("enableNer");
|
|
232
|
+
if ("enableNer" in config && Boolean(config.enableNer)) unsupportedFeatures.push("enableNer");
|
|
214
233
|
if (unsupportedFeatures.length === 0) return { status: "supported" };
|
|
215
234
|
return {
|
|
216
235
|
status: "unsupported",
|
|
@@ -229,11 +248,8 @@ const encoder = new TextEncoder();
|
|
|
229
248
|
* the separate bundle preferentially, and keeping the (large) dictionaries out
|
|
230
249
|
* of the config JSON avoids serializing them twice.
|
|
231
250
|
*/
|
|
232
|
-
const toAssembleInputs = ({ dictionaries,
|
|
233
|
-
pipelineConfigJson: encoder.encode(JSON.stringify(
|
|
234
|
-
...config,
|
|
235
|
-
enableNer
|
|
236
|
-
})),
|
|
251
|
+
const toAssembleInputs = ({ dictionaries, ...config }, gazetteerEntries) => ({
|
|
252
|
+
pipelineConfigJson: encoder.encode(JSON.stringify(config)),
|
|
237
253
|
dictionariesJson: dictionaries === void 0 ? void 0 : encoder.encode(JSON.stringify(dictionaries)),
|
|
238
254
|
gazetteerJson: gazetteerEntries.length === 0 ? void 0 : encoder.encode(JSON.stringify(gazetteerEntries))
|
|
239
255
|
});
|
|
@@ -287,6 +303,7 @@ const getCachedNativePipelinePackage = async ({ binding, config, gazetteerEntrie
|
|
|
287
303
|
const sharedCache = sharedPackageCacheFor(scopedConfig.dictionaries);
|
|
288
304
|
const shared = sharedCache.get(key);
|
|
289
305
|
if (shared !== void 0) {
|
|
306
|
+
touchSharedPackageCacheEntry(sharedCache, key, shared);
|
|
290
307
|
const packageBytes = await shared;
|
|
291
308
|
ctx.nativePipelinePackage = packageBytes;
|
|
292
309
|
ctx.nativePipelinePackageKey = key;
|
|
@@ -302,7 +319,7 @@ const getCachedNativePipelinePackage = async ({ binding, config, gazetteerEntrie
|
|
|
302
319
|
compressed
|
|
303
320
|
});
|
|
304
321
|
ctx.nativePipelinePackagePromise = promise;
|
|
305
|
-
sharedCache
|
|
322
|
+
touchSharedPackageCacheEntry(sharedCache, key, promise);
|
|
306
323
|
let packageBytes;
|
|
307
324
|
try {
|
|
308
325
|
packageBytes = await promise;
|
|
@@ -339,7 +356,6 @@ const DEFAULT_NATIVE_PIPELINE_CONFIG = {
|
|
|
339
356
|
enableDenyList: true,
|
|
340
357
|
enableGazetteer: false,
|
|
341
358
|
enableCountries: true,
|
|
342
|
-
enableNer: false,
|
|
343
359
|
enableConfidenceBoost: true,
|
|
344
360
|
enableCoreference: true,
|
|
345
361
|
enableHotwordRules: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-node2.mjs","names":["languageScopes","nativePackageVersionWithBinding","normalizeForSearchWithBinding","prepareSearchPackageWithBinding","loadPreparedPackageWithBinding","redactTextWithBinding","redactTextJsonWithBinding","redactTextStreamJsonWithBinding","diagnosticsJsonWithBinding","diagnosticsStreamJsonWithBinding","summaryDiagnosticsJsonWithBinding"],"sources":["../src/context.ts","../src/data/language-scopes.json","../src/language-scope.ts","../src/types.ts","../src/util/language-selection.ts","../src/pipeline-cache-key.ts","../src/native-pipeline.ts","../src/native-default-config.ts","../src/native-node.ts"],"sourcesContent":["/**\n * Cached state for a single pipeline run (or a sequence of runs sharing the\n * same config). The native pipeline builds its prepared package once and reuses\n * it across calls with the same config; the package bytes and the key/promise\n * that guard concurrent builds live here so callers can share one warmed\n * context.\n */\nexport type PipelineContext = {\n // ── Native prepared-package cache ─────────────\n nativePipelinePackage: Uint8Array | null;\n nativePipelinePackageKey: string;\n nativePipelinePackagePromise: Promise<Uint8Array> | null;\n};\n\n/** Create a fresh, empty pipeline context. */\nexport const createPipelineContext = (): PipelineContext => ({\n nativePipelinePackage: null,\n nativePipelinePackageKey: \"\",\n nativePipelinePackagePromise: null,\n});\n\n/**\n * Module-level default context. Used when callers\n * don't provide an explicit context, preserving full\n * backward compatibility with the existing API.\n */\nexport const defaultContext: PipelineContext = createPipelineContext();\n","","import languageScopes from \"./data/language-scopes.json\";\n\nimport type { PipelineConfig } from \"./types\";\n\ntype LanguageScope = {\n nameCorpusLanguages?: readonly string[];\n denyListCountries?: readonly string[];\n};\n\ntype LanguageScopeData = {\n languages: Record<string, LanguageScope>;\n};\n\nconst scopeData = languageScopes as LanguageScopeData;\n\nconst normalizeLanguage = (language: string): string =>\n language.trim().toLowerCase();\n\nconst fallbackLanguage = (language: string): string | null => {\n const index = language.indexOf(\"-\");\n return index === -1 ? null : language.slice(0, index);\n};\n\nconst uniquePush = (target: string[], values: readonly string[]): void => {\n const seen = new Set(target);\n for (const value of values) {\n if (seen.has(value)) {\n continue;\n }\n seen.add(value);\n target.push(value);\n }\n};\n\nconst resolveLanguageScope = (language: string): LanguageScope | null => {\n const normalized = normalizeLanguage(language);\n if (normalized.length === 0) {\n return null;\n }\n const exact = scopeData.languages[normalized];\n if (exact !== undefined) {\n return exact;\n }\n const fallback = fallbackLanguage(normalized);\n return fallback === null ? null : (scopeData.languages[fallback] ?? null);\n};\n\nconst configuredLanguages = (config: PipelineConfig): readonly string[] => {\n if (config.languages !== undefined) {\n return config.languages;\n }\n return config.language === undefined ? [] : [config.language];\n};\n\nexport const configuredContentLanguages = (\n config: Pick<PipelineConfig, \"language\" | \"languages\">,\n): readonly string[] | undefined => {\n if (config.languages !== undefined) {\n return config.languages;\n }\n return config.language === undefined ? undefined : [config.language];\n};\n\nexport const applyPipelineLanguageScope = (\n config: PipelineConfig,\n): PipelineConfig => {\n const languages = configuredLanguages(config);\n if (languages.length === 0) {\n return config;\n }\n\n const nameCorpusLanguages: string[] = [];\n const denyListCountries: string[] = [];\n for (const language of languages) {\n const scope = resolveLanguageScope(language);\n if (scope === null) {\n continue;\n }\n uniquePush(nameCorpusLanguages, scope.nameCorpusLanguages ?? []);\n uniquePush(denyListCountries, scope.denyListCountries ?? []);\n }\n\n const next: Partial<PipelineConfig> = {};\n if (\n config.nameCorpusLanguages === undefined &&\n nameCorpusLanguages.length > 0\n ) {\n next.nameCorpusLanguages = nameCorpusLanguages;\n }\n if (config.denyListCountries === undefined && denyListCountries.length > 0) {\n next.denyListCountries = denyListCountries;\n }\n\n return Object.keys(next).length === 0 ? config : { ...config, ...next };\n};\n","// Runtime-free constants live in `./constants`; re-exported\n// here for back-compat with existing call sites that import\n// from `@stll/anonymize` directly.\n//\n// `verbatimModuleSyntax` requires an explicit type-only\n// import for any name used locally as a type even when it\n// is also re-exported below — applies to `DetectionSource`\n// (used by `Entity`) and `OperatorType` (used by\n// `OperatorConfig`).\nimport type { DetectionSource, OperatorType } from \"./constants\";\nimport { DETECTION_SOURCES } from \"./constants\";\n\nexport {\n DETECTION_SOURCES,\n DETECTOR_PRIORITY,\n type DetectionSource,\n} from \"./constants\";\n\n/**\n * Fields shared by every entity span in the source text.\n */\ntype EntityBase = {\n start: number;\n end: number;\n label: string;\n text: string;\n score: number;\n sourceDetail?: \"custom-deny-list\" | \"custom-regex\" | \"gazetteer-extension\";\n};\n\n/**\n * A PII entity span found by a primary detection layer\n * (regex, NER, legal forms, deny list, ...).\n */\nexport type DetectedEntity = EntityBase & {\n source: Exclude<DetectionSource, typeof DETECTION_SOURCES.COREFERENCE>;\n};\n\n/**\n * An alias mention of a previously detected entity: a\n * defined term (\"the Seller\") or a propagated bare\n * mention (\"Acme\" after \"Acme Corp.\").\n *\n * `corefSourceText` is required by construction, so an\n * alias cannot exist without the link back to its source\n * entity. Placeholder numbering reads it to give the\n * alias the same placeholder as the source. The link\n * travels with the entity instead of living in a\n * side-channel map that a producer could forget to\n * write — or that a later pass could clear.\n */\nexport type CorefAliasEntity = EntityBase & {\n source: typeof DETECTION_SOURCES.COREFERENCE;\n /** Full text of the source entity this alias refers to. */\n corefSourceText: string;\n};\n\n/**\n * A detected PII entity span in the source text.\n * Every detection layer produces these.\n */\nexport type Entity = DetectedEntity | CorefAliasEntity;\n\n/**\n * Entity after human review. Extends the base Entity\n * with a review decision.\n */\nexport type ReviewDecision = \"confirmed\" | \"rejected\" | \"relabeled\";\n\nexport type ReviewedEntity = Entity & {\n decision?: ReviewDecision;\n originalLabel?: string;\n};\n\n/**\n * A single entry in the workspace-scoped gazetteer\n * (deny list). Persisted in IndexedDB.\n */\nexport type GazetteerEntry = {\n id: string;\n canonical: string;\n label: string;\n variants: string[];\n workspaceId: string;\n createdAt: number;\n source: \"manual\" | \"confirmed-from-model\";\n};\n\n/** Extraction strategy — closed discriminated union. */\nexport type TriggerStrategy =\n | {\n type: \"to-next-comma\";\n /**\n * Optional list of lowercase keywords that terminate\n * the value scan, in addition to commas/newlines. Useful\n * for triggers like court names that may continue past\n * a missing comma into adjacent clause text (\"Městským\n * soudem v Praze dne 1. 1. 2020\"); listing `\"dne\"` here\n * stops the scan at the date boundary. Matched on a\n * word-boundary, case-insensitive.\n */\n stopWords?: string[];\n /**\n * Hard cap on the captured span length, in characters,\n * regardless of where the next comma / stop char sits.\n * Use for triggers that label short formulaic phrases\n * (\"State of Delaware\") and must not absorb the rest\n * of a long forum-selection clause when the comma is\n * sentences away. Falls back to the default 100-char\n * fallback when omitted.\n */\n maxLength?: number;\n }\n | { type: \"to-end-of-line\" }\n | { type: \"n-words\"; count: number }\n | { type: \"company-id-value\" }\n | { type: \"address\"; maxChars?: number }\n | {\n /**\n * Extract the first regex match in the value text.\n * Useful for shape-bounded values that follow a\n * label on the same line as other fields, where\n * `to-end-of-line` would over-capture. The pattern\n * is anchored to the start of the (already\n * leading-whitespace-stripped) value, so use\n * `(?:.*?)` prefix only when intentional.\n */\n type: \"match-pattern\";\n pattern: string;\n flags?: string;\n };\n\n/** Validation rules — closed discriminated union. */\nexport type TriggerValidation =\n | { type: \"starts-uppercase\" }\n | { type: \"min-length\"; min: number }\n | { type: \"max-length\"; max: number }\n | { type: \"no-digits\" }\n | { type: \"has-digits\" }\n | {\n type: \"matches-pattern\";\n pattern: string;\n flags?: string;\n }\n /**\n * Run a named stdnum validator (checksum + length)\n * against the captured value. Keeps the trigger\n * path symmetrical with the formatted-regex\n * detectors so e.g. `CPF nº 00000000000` does not\n * survive as a tax-ID entity.\n */\n | { type: \"valid-id\"; validator: ValidIdValidator };\n\n/** Built-in stdnum validators that can be referenced\n * by `valid-id` validations. */\nexport type ValidIdValidator = \"br.cpf\" | \"br.cnpj\" | \"us.rtn\";\n\n/** Auto-generated trigger variants — closed set. */\nexport type TriggerExtension =\n | \"add-colon\"\n | \"add-trailing-space\"\n | \"add-colon-space\"\n | \"normalize-spaces\";\n\n/** V2 trigger config entry (JSON shape). */\nexport type TriggerGroupConfig = {\n id?: string;\n triggers: string[];\n label: string;\n strategy: TriggerStrategy;\n extensions?: TriggerExtension[];\n validations?: TriggerValidation[];\n /** When true, include the trigger text in the\n * entity span (e.g., court names). */\n includeTrigger?: boolean;\n};\n\n/** Compiled validation with pre-built regex. */\nexport type CompiledValidation =\n | { type: \"starts-uppercase\"; re: RegExp }\n | { type: \"min-length\"; min: number }\n | { type: \"max-length\"; max: number }\n | { type: \"no-digits\"; re: RegExp }\n | { type: \"has-digits\"; re: RegExp }\n | { type: \"matches-pattern\"; re: RegExp }\n | {\n type: \"valid-id\";\n validator: ValidIdValidator;\n check: (value: string) => boolean;\n };\n\n/**\n * Runtime rule — one per trigger string after\n * expansion. Fed to the Aho-Corasick automaton.\n */\nexport type TriggerRule = {\n trigger: string;\n label: string;\n strategy: TriggerStrategy;\n validations: CompiledValidation[];\n includeTrigger: boolean;\n};\n\nexport {\n ENTITY_CAPABILITIES,\n ENTITY_LABELS,\n ENTITY_SELECTIONS,\n OPERATOR_TYPES,\n type DefaultEntityLabel,\n type EntityCapability,\n type EntityLabel,\n type EntitySelection,\n type OperatorType,\n} from \"./constants\";\n\n/** Per-label operator selection. Key is the entity label. */\nexport type MaskDirection = \"start\" | \"end\";\n\nexport type MaskOperatorConfig = {\n type: \"mask\";\n maskingCharacter: string;\n charactersToMask: number;\n direction: MaskDirection;\n};\n\nexport type OperatorSelection =\n | Exclude<OperatorType, \"mask\">\n | MaskOperatorConfig;\n\nexport type OperatorConfig = {\n /** Operator per label. Missing labels default to \"replace\". */\n operators: Record<string, OperatorSelection>;\n /** Custom replacement string for the redact operator. */\n redactString: string;\n};\n\n/** Whether an operator produces a reversible redaction entry. */\ntype OperatorReversibility = \"reversible\" | \"irreversible\" | \"preserving\";\n\nexport type AnonymisationOperator = {\n type: OperatorType;\n reversibility: OperatorReversibility;\n /**\n * Apply the operator to a single entity occurrence.\n * Returns the replacement string to embed in the document.\n */\n apply: (\n text: string,\n label: string,\n placeholder: string,\n redactString: string,\n selection: OperatorSelection,\n ) => string;\n};\n\n/**\n * Redacted document output with stable entity mapping.\n */\nexport type RedactionResult = {\n redactedText: string;\n /**\n * Maps placeholder to original text. Only populated for\n * reversible operators (replace). Empty for redact, keep, and mask.\n */\n redactionMap: Map<string, string>;\n /** Maps placeholder to the operator that produced it. */\n operatorMap: Map<string, OperatorType>;\n entityCount: number;\n};\n\n/**\n * Configuration for the detection pipeline.\n */\nexport type DenyListCategory =\n | \"Names\"\n | \"Places\"\n | \"Addresses\"\n | \"Courts\"\n | \"Financial\"\n | \"Government\"\n | \"Healthcare\"\n | \"Education\"\n | \"Political\"\n | \"Organizations\"\n | \"International\";\n\n/**\n * Metadata for a single dictionary entry in the\n * deny-list system. Mirrors the shape from\n * the anonymize-data package so consumers can pass\n * pre-loaded data without a runtime dependency.\n */\nexport type DictionaryMeta = {\n label: string;\n category: DenyListCategory;\n country: string | null;\n};\n\n/**\n * Caller-supplied exact terms for deny-list matching.\n * These entries are merged with the published deny-list\n * dictionaries when `enableDenyList` is enabled.\n */\nexport type CustomDenyListEntry = {\n value: string;\n label: string;\n variants?: readonly string[];\n};\n\n/**\n * Caller-supplied regex detector. The pattern is passed\n * to the underlying text-search regex engine, so use its\n * supported regex syntax. Inline flags such as `(?i)` are\n * accepted when supported by that engine.\n */\nexport type CustomRegexPattern = {\n pattern: string;\n label: string;\n score?: number;\n preparedArtifactPolicy?: \"include\" | \"omit\";\n};\n\n/**\n * Pre-loaded dictionary data for dependency injection.\n * Consumers that want name/city/deny-list detection\n * load dictionaries themselves (e.g. from the\n * anonymize-data package) and pass them here; the\n * anonymize package has zero cross-package imports.\n *\n * All fields are optional. When a field is absent,\n * the corresponding detection path is skipped (same\n * behavior as when no dictionaries are available).\n */\nexport type Dictionaries = {\n /**\n * First names per language code (e.g., \"cs\", \"de\").\n * Merged with legacy config names at init time.\n */\n firstNames?: Readonly<Record<string, readonly string[]>>;\n /**\n * Surnames per language code.\n * Merged with legacy config names at init time.\n */\n surnames?: Readonly<Record<string, readonly string[]>>;\n /**\n * Non-Western name tokens per locale code\n * (e.g., \"in\", \"ar\", \"ja-latn\", \"ko\", \"zh-latn\",\n * \"th\", \"vi\", \"fil\", \"id\"). Merged with bundled\n * names-nw-*.json data at init time.\n */\n nonWesternNames?: Readonly<Record<string, readonly string[]>>;\n /**\n * Pre-loaded deny-list dictionaries keyed by\n * dictionary ID (e.g., \"courts/CZ\", \"banks/DE\").\n * Each value is the array of terms for that\n * dictionary.\n */\n denyList?: Readonly<Record<string, readonly string[]>>;\n /**\n * Metadata per dictionary ID. Required when\n * `denyList` is provided so the pipeline knows\n * labels, categories, and country filters.\n */\n denyListMeta?: Readonly<Record<string, DictionaryMeta>>;\n /**\n * Pre-loaded city names, already merged across\n * all desired countries.\n *\n * Prefer `citiesByCountry` when callers also pass\n * `denyListCountries` / `denyListRegions`; merged\n * city arrays cannot be scoped after injection.\n */\n cities?: readonly string[];\n /**\n * Pre-loaded city names keyed by ISO 3166-1 alpha-2\n * country code. When provided, the deny-list builder\n * applies `denyListCountries` / `denyListRegions`\n * before adding city patterns to the search automaton.\n */\n citiesByCountry?: Readonly<Record<string, readonly string[]>>;\n};\n\nexport type PipelineConfig = {\n threshold: number;\n enableTriggerPhrases: boolean;\n enableRegex: boolean;\n /**\n * Expected content language codes. When present, these\n * derive default dictionary scopes for name corpus and\n * deny-list matching unless the lower-level scope fields\n * below are set explicitly.\n */\n languages?: string[];\n /**\n * Convenience form for single-language documents. Ignored\n * when `languages` is also provided.\n */\n language?: string;\n /**\n * Enables legal-form organization detection.\n * Required for typed callers; legacy untyped\n * callers that omit this field are treated as\n * enabled at runtime for backward compatibility.\n */\n enableLegalForms: boolean;\n /**\n * Enables first-name/surname/title corpus matching.\n * When deny-list mode is enabled, this also controls\n * whether name-corpus entries are injected into the\n * deny-list search automaton.\n */\n enableNameCorpus: boolean;\n /**\n * Optional language scope for first-name/surname\n * dictionaries, using the keys present in\n * `dictionaries.firstNames` / `dictionaries.surnames`\n * (for example `[\"en\", \"de\"]`). When omitted, all\n * injected name languages are used for backward\n * compatibility.\n */\n nameCorpusLanguages?: string[];\n enableDenyList: boolean;\n denyListCountries?: string[];\n denyListRegions?: string[];\n denyListExcludeCategories?: string[];\n /**\n * Caller-owned exact terms to match through the\n * deny-list layer. Requires `enableDenyList: true`.\n */\n customDenyList?: readonly CustomDenyListEntry[];\n /**\n * Caller-owned regex detectors. Requires\n * `enableRegex: true`.\n */\n customRegexes?: readonly CustomRegexPattern[];\n enableGazetteer: boolean;\n /**\n * Detect country names (ISO 3166-1 names, curated\n * aliases, alpha-3 codes). Defaults to true. Names\n * span all manifest languages plus widely-used\n * additions (Dutch, Russian, Chinese, Arabic, etc.).\n */\n enableCountries?: boolean;\n /**\n * Reserved for compatibility with the removed TypeScript pipeline.\n * The native pipeline rejects `true`; supply deterministic custom rules today\n * and use the future caller-detection API for model-produced spans.\n *\n * @deprecated Native NER is not implemented.\n */\n enableNer?: boolean;\n enableConfidenceBoost: boolean;\n enableCoreference: boolean;\n enableZoneClassification?: boolean;\n enableHotwordRules?: boolean;\n /**\n * Requested output labels. An empty array means\n * \"do not filter by label\" for deterministic detectors.\n */\n labels: string[];\n workspaceId: string;\n /**\n * Pre-loaded dictionary data for name, deny-list,\n * and city detection. When omitted, dictionary-based\n * detection paths are skipped. Consumers load from\n * the anonymize-data package and pass the data here.\n */\n dictionaries?: Dictionaries;\n};\n\nexport { DEFAULT_ENTITY_LABELS } from \"./constants\";\n\nexport const isLegalFormsEnabled = (\n config: Pick<PipelineConfig, \"enableLegalForms\">,\n): boolean => config.enableLegalForms !== false;\n","const normalizeLanguageCode = (language: string): string =>\n language.trim().toLowerCase();\n\nconst normalizeLanguageSelection = (\n languages: readonly string[] | undefined,\n): string[] =>\n languages === undefined\n ? []\n : languages\n .map(normalizeLanguageCode)\n .filter((language) => language.length > 0);\n\nexport const languageSelectionKey = (\n languages: readonly string[] | undefined,\n): string => {\n const normalized = normalizeLanguageSelection(languages).toSorted();\n return normalized.length === 0 ? \"*\" : normalized.join(\",\");\n};\n\nconst baseLanguage = (language: string): string => {\n const index = language.indexOf(\"-\");\n return index === -1 ? language : language.slice(0, index);\n};\n\nexport const languageConfigMatches = (\n configLanguage: string,\n selectedLanguages: readonly string[] | undefined,\n): boolean => {\n if (selectedLanguages === undefined || selectedLanguages.length === 0) {\n return true;\n }\n const normalizedSelectedLanguages =\n normalizeLanguageSelection(selectedLanguages);\n if (normalizedSelectedLanguages.length === 0) {\n return true;\n }\n\n const normalizedConfigLanguage = normalizeLanguageCode(configLanguage);\n if (normalizedConfigLanguage.length === 0) {\n return false;\n }\n\n const genericConfig =\n baseLanguage(normalizedConfigLanguage) === normalizedConfigLanguage;\n for (const normalizedLanguage of normalizedSelectedLanguages) {\n if (normalizedLanguage === normalizedConfigLanguage) {\n return true;\n }\n if (\n genericConfig &&\n baseLanguage(normalizedLanguage) === normalizedConfigLanguage\n ) {\n return true;\n }\n }\n\n return false;\n};\n","import {\n isLegalFormsEnabled,\n type GazetteerEntry,\n type PipelineConfig,\n} from \"./types\";\nimport { languageSelectionKey } from \"./util/language-selection\";\n\nconst DEFAULT_CUSTOM_REGEX_SCORE = 0.9;\n\nconst contentLanguageFingerprint = (\n config: Pick<PipelineConfig, \"language\" | \"languages\">,\n): string => {\n const languages =\n config.languages ??\n (config.language === undefined ? [] : [config.language]);\n return languageSelectionKey(languages);\n};\n\nexport const pipelineConfigKey = (\n config: PipelineConfig,\n gazetteerEntries: readonly GazetteerEntry[],\n): string => {\n const legalFormsEnabled = isLegalFormsEnabled(config);\n const customDenyFingerprint =\n config.enableDenyList && config.customDenyList\n ? config.customDenyList\n .map((entry) =>\n JSON.stringify({\n label: entry.label,\n value: entry.value,\n variants: [...(entry.variants ?? [])].sort(),\n }),\n )\n .sort()\n .join(\"\\n\")\n : \"\";\n const customRegexFingerprint =\n config.enableRegex && config.customRegexes\n ? config.customRegexes\n .map((entry) =>\n JSON.stringify({\n label: entry.label,\n pattern: entry.pattern,\n preparedArtifactPolicy: entry.preparedArtifactPolicy ?? null,\n score: entry.score ?? DEFAULT_CUSTOM_REGEX_SCORE,\n }),\n )\n .sort()\n .join(\"\\n\")\n : \"\";\n const gazFingerprint =\n config.enableGazetteer && gazetteerEntries.length > 0\n ? gazetteerEntries\n .map(\n (entry) =>\n `${entry.id}:${entry.canonical}:${entry.label}:${[\n ...entry.variants,\n ]\n .sort()\n .join(\",\")}`,\n )\n .toSorted()\n .join(\";\")\n : \"\";\n\n return (\n `${config.enableDenyList}:` +\n `${config.enableTriggerPhrases}:` +\n `${legalFormsEnabled}:` +\n `${config.enableNameCorpus}:` +\n `${contentLanguageFingerprint(config)}:` +\n `${config.nameCorpusLanguages?.toSorted().join(\",\") ?? \"\"}:` +\n `${config.enableRegex}:` +\n `${config.threshold}:` +\n `${config.enableConfidenceBoost}:` +\n `${config.enableHotwordRules === true}:` +\n `${config.enableCoreference === true}:` +\n `${config.enableZoneClassification === true}:` +\n `${config.labels.toSorted().join(\",\")}:` +\n `${config.denyListCountries?.toSorted().join(\",\") ?? \"\"}:` +\n `${config.denyListRegions?.toSorted().join(\",\") ?? \"\"}:` +\n `${config.denyListExcludeCategories?.toSorted().join(\",\") ?? \"\"}:` +\n `${customDenyFingerprint}:` +\n `${customRegexFingerprint}:` +\n `${config.enableGazetteer}:${gazFingerprint}:` +\n `${config.enableCountries !== false}`\n );\n};\n","import type { PipelineContext } from \"./context\";\nimport { defaultContext } from \"./context\";\nimport { applyPipelineLanguageScope } from \"./language-scope\";\nimport type { NativePreparedSearchConfig } from \"./native-search-config\";\nimport { pipelineConfigKey } from \"./pipeline-cache-key\";\nimport type { Dictionaries, GazetteerEntry, PipelineConfig } from \"./types\";\nimport {\n createNativePipelineFromPackage,\n PreparedNativePipeline,\n type NativeAnonymizeBinding,\n} from \"./native\";\n\nexport {\n PreparedNativePipeline,\n createNativePipelineFromPackage,\n} from \"./native\";\n\nexport type NativePipelineUnsupportedFeature = \"enableNer\";\n\nexport type NativePipelineCompatibility =\n | { status: \"supported\" }\n | {\n status: \"unsupported\";\n unsupportedFeatures: NativePipelineUnsupportedFeature[];\n };\n\nexport type NativePipelineBuildOptions = {\n binding: NativeAnonymizeBinding;\n config: PipelineConfig;\n gazetteerEntries?: GazetteerEntry[];\n context?: PipelineContext;\n};\n\nexport type NativePipelinePackageOptions = NativePipelineBuildOptions & {\n compressed?: boolean;\n};\n\nexport type { NativePipelineFromPackageOptions } from \"./native\";\n\ntype NativePipelinePackageCacheValue = Promise<Uint8Array> | Uint8Array;\n\nconst sharedPackageByDictionaries = new WeakMap<\n Dictionaries,\n Map<string, NativePipelinePackageCacheValue>\n>();\nconst sharedPackageWithoutDictionaries = new Map<\n string,\n NativePipelinePackageCacheValue\n>();\nconst dictionaryCacheIds = new WeakMap<Dictionaries, number>();\nlet nextDictionaryCacheId = 0;\n\nconst dictionaryCacheKey = (dictionaries: Dictionaries | undefined): string => {\n if (dictionaries === undefined) {\n return \"none\";\n }\n const existing = dictionaryCacheIds.get(dictionaries);\n if (existing !== undefined) {\n return `dict:${existing}`;\n }\n nextDictionaryCacheId += 1;\n dictionaryCacheIds.set(dictionaries, nextDictionaryCacheId);\n return `dict:${nextDictionaryCacheId}`;\n};\n\nconst sharedPackageCacheFor = (\n dictionaries: Dictionaries | undefined,\n): Map<string, NativePipelinePackageCacheValue> => {\n if (dictionaries === undefined) {\n return sharedPackageWithoutDictionaries;\n }\n const cached = sharedPackageByDictionaries.get(dictionaries);\n if (cached !== undefined) {\n return cached;\n }\n const created = new Map<string, NativePipelinePackageCacheValue>();\n sharedPackageByDictionaries.set(dictionaries, created);\n return created;\n};\n\nexport const getNativePipelineCompatibility = (\n config: PipelineConfig,\n): NativePipelineCompatibility => {\n const unsupportedFeatures: NativePipelineUnsupportedFeature[] = [];\n\n if (config.enableNer) unsupportedFeatures.push(\"enableNer\");\n if (unsupportedFeatures.length === 0) {\n return { status: \"supported\" };\n }\n return { status: \"unsupported\", unsupportedFeatures };\n};\n\nexport const assertNativePipelineSupported = (config: PipelineConfig): void => {\n const compatibility = getNativePipelineCompatibility(config);\n if (compatibility.status === \"supported\") {\n return;\n }\n throw new Error(\n `Native pipeline does not yet support: ${compatibility.unsupportedFeatures.join(\", \")}`,\n );\n};\n\nconst encoder = new TextEncoder();\n\ntype AssembleInputs = {\n pipelineConfigJson: Uint8Array;\n dictionariesJson: Uint8Array | undefined;\n gazetteerJson: Uint8Array | undefined;\n};\n\n/**\n * Serialize the assembler inputs the Rust binding expects. Dictionaries are\n * stripped from the pipeline config and passed out of band: the assembler reads\n * the separate bundle preferentially, and keeping the (large) dictionaries out\n * of the config JSON avoids serializing them twice.\n */\nconst toAssembleInputs = (\n { dictionaries, enableNer = false, ...config }: PipelineConfig,\n gazetteerEntries: readonly GazetteerEntry[],\n): AssembleInputs => ({\n pipelineConfigJson: encoder.encode(JSON.stringify({ ...config, enableNer })),\n dictionariesJson:\n dictionaries === undefined\n ? undefined\n : encoder.encode(JSON.stringify(dictionaries)),\n gazetteerJson:\n gazetteerEntries.length === 0\n ? undefined\n : encoder.encode(JSON.stringify(gazetteerEntries)),\n});\n\nconst assemblePackageBytes = (\n binding: NativeAnonymizeBinding,\n { pipelineConfigJson, dictionariesJson, gazetteerJson }: AssembleInputs,\n compressed: boolean,\n): Uint8Array => {\n const assemble = compressed\n ? binding.assembleStaticSearchCompressedPackageBytes\n : binding.assembleStaticSearchPackageBytes;\n if (assemble === undefined) {\n throw new Error(\n \"Native anonymize binding does not support static-search config assembly\",\n );\n }\n return assemble(pipelineConfigJson, dictionariesJson, gazetteerJson);\n};\n\nexport const prepareNativePipelineConfig = async ({\n binding,\n config,\n gazetteerEntries = [],\n}: Omit<\n NativePipelineBuildOptions,\n \"context\"\n>): Promise<NativePreparedSearchConfig> => {\n const scopedConfig = applyPipelineLanguageScope(config);\n assertNativePipelineSupported(scopedConfig);\n const assemble = binding.assembleStaticSearchConfigJson;\n if (assemble === undefined) {\n throw new Error(\n \"Native anonymize binding does not support static-search config assembly\",\n );\n }\n const { pipelineConfigJson, dictionariesJson, gazetteerJson } =\n toAssembleInputs(scopedConfig, gazetteerEntries);\n const configJson = assemble(\n pipelineConfigJson,\n dictionariesJson,\n gazetteerJson,\n );\n return JSON.parse(new TextDecoder().decode(configJson));\n};\n\nexport const prepareNativePipelinePackage = async ({\n binding,\n config,\n gazetteerEntries = [],\n context,\n compressed = false,\n}: NativePipelinePackageOptions): Promise<Uint8Array> => {\n const packageBytes = await getCachedNativePipelinePackage({\n config,\n binding,\n gazetteerEntries,\n ...(context ? { context } : {}),\n compressed,\n });\n // Return a genuine copy: with the real NAPI binding packageBytes is a Node\n // Buffer, and Buffer.prototype.slice() yields a memory-sharing view, so a\n // caller mutating it would corrupt the shared cache and ctx.nativePipelinePackage.\n return new Uint8Array(packageBytes);\n};\n\nexport const createNativePipelineFromConfig = async ({\n binding,\n config,\n gazetteerEntries = [],\n context,\n}: NativePipelineBuildOptions): Promise<PreparedNativePipeline> => {\n const packageBytes = await getCachedNativePipelinePackage({\n binding,\n config,\n gazetteerEntries,\n ...(context ? { context } : {}),\n });\n return createNativePipelineFromPackage({ binding, packageBytes });\n};\n\nconst getCachedNativePipelinePackage = async ({\n binding,\n config,\n gazetteerEntries = [],\n context,\n compressed = false,\n}: NativePipelinePackageOptions): Promise<Uint8Array> => {\n const scopedConfig = applyPipelineLanguageScope(config);\n assertNativePipelineSupported(scopedConfig);\n const ctx = context ?? defaultContext;\n const key = nativePackageCacheKey({\n binding,\n config: scopedConfig,\n gazetteerEntries,\n compressed,\n });\n if (ctx.nativePipelinePackage && ctx.nativePipelinePackageKey === key) {\n return ctx.nativePipelinePackage;\n }\n if (\n ctx.nativePipelinePackagePromise &&\n ctx.nativePipelinePackageKey === key\n ) {\n return ctx.nativePipelinePackagePromise;\n }\n\n const sharedCache = sharedPackageCacheFor(scopedConfig.dictionaries);\n const shared = sharedCache.get(key);\n if (shared !== undefined) {\n const packageBytes = await shared;\n ctx.nativePipelinePackage = packageBytes;\n ctx.nativePipelinePackageKey = key;\n ctx.nativePipelinePackagePromise = null;\n return packageBytes;\n }\n\n ctx.nativePipelinePackage = null;\n ctx.nativePipelinePackageKey = key;\n const promise = buildNativePipelinePackage({\n binding,\n config: scopedConfig,\n gazetteerEntries,\n compressed,\n });\n ctx.nativePipelinePackagePromise = promise;\n sharedCache.set(key, promise);\n let packageBytes: Uint8Array;\n try {\n packageBytes = await promise;\n } catch (error) {\n if (sharedCache.get(key) === promise) {\n sharedCache.delete(key);\n }\n if (\n ctx.nativePipelinePackageKey === key &&\n ctx.nativePipelinePackagePromise === promise\n ) {\n ctx.nativePipelinePackage = null;\n ctx.nativePipelinePackagePromise = null;\n }\n throw error;\n }\n if (sharedCache.get(key) === promise) {\n sharedCache.set(key, packageBytes);\n }\n if (ctx.nativePipelinePackageKey === key) {\n ctx.nativePipelinePackage = packageBytes;\n ctx.nativePipelinePackagePromise = null;\n }\n return packageBytes;\n};\n\n// `async` so the shared package cache can store the in-flight value and dedupe\n// concurrent builds for the same key, and so assembly failures (an older\n// binding without the assemble functions, or a config the assembler rejects)\n// surface as a rejected promise rather than a synchronous throw mid-cache-flow.\nconst buildNativePipelinePackage = async ({\n binding,\n config,\n gazetteerEntries,\n compressed,\n}: Required<\n Omit<NativePipelinePackageOptions, \"context\">\n>): Promise<Uint8Array> =>\n assemblePackageBytes(\n binding,\n toAssembleInputs(config, gazetteerEntries),\n compressed,\n );\n\ntype NativePackageCacheKeyOptions = {\n binding: NativeAnonymizeBinding;\n config: PipelineConfig;\n gazetteerEntries: readonly GazetteerEntry[];\n compressed: boolean;\n};\n\nconst nativePackageCacheKey = ({\n binding,\n config,\n gazetteerEntries,\n compressed,\n}: NativePackageCacheKeyOptions): string =>\n [\n binding.nativePackageVersion(),\n compressed ? \"compressed\" : \"raw\",\n dictionaryCacheKey(config.dictionaries),\n pipelineConfigKey(config, gazetteerEntries),\n ].join(\":\");\n","import { DEFAULT_ENTITY_LABELS } from \"./constants\";\nimport type { PipelineConfig } from \"./types\";\n\nexport const DEFAULT_NATIVE_PIPELINE_CONFIG: PipelineConfig = {\n threshold: 0.3,\n enableTriggerPhrases: true,\n enableRegex: true,\n enableLegalForms: true,\n enableNameCorpus: true,\n enableDenyList: true,\n enableGazetteer: false,\n enableCountries: true,\n enableNer: false,\n enableConfidenceBoost: true,\n enableCoreference: true,\n enableHotwordRules: true,\n enableZoneClassification: true,\n labels: [...DEFAULT_ENTITY_LABELS],\n workspaceId: \"native-pipeline-default\",\n};\n","import { createRequire } from \"node:module\";\nimport { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport process from \"node:process\";\n\nimport {\n assertNativeBindingVersion,\n createNativePipelineFromPackage,\n type NativeOperatorConfig,\n type NativeAnonymizeBinding,\n type NativeNormalizeOptions,\n type NativeSearchPackageInput,\n PreparedNativeAnonymizer,\n PreparedNativePipeline,\n type NativeStaticRedactionResult,\n diagnostics_json as diagnosticsJsonWithBinding,\n diagnostics_stream_json as diagnosticsStreamJsonWithBinding,\n load_prepared_package as loadPreparedPackageWithBinding,\n native_package_version as nativePackageVersionWithBinding,\n normalize_for_search as normalizeForSearchWithBinding,\n prepare_search_package as prepareSearchPackageWithBinding,\n redact_text as redactTextWithBinding,\n redact_text_json as redactTextJsonWithBinding,\n redact_text_stream_json as redactTextStreamJsonWithBinding,\n summary_diagnostics_json as summaryDiagnosticsJsonWithBinding,\n} from \"./native\";\n\nexport * from \"./native\";\nexport {\n assertNativePipelineSupported,\n createNativePipelineFromConfig,\n getNativePipelineCompatibility,\n prepareNativePipelineConfig,\n prepareNativePipelinePackage,\n} from \"./native-pipeline\";\nexport type {\n NativePipelineBuildOptions,\n NativePipelineCompatibility,\n NativePipelinePackageOptions,\n NativePipelineUnsupportedFeature,\n} from \"./native-pipeline\";\n\nexport type NativeRequire = (specifier: string) => unknown;\n\nexport type NativeLibc = \"gnu\" | \"musl\";\n\nexport type LoadNativeBindingOptions = {\n expectedVersion?: string;\n platform?: string;\n arch?: string;\n libc?: NativeLibc;\n env?: Record<string, string | undefined>;\n requireModule?: NativeRequire;\n};\n\nexport type NativePipelinePackageFileOptions = LoadNativeBindingOptions & {\n binding?: NativeAnonymizeBinding;\n packagePath: string;\n};\n\nexport type NativeSdkOptions = LoadNativeBindingOptions & {\n binding?: NativeAnonymizeBinding;\n};\n\nexport type NativeSdkPackageOptions = NativeSdkOptions & {\n compressed?: boolean;\n};\n\nexport type DefaultNativePipelinePackageOptions = LoadNativeBindingOptions & {\n binding?: NativeAnonymizeBinding;\n language?: string;\n packagePath?: string;\n warmup?: DefaultNativePipelineWarmup;\n};\n\ntype ResolvedDefaultNativePipelineOptions = {\n binding: NativeAnonymizeBinding;\n language?: string;\n packagePath?: string;\n warmup: DefaultNativePipelineWarmup;\n};\n\nexport const DEFAULT_NATIVE_PIPELINE_WARMUPS = {\n lazyRegex: \"lazy-regex\",\n none: \"none\",\n} as const;\n\nexport type DefaultNativePipelineWarmup =\n (typeof DEFAULT_NATIVE_PIPELINE_WARMUPS)[keyof typeof DEFAULT_NATIVE_PIPELINE_WARMUPS];\n\nexport type DefaultNativePipelinePackageFileOptions = {\n language?: string;\n};\n\nconst LOCAL_NATIVE_LOADER = \"../index.cjs\";\nconst PACKAGE_SPECIFIC_NATIVE_PATH = \"STELLA_ANONYMIZE_NATIVE_LIBRARY_PATH\";\nconst DEFAULT_NATIVE_PIPELINE_PACKAGE_URL = new URL(\n \"../native-pipeline.stlanonpkg\",\n import.meta.url,\n);\nconst DEFAULT_NATIVE_PIPELINE_PACKAGE_DIR_URL = new URL(\"../\", import.meta.url);\nconst DEFAULT_NATIVE_PIPELINE_LANGUAGE_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;\nconst DEFAULT_NATIVE_PIPELINE_LANGUAGE_PACKAGE_PATTERN =\n /^native-pipeline\\.([a-z0-9]+(?:-[a-z0-9]+)*)\\.stlanonpkg$/u;\nconst DEFAULT_NATIVE_PIPELINE_PACKAGE_CACHE_KEY = \"<default>\";\nconst defaultNativePipelineCache = new WeakMap<\n NativeAnonymizeBinding,\n Map<string, PreparedNativePipeline>\n>();\nconst warmedDefaultNativePipelines = new WeakSet<PreparedNativePipeline>();\nconst defaultNativePipelineInflightCache = new WeakMap<\n NativeAnonymizeBinding,\n Map<string, Promise<PreparedNativePipeline>>\n>();\n\nexport { DEFAULT_NATIVE_PIPELINE_CONFIG } from \"./native-default-config\";\n\nexport const loadNativeAnonymizeBinding = (\n options: LoadNativeBindingOptions = {},\n): NativeAnonymizeBinding => {\n const requireModule = options.requireModule ?? createRequire(import.meta.url);\n const platform = options.platform ?? process.platform;\n const arch = options.arch ?? process.arch;\n const libc = options.libc ?? detectNativeLibc(platform);\n const env = options.env ?? process.env;\n const specifiers = nativeBindingSpecifiers({ arch, env, libc, platform });\n const errors: string[] = [];\n\n for (const specifier of specifiers) {\n const binding = tryLoadNativeBinding({\n specifier,\n requireModule,\n errors,\n });\n if (!binding) {\n continue;\n }\n if (options.expectedVersion !== undefined) {\n assertNativeBindingVersion({\n binding,\n expectedVersion: options.expectedVersion,\n });\n }\n return binding;\n }\n\n if (nativeBindingPackageName({ arch, libc, platform }) === null) {\n throw unsupportedNativeTargetError({ arch, errors, libc, platform });\n }\n throw new Error(\n `Unable to load native anonymize binding for ${platform}/${arch}:\\n${errors.join(\"\\n\")}`,\n );\n};\n\nexport const readNativePipelinePackageFile = (\n packagePath: string,\n): Uint8Array => readFileSync(packagePath);\n\nexport const readNativePipelinePackageFileAsync = async (\n packagePath: string,\n): Promise<Uint8Array> => readFile(packagePath);\n\nexport const native_package_version = (\n options: NativeSdkOptions = {},\n): string => nativePackageVersionWithBinding(resolveNativeSdkBinding(options));\n\nexport const normalize_for_search = (\n text: string,\n options: NativeSdkOptions = {},\n): string => {\n const args: NativeNormalizeOptions = {\n binding: resolveNativeSdkBinding(options),\n text,\n };\n return normalizeForSearchWithBinding(args);\n};\n\nexport const prepare_search_package = (\n config: NativeSearchPackageInput,\n { compressed = false, ...options }: NativeSdkPackageOptions = {},\n): Uint8Array =>\n prepareSearchPackageWithBinding({\n binding: resolveNativeSdkBinding(options),\n config,\n compressed,\n });\n\nexport const load_prepared_package = (\n packageBytes: Uint8Array,\n options: NativeSdkOptions = {},\n) =>\n loadPreparedPackageWithBinding({\n binding: resolveNativeSdkBinding(options),\n packageBytes,\n });\n\nexport const load_prepared_package_file = (\n packagePath: string,\n options: NativeSdkOptions = {},\n) => load_prepared_package(readNativePipelinePackageFile(packagePath), options);\n\nexport const redact_text = (\n config: NativeSearchPackageInput,\n fullText: string,\n operators?: NativeOperatorConfig,\n options: NativeSdkOptions = {},\n): NativeStaticRedactionResult =>\n redactTextWithBinding({\n binding: resolveNativeSdkBinding(options),\n config,\n fullText,\n ...(operators !== undefined ? { operators } : {}),\n });\n\nexport const redact_text_json = (\n config: NativeSearchPackageInput,\n fullText: string,\n operators?: NativeOperatorConfig,\n options: NativeSdkOptions = {},\n): string =>\n redactTextJsonWithBinding({\n binding: resolveNativeSdkBinding(options),\n config,\n fullText,\n ...(operators !== undefined ? { operators } : {}),\n });\n\nexport const redact_text_stream_json = (\n config: NativeSearchPackageInput,\n fullText: string,\n onEvent: (eventJson: string) => void,\n operators?: NativeOperatorConfig,\n options: NativeSdkOptions = {},\n): string | null =>\n redactTextStreamJsonWithBinding({\n binding: resolveNativeSdkBinding(options),\n config,\n fullText,\n onEvent,\n ...(operators !== undefined ? { operators } : {}),\n });\n\nexport const diagnostics_json = (\n config: NativeSearchPackageInput,\n fullText: string,\n operators?: NativeOperatorConfig,\n options: NativeSdkOptions = {},\n): string | null =>\n diagnosticsJsonWithBinding({\n binding: resolveNativeSdkBinding(options),\n config,\n fullText,\n ...(operators !== undefined ? { operators } : {}),\n });\n\nexport const diagnostics_stream_json = (\n config: NativeSearchPackageInput,\n fullText: string,\n onBatch: (diagnosticsJson: string) => void,\n operators?: NativeOperatorConfig,\n options: NativeSdkOptions = {},\n): string | null =>\n diagnosticsStreamJsonWithBinding({\n binding: resolveNativeSdkBinding(options),\n config,\n fullText,\n onBatch,\n ...(operators !== undefined ? { operators } : {}),\n });\n\nexport const summary_diagnostics_json = (\n config: NativeSearchPackageInput,\n fullText: string,\n operators?: NativeOperatorConfig,\n options: NativeSdkOptions = {},\n): string | null =>\n summaryDiagnosticsJsonWithBinding({\n binding: resolveNativeSdkBinding(options),\n config,\n fullText,\n ...(operators !== undefined ? { operators } : {}),\n });\n\nexport const readDefaultNativePipelinePackageFile = ({\n language,\n}: DefaultNativePipelinePackageFileOptions = {}): Uint8Array => {\n const packageUrl = defaultNativePipelinePackageUrl(language);\n try {\n return readFileSync(packageUrl);\n } catch (error) {\n throw new Error(\n `${defaultNativePipelinePackageDescription(language)} is unavailable: ${formatLoadError(error)}`,\n );\n }\n};\n\nexport const read_default_native_pipeline_package_file = (\n options: DefaultNativePipelinePackageFileOptions = {},\n): Uint8Array => readDefaultNativePipelinePackageFile(options);\n\nexport const availableDefaultNativePipelineLanguages = (): string[] => {\n const languages = new Set<string>();\n try {\n for (const fileName of readdirSync(\n DEFAULT_NATIVE_PIPELINE_PACKAGE_DIR_URL,\n )) {\n const match = fileName.match(\n DEFAULT_NATIVE_PIPELINE_LANGUAGE_PACKAGE_PATTERN,\n );\n if (match?.[1] !== undefined) {\n languages.add(match[1]);\n }\n }\n } catch (error) {\n throw new Error(\n `Default native pipeline package directory is unavailable: ${formatLoadError(error)}`,\n );\n }\n return [...languages].toSorted();\n};\n\nexport const available_default_native_pipeline_languages =\n availableDefaultNativePipelineLanguages;\n\nexport const readDefaultNativePipelinePackageFileAsync = async ({\n language,\n}: DefaultNativePipelinePackageFileOptions = {}): Promise<Uint8Array> => {\n const packageUrl = defaultNativePipelinePackageUrl(language);\n try {\n return await readFile(packageUrl);\n } catch (error) {\n throw new Error(\n `${defaultNativePipelinePackageDescription(language)} is unavailable: ${formatLoadError(error)}`,\n );\n }\n};\n\nexport const createNativePipelineFromPackageFile = ({\n binding,\n packagePath,\n expectedVersion,\n ...loadOptions\n}: NativePipelinePackageFileOptions): PreparedNativePipeline => {\n const resolvedBinding =\n binding ??\n loadNativeAnonymizeBinding({\n ...loadOptions,\n ...(expectedVersion !== undefined ? { expectedVersion } : {}),\n });\n if (binding && expectedVersion !== undefined) {\n assertNativeBindingVersion({ binding, expectedVersion });\n }\n return createNativePipelineFromPackage({\n binding: resolvedBinding,\n packageBytes: readNativePipelinePackageFile(packagePath),\n });\n};\n\nexport const createNativePipelineFromDefaultPackage = (\n options: DefaultNativePipelinePackageOptions = {},\n): PreparedNativePipeline => {\n const resolvedOptions = resolveDefaultNativePipelineOptions(options);\n return applyDefaultNativePipelineWarmup(\n createNativePipelineFromResolvedDefaultPackage(resolvedOptions),\n resolvedOptions.warmup,\n );\n};\n\nexport const create_native_pipeline_from_default_package = (\n options: DefaultNativePipelinePackageOptions = {},\n): PreparedNativePipeline => createNativePipelineFromDefaultPackage(options);\n\nexport const getDefaultNativePipeline = (\n options: DefaultNativePipelinePackageOptions = {},\n): PreparedNativePipeline => {\n const resolvedOptions = resolveDefaultNativePipelineOptions(options);\n const cache = defaultPipelineCacheFor(resolvedOptions.binding);\n const key = defaultPipelineCacheKey(resolvedOptions);\n const cached = cache.get(key);\n if (cached !== undefined) {\n return applyDefaultNativePipelineWarmup(cached, resolvedOptions.warmup);\n }\n const pipeline =\n createNativePipelineFromResolvedDefaultPackage(resolvedOptions);\n cache.set(key, pipeline);\n return applyDefaultNativePipelineWarmup(pipeline, resolvedOptions.warmup);\n};\n\nexport const get_default_native_pipeline = (\n options: DefaultNativePipelinePackageOptions = {},\n): PreparedNativePipeline => getDefaultNativePipeline(options);\n\nexport const preloadDefaultNativePipeline = (\n options: DefaultNativePipelinePackageOptions = {},\n): PreparedNativePipeline => {\n const pipeline = getDefaultNativePipeline(options);\n return applyDefaultNativePipelineWarmup(\n pipeline,\n DEFAULT_NATIVE_PIPELINE_WARMUPS.lazyRegex,\n );\n};\n\nexport const preload_default_native_pipeline = (\n options: DefaultNativePipelinePackageOptions = {},\n): PreparedNativePipeline => preloadDefaultNativePipeline(options);\n\nexport const redactDefaultText = (\n fullText: string,\n operators?: NativeOperatorConfig,\n options: DefaultNativePipelinePackageOptions = {},\n): NativeStaticRedactionResult =>\n getDefaultNativePipeline(options).redactText(fullText, operators);\n\nexport const redact_default_text = (\n fullText: string,\n operators?: NativeOperatorConfig,\n options: DefaultNativePipelinePackageOptions = {},\n): NativeStaticRedactionResult =>\n redactDefaultText(fullText, operators, options);\n\nexport const redactDefaultTextJson = (\n fullText: string,\n operators?: NativeOperatorConfig,\n options: DefaultNativePipelinePackageOptions = {},\n): string =>\n getDefaultNativePipeline(options).redact_text_json(fullText, operators);\n\nexport const redact_default_text_json = (\n fullText: string,\n operators?: NativeOperatorConfig,\n options: DefaultNativePipelinePackageOptions = {},\n): string => redactDefaultTextJson(fullText, operators, options);\n\nexport const preloadDefaultNativePipelineAsync = (\n options: DefaultNativePipelinePackageOptions = {},\n): Promise<PreparedNativePipeline> => {\n const resolvedOptions = {\n ...resolveDefaultNativePipelineOptions(options),\n warmup: DEFAULT_NATIVE_PIPELINE_WARMUPS.lazyRegex,\n };\n const cache = defaultPipelineCacheFor(resolvedOptions.binding);\n const key = defaultPipelineCacheKey(resolvedOptions);\n const cached = cache.get(key);\n if (cached !== undefined) {\n return Promise.resolve(\n applyDefaultNativePipelineWarmup(cached, resolvedOptions.warmup),\n );\n }\n\n const inflightCache = defaultPipelineInflightCacheFor(\n resolvedOptions.binding,\n );\n const inflight = inflightCache.get(key);\n if (inflight !== undefined) {\n return inflight;\n }\n\n const promise = createNativePipelineFromResolvedDefaultPackageAsync(\n resolvedOptions,\n )\n .then((pipeline) => {\n cache.set(key, pipeline);\n return applyDefaultNativePipelineWarmup(pipeline, resolvedOptions.warmup);\n })\n .finally(() => {\n inflightCache.delete(key);\n });\n inflightCache.set(key, promise);\n return promise;\n};\n\nconst resolveDefaultNativePipelineOptions = ({\n binding,\n language,\n packagePath,\n warmup,\n expectedVersion,\n ...loadOptions\n}: DefaultNativePipelinePackageOptions = {}): ResolvedDefaultNativePipelineOptions => {\n if (language !== undefined && packagePath !== undefined) {\n throw new Error(\"Use either language or packagePath, not both\");\n }\n const resolvedBinding =\n binding ??\n loadNativeAnonymizeBinding({\n ...loadOptions,\n ...(expectedVersion !== undefined ? { expectedVersion } : {}),\n });\n if (binding && expectedVersion !== undefined) {\n assertNativeBindingVersion({ binding, expectedVersion });\n }\n return {\n binding: resolvedBinding,\n warmup: normalizeDefaultNativePipelineWarmup(warmup),\n ...(language !== undefined\n ? { language: resolveDefaultNativePipelineLanguage(language) }\n : {}),\n ...(packagePath !== undefined ? { packagePath } : {}),\n };\n};\n\nconst applyDefaultNativePipelineWarmup = (\n pipeline: PreparedNativePipeline,\n warmup: DefaultNativePipelineWarmup,\n): PreparedNativePipeline => {\n if (warmup !== DEFAULT_NATIVE_PIPELINE_WARMUPS.lazyRegex) {\n return pipeline;\n }\n if (!warmedDefaultNativePipelines.has(pipeline)) {\n pipeline.warmLazyRegex();\n warmedDefaultNativePipelines.add(pipeline);\n }\n return pipeline;\n};\n\nconst createNativePipelineFromResolvedDefaultPackage = ({\n binding,\n language,\n packagePath,\n}: ResolvedDefaultNativePipelineOptions): PreparedNativePipeline => {\n const packageBytes =\n packagePath === undefined\n ? readDefaultNativePipelinePackageFile(\n defaultPackageFileOptions(language),\n )\n : readNativePipelinePackageFile(packagePath);\n return createNativePipelineFromTrustedDefaultPackage(binding, packageBytes);\n};\n\nconst createNativePipelineFromResolvedDefaultPackageAsync = async ({\n binding,\n language,\n packagePath,\n}: ResolvedDefaultNativePipelineOptions): Promise<PreparedNativePipeline> => {\n const packageBytes =\n packagePath === undefined\n ? await readDefaultNativePipelinePackageFileAsync(\n defaultPackageFileOptions(language),\n )\n : await readNativePipelinePackageFileAsync(packagePath);\n return createNativePipelineFromTrustedDefaultPackage(binding, packageBytes);\n};\n\nconst createNativePipelineFromTrustedDefaultPackage = (\n binding: NativeAnonymizeBinding,\n packageBytes: Uint8Array,\n): PreparedNativePipeline =>\n new PreparedNativePipeline(\n new PreparedNativeAnonymizer(\n binding.NativePreparedSearch.fromTrustedPreparedPackageBytesWithoutCache?.(\n packageBytes,\n ) ??\n binding.NativePreparedSearch.fromTrustedPreparedPackageBytes?.(\n packageBytes,\n ) ??\n binding.NativePreparedSearch.fromPreparedPackageBytesWithoutCache?.(\n packageBytes,\n ) ??\n binding.NativePreparedSearch.fromPreparedPackageBytes(packageBytes),\n ),\n );\n\nconst defaultPackageFileOptions = (\n language: string | undefined,\n): DefaultNativePipelinePackageFileOptions =>\n language === undefined ? {} : { language };\n\nconst normalizeDefaultNativePipelineWarmup = (\n warmup: DefaultNativePipelineWarmup | undefined,\n): DefaultNativePipelineWarmup => {\n if (warmup === undefined) {\n return DEFAULT_NATIVE_PIPELINE_WARMUPS.none;\n }\n switch (warmup) {\n case DEFAULT_NATIVE_PIPELINE_WARMUPS.lazyRegex:\n case DEFAULT_NATIVE_PIPELINE_WARMUPS.none:\n return warmup;\n }\n throw new Error(\n 'Default native pipeline warmup must be \"lazy-regex\" or \"none\"',\n );\n};\n\nconst resolveNativeSdkBinding = ({\n binding,\n expectedVersion,\n ...loadOptions\n}: NativeSdkOptions): NativeAnonymizeBinding => {\n const resolvedBinding =\n binding ??\n loadNativeAnonymizeBinding({\n ...loadOptions,\n ...(expectedVersion !== undefined ? { expectedVersion } : {}),\n });\n if (binding && expectedVersion !== undefined) {\n assertNativeBindingVersion({ binding, expectedVersion });\n }\n return resolvedBinding;\n};\n\nconst defaultPipelineCacheFor = (\n binding: NativeAnonymizeBinding,\n): Map<string, PreparedNativePipeline> => {\n const cached = defaultNativePipelineCache.get(binding);\n if (cached !== undefined) {\n return cached;\n }\n const created = new Map<string, PreparedNativePipeline>();\n defaultNativePipelineCache.set(binding, created);\n return created;\n};\n\nconst defaultPipelineInflightCacheFor = (\n binding: NativeAnonymizeBinding,\n): Map<string, Promise<PreparedNativePipeline>> => {\n const cached = defaultNativePipelineInflightCache.get(binding);\n if (cached !== undefined) {\n return cached;\n }\n const created = new Map<string, Promise<PreparedNativePipeline>>();\n defaultNativePipelineInflightCache.set(binding, created);\n return created;\n};\n\nconst defaultPipelineCacheKey = ({\n binding,\n language,\n packagePath,\n}: ResolvedDefaultNativePipelineOptions): string =>\n [\n binding.nativePackageVersion(),\n packagePath ??\n (language === undefined\n ? DEFAULT_NATIVE_PIPELINE_PACKAGE_CACHE_KEY\n : `language:${language}`),\n ].join(\"\\0\");\n\nconst defaultNativePipelinePackageUrl = (language: string | undefined): URL => {\n if (language === undefined) {\n return DEFAULT_NATIVE_PIPELINE_PACKAGE_URL;\n }\n const normalized = resolveDefaultNativePipelineLanguage(language);\n return defaultNativePipelineLanguagePackageUrl(normalized);\n};\n\nconst defaultNativePipelineLanguagePackageUrl = (language: string): URL =>\n new URL(`../native-pipeline.${language}.stlanonpkg`, import.meta.url);\n\nconst resolveDefaultNativePipelineLanguage = (language: string): string => {\n const normalized = normalizeDefaultNativePipelineLanguage(language);\n const exactUrl = defaultNativePipelineLanguagePackageUrl(normalized);\n if (existsSync(exactUrl)) {\n return normalized;\n }\n const baseLanguage = normalized.split(\"-\").at(0);\n if (baseLanguage === undefined || baseLanguage === normalized) {\n return normalized;\n }\n const baseUrl = defaultNativePipelineLanguagePackageUrl(baseLanguage);\n if (existsSync(baseUrl)) {\n return baseLanguage;\n }\n return normalized;\n};\n\nconst defaultNativePipelinePackageDescription = (\n language: string | undefined,\n): string =>\n language === undefined\n ? \"Default native pipeline package\"\n : `Default native pipeline package for language \"${resolveDefaultNativePipelineLanguage(language)}\"`;\n\nconst normalizeDefaultNativePipelineLanguage = (language: string): string => {\n const normalized = language.trim().toLowerCase();\n if (!DEFAULT_NATIVE_PIPELINE_LANGUAGE_PATTERN.test(normalized)) {\n throw new Error(\n `Default native pipeline language must match ${DEFAULT_NATIVE_PIPELINE_LANGUAGE_PATTERN.source}`,\n );\n }\n return normalized;\n};\n\ntype NativeBindingSpecifiersOptions = {\n arch: string;\n env: Record<string, string | undefined>;\n libc: NativeLibc | undefined;\n platform: string;\n};\n\nconst nativeBindingSpecifiers = ({\n arch,\n env,\n libc,\n platform,\n}: NativeBindingSpecifiersOptions): string[] => {\n const specifiers: string[] = [];\n const overridePath = env[PACKAGE_SPECIFIC_NATIVE_PATH];\n if (overridePath) {\n specifiers.push(overridePath);\n }\n specifiers.push(LOCAL_NATIVE_LOADER);\n const platformPackage = nativeBindingPackageName({ arch, libc, platform });\n if (platformPackage !== null) {\n specifiers.push(platformPackage);\n }\n return specifiers;\n};\n\ntype NativeBindingTarget = {\n platform: string;\n arch: string;\n libc?: NativeLibc;\n package: string;\n};\n\n// Single source of truth for published native sidecars. Both the runtime\n// package lookup and the \"unsupported target\" error message derive from this\n// table, so a target is never advertised as supported without a package (and\n// vice versa). musl Linux is intentionally absent: no musl sidecar is shipped.\nconst NATIVE_BINDING_TARGETS: readonly NativeBindingTarget[] = [\n {\n platform: \"darwin\",\n arch: \"arm64\",\n package: \"@stll/anonymize-darwin-arm64\",\n },\n { platform: \"darwin\", arch: \"x64\", package: \"@stll/anonymize-darwin-x64\" },\n {\n platform: \"linux\",\n arch: \"arm64\",\n libc: \"gnu\",\n package: \"@stll/anonymize-linux-arm64-gnu\",\n },\n {\n platform: \"linux\",\n arch: \"x64\",\n libc: \"gnu\",\n package: \"@stll/anonymize-linux-x64-gnu\",\n },\n { platform: \"win32\", arch: \"x64\", package: \"@stll/anonymize-win32-x64-msvc\" },\n];\n\ntype NativeBindingPackageNameOptions = {\n arch: string;\n libc: NativeLibc | undefined;\n platform: string;\n};\n\ntype DescribeNativeTargetOptions = {\n arch: string;\n libc?: NativeLibc | undefined;\n platform: string;\n};\n\nconst describeNativeTarget = ({\n arch,\n libc,\n platform,\n}: DescribeNativeTargetOptions): string =>\n libc === undefined ? `${platform}-${arch}` : `${platform}-${arch}-${libc}`;\n\nconst SUPPORTED_NATIVE_TARGETS: readonly string[] = NATIVE_BINDING_TARGETS.map(\n (target) => describeNativeTarget(target),\n);\n\nconst nativeBindingPackageName = ({\n arch,\n libc,\n platform,\n}: NativeBindingPackageNameOptions): string | null => {\n const match = NATIVE_BINDING_TARGETS.find(\n (target) =>\n target.platform === platform &&\n target.arch === arch &&\n (target.libc === undefined || target.libc === libc),\n );\n return match?.package ?? null;\n};\n\nconst unsupportedNativeTargetError = ({\n arch,\n errors,\n libc,\n platform,\n}: NativeBindingPackageNameOptions & { errors: string[] }): Error => {\n const target = describeNativeTarget({ arch, libc, platform });\n const supported = SUPPORTED_NATIVE_TARGETS.join(\", \");\n const attempts = errors.length > 0 ? `\\n${errors.join(\"\\n\")}` : \"\";\n return new Error(\n `No native anonymize binding is published for ${target}; supported targets: ${supported}. Set ${PACKAGE_SPECIFIC_NATIVE_PATH} to a locally built binding to run on this platform.${attempts}`,\n );\n};\n\nconst detectNativeLibc = (platform: string): NativeLibc | undefined => {\n if (platform !== \"linux\") {\n return undefined;\n }\n const report = process.report?.getReport();\n const header =\n isPropertyBag(report) && isPropertyBag(report[\"header\"])\n ? report[\"header\"]\n : null;\n return typeof header?.[\"glibcVersionRuntime\"] === \"string\" ? \"gnu\" : \"musl\";\n};\n\ntype TryLoadNativeBindingOptions = {\n specifier: string;\n requireModule: NativeRequire;\n errors: string[];\n};\n\nconst tryLoadNativeBinding = ({\n specifier,\n requireModule,\n errors,\n}: TryLoadNativeBindingOptions): NativeAnonymizeBinding | null => {\n try {\n const loaded = requireModule(specifier);\n const binding = toNativeAnonymizeBinding(loaded);\n if (binding) {\n return binding;\n }\n errors.push(`${specifier}: module does not match native binding shape`);\n } catch (error) {\n errors.push(`${specifier}: ${formatLoadError(error)}`);\n }\n return null;\n};\n\nconst toNativeAnonymizeBinding = (\n value: unknown,\n): NativeAnonymizeBinding | null => {\n const candidate =\n isPropertyBag(value) && isPropertyBag(value[\"default\"])\n ? value[\"default\"]\n : value;\n return isNativeAnonymizeBinding(candidate) ? candidate : null;\n};\n\nconst isNativeAnonymizeBinding = (\n candidate: unknown,\n): candidate is NativeAnonymizeBinding => {\n if (!isPropertyBag(candidate)) {\n return false;\n }\n if (typeof candidate[\"nativePackageVersion\"] !== \"function\") {\n return false;\n }\n if (typeof candidate[\"normalizeForSearch\"] !== \"function\") {\n return false;\n }\n if (typeof candidate[\"prepareStaticSearchPackageBytes\"] !== \"function\") {\n return false;\n }\n if (\n typeof candidate[\"prepareStaticSearchCompressedPackageBytes\"] !== \"function\"\n ) {\n return false;\n }\n const preparedSearch = candidate[\"NativePreparedSearch\"];\n if (!isPropertyBag(preparedSearch)) {\n return false;\n }\n if (typeof preparedSearch[\"fromConfigJsonBytes\"] !== \"function\") {\n return false;\n }\n if (typeof preparedSearch[\"fromPreparedPackageBytes\"] !== \"function\") {\n return false;\n }\n return true;\n};\n\nconst isPropertyBag = (value: unknown): value is Record<string, unknown> =>\n (typeof value === \"object\" && value !== null) || typeof value === \"function\";\n\nconst formatLoadError = (error: unknown): string => {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"native-node2.mjs","names":["languageScopes","nativePackageVersionWithBinding","normalizeForSearchWithBinding","prepareSearchPackageWithBinding","loadPreparedPackageWithBinding","redactTextWithBinding","redactTextJsonWithBinding","redactTextStreamJsonWithBinding","diagnosticsJsonWithBinding","diagnosticsStreamJsonWithBinding","summaryDiagnosticsJsonWithBinding"],"sources":["../src/context.ts","../src/data/language-scopes.json","../src/language-scope.ts","../src/types.ts","../src/util/language-selection.ts","../src/pipeline-cache-key.ts","../src/native-pipeline.ts","../src/native-default-config.ts","../src/native-node.ts"],"sourcesContent":["/**\n * Cached state for a single pipeline run (or a sequence of runs sharing the\n * same config). The native pipeline builds its prepared package once and reuses\n * it across calls with the same config; the package bytes and the key/promise\n * that guard concurrent builds live here so callers can share one warmed\n * context.\n */\nexport type PipelineContext = {\n // ── Native prepared-package cache ─────────────\n nativePipelinePackage: Uint8Array | null;\n nativePipelinePackageKey: string;\n nativePipelinePackagePromise: Promise<Uint8Array> | null;\n};\n\n/** Create a fresh, empty pipeline context. */\nexport const createPipelineContext = (): PipelineContext => ({\n nativePipelinePackage: null,\n nativePipelinePackageKey: \"\",\n nativePipelinePackagePromise: null,\n});\n\n/**\n * Module-level default context. Used when callers\n * don't provide an explicit context, preserving full\n * backward compatibility with the existing API.\n */\nexport const defaultContext: PipelineContext = createPipelineContext();\n","","import languageScopes from \"./data/language-scopes.json\";\n\nimport type { PipelineConfig } from \"./types\";\n\ntype LanguageScope = {\n nameCorpusLanguages?: readonly string[];\n denyListCountries?: readonly string[];\n};\n\ntype LanguageScopeData = {\n languages: Record<string, LanguageScope>;\n};\n\nconst scopeData = languageScopes as LanguageScopeData;\n\nconst normalizeLanguage = (language: string): string =>\n language.trim().toLowerCase();\n\nconst fallbackLanguage = (language: string): string | null => {\n const index = language.indexOf(\"-\");\n return index === -1 ? null : language.slice(0, index);\n};\n\nconst uniquePush = (target: string[], values: readonly string[]): void => {\n const seen = new Set(target);\n for (const value of values) {\n if (seen.has(value)) {\n continue;\n }\n seen.add(value);\n target.push(value);\n }\n};\n\nconst resolveLanguageScope = (language: string): LanguageScope | null => {\n const normalized = normalizeLanguage(language);\n if (normalized.length === 0) {\n return null;\n }\n const exact = scopeData.languages[normalized];\n if (exact !== undefined) {\n return exact;\n }\n const fallback = fallbackLanguage(normalized);\n return fallback === null ? null : (scopeData.languages[fallback] ?? null);\n};\n\nconst configuredLanguages = (config: PipelineConfig): readonly string[] => {\n if (config.languages !== undefined) {\n return config.languages;\n }\n return config.language === undefined ? [] : [config.language];\n};\n\nexport const configuredContentLanguages = (\n config: Pick<PipelineConfig, \"language\" | \"languages\">,\n): readonly string[] | undefined => {\n if (config.languages !== undefined) {\n return config.languages;\n }\n return config.language === undefined ? undefined : [config.language];\n};\n\nexport const applyPipelineLanguageScope = (\n config: PipelineConfig,\n): PipelineConfig => {\n const languages = configuredLanguages(config);\n if (languages.length === 0) {\n return config;\n }\n\n const nameCorpusLanguages: string[] = [];\n const denyListCountries: string[] = [];\n for (const language of languages) {\n const scope = resolveLanguageScope(language);\n if (scope === null) {\n continue;\n }\n uniquePush(nameCorpusLanguages, scope.nameCorpusLanguages ?? []);\n uniquePush(denyListCountries, scope.denyListCountries ?? []);\n }\n\n const next: Partial<PipelineConfig> = {};\n if (\n config.nameCorpusLanguages === undefined &&\n nameCorpusLanguages.length > 0\n ) {\n next.nameCorpusLanguages = nameCorpusLanguages;\n }\n if (config.denyListCountries === undefined && denyListCountries.length > 0) {\n next.denyListCountries = denyListCountries;\n }\n\n return Object.keys(next).length === 0 ? config : { ...config, ...next };\n};\n","// Runtime-free constants live in `./constants`; re-exported\n// here for back-compat with existing call sites that import\n// from `@stll/anonymize` directly.\n//\n// `verbatimModuleSyntax` requires an explicit type-only\n// import for any name used locally as a type even when it\n// is also re-exported below — applies to `DetectionSource`\n// (used by `Entity`) and `OperatorType` (used by\n// `OperatorConfig`).\nimport type { DetectionSource, OperatorType } from \"./constants\";\nimport { DETECTION_SOURCES } from \"./constants\";\n\nexport {\n DETECTION_SOURCES,\n DETECTOR_PRIORITY,\n type DetectionSource,\n} from \"./constants\";\n\n/**\n * Fields shared by every entity span in the source text.\n */\ntype EntityBase = {\n start: number;\n end: number;\n label: string;\n text: string;\n score: number;\n sourceDetail?: \"custom-deny-list\" | \"custom-regex\" | \"gazetteer-extension\";\n};\n\n/**\n * A PII entity span found by a primary detection layer\n * (regex, NER, legal forms, deny list, ...).\n */\nexport type DetectedEntity = EntityBase & {\n source: Exclude<DetectionSource, typeof DETECTION_SOURCES.COREFERENCE>;\n};\n\n/**\n * An alias mention of a previously detected entity: a\n * defined term (\"the Seller\") or a propagated bare\n * mention (\"Acme\" after \"Acme Corp.\").\n *\n * `corefSourceText` is required by construction, so an\n * alias cannot exist without the link back to its source\n * entity. Placeholder numbering reads it to give the\n * alias the same placeholder as the source. The link\n * travels with the entity instead of living in a\n * side-channel map that a producer could forget to\n * write — or that a later pass could clear.\n */\nexport type CorefAliasEntity = EntityBase & {\n source: typeof DETECTION_SOURCES.COREFERENCE;\n /** Full text of the source entity this alias refers to. */\n corefSourceText: string;\n};\n\n/**\n * A detected PII entity span in the source text.\n * Every detection layer produces these.\n */\nexport type Entity = DetectedEntity | CorefAliasEntity;\n\n/**\n * Entity after human review. Extends the base Entity\n * with a review decision.\n */\nexport type ReviewDecision = \"confirmed\" | \"rejected\" | \"relabeled\";\n\nexport type ReviewedEntity = Entity & {\n decision?: ReviewDecision;\n originalLabel?: string;\n};\n\n/**\n * A single entry in the workspace-scoped gazetteer\n * (deny list). Persisted in IndexedDB.\n */\nexport type GazetteerEntry = {\n id: string;\n canonical: string;\n label: string;\n variants: string[];\n workspaceId: string;\n createdAt: number;\n source: \"manual\" | \"confirmed-from-model\";\n};\n\n/** Extraction strategy — closed discriminated union. */\nexport type TriggerStrategy =\n | {\n type: \"to-next-comma\";\n /**\n * Optional list of lowercase keywords that terminate\n * the value scan, in addition to commas/newlines. Useful\n * for triggers like court names that may continue past\n * a missing comma into adjacent clause text (\"Městským\n * soudem v Praze dne 1. 1. 2020\"); listing `\"dne\"` here\n * stops the scan at the date boundary. Matched on a\n * word-boundary, case-insensitive.\n */\n stopWords?: string[];\n /**\n * Hard cap on the captured span length, in characters,\n * regardless of where the next comma / stop char sits.\n * Use for triggers that label short formulaic phrases\n * (\"State of Delaware\") and must not absorb the rest\n * of a long forum-selection clause when the comma is\n * sentences away. Falls back to the default 100-char\n * fallback when omitted.\n */\n maxLength?: number;\n }\n | { type: \"to-end-of-line\" }\n | { type: \"n-words\"; count: number }\n | { type: \"company-id-value\" }\n | { type: \"address\"; maxChars?: number }\n | {\n /**\n * Extract the first regex match in the value text.\n * Useful for shape-bounded values that follow a\n * label on the same line as other fields, where\n * `to-end-of-line` would over-capture. The pattern\n * is anchored to the start of the (already\n * leading-whitespace-stripped) value, so use\n * `(?:.*?)` prefix only when intentional.\n */\n type: \"match-pattern\";\n pattern: string;\n flags?: string;\n };\n\n/** Validation rules — closed discriminated union. */\nexport type TriggerValidation =\n | { type: \"starts-uppercase\" }\n | { type: \"min-length\"; min: number }\n | { type: \"max-length\"; max: number }\n | { type: \"no-digits\" }\n | { type: \"has-digits\" }\n | {\n type: \"matches-pattern\";\n pattern: string;\n flags?: string;\n }\n /**\n * Run a named stdnum validator (checksum + length)\n * against the captured value. Keeps the trigger\n * path symmetrical with the formatted-regex\n * detectors so e.g. `CPF nº 00000000000` does not\n * survive as a tax-ID entity.\n */\n | { type: \"valid-id\"; validator: ValidIdValidator };\n\n/** Built-in stdnum validators that can be referenced\n * by `valid-id` validations. */\nexport type ValidIdValidator = \"br.cpf\" | \"br.cnpj\" | \"us.rtn\";\n\n/** Auto-generated trigger variants — closed set. */\nexport type TriggerExtension =\n | \"add-colon\"\n | \"add-trailing-space\"\n | \"add-colon-space\"\n | \"normalize-spaces\";\n\n/** V2 trigger config entry (JSON shape). */\nexport type TriggerGroupConfig = {\n id?: string;\n triggers: string[];\n label: string;\n strategy: TriggerStrategy;\n extensions?: TriggerExtension[];\n validations?: TriggerValidation[];\n /** When true, include the trigger text in the\n * entity span (e.g., court names). */\n includeTrigger?: boolean;\n};\n\n/** Compiled validation with pre-built regex. */\nexport type CompiledValidation =\n | { type: \"starts-uppercase\"; re: RegExp }\n | { type: \"min-length\"; min: number }\n | { type: \"max-length\"; max: number }\n | { type: \"no-digits\"; re: RegExp }\n | { type: \"has-digits\"; re: RegExp }\n | { type: \"matches-pattern\"; re: RegExp }\n | {\n type: \"valid-id\";\n validator: ValidIdValidator;\n check: (value: string) => boolean;\n };\n\n/**\n * Runtime rule — one per trigger string after\n * expansion. Fed to the Aho-Corasick automaton.\n */\nexport type TriggerRule = {\n trigger: string;\n label: string;\n strategy: TriggerStrategy;\n validations: CompiledValidation[];\n includeTrigger: boolean;\n};\n\nexport {\n ENTITY_CAPABILITIES,\n ENTITY_LABELS,\n ENTITY_SELECTIONS,\n OPERATOR_TYPES,\n type DefaultEntityLabel,\n type EntityCapability,\n type EntityLabel,\n type EntitySelection,\n type OperatorType,\n} from \"./constants\";\n\n/** Per-label operator selection. Key is the entity label. */\nexport type MaskDirection = \"start\" | \"end\";\n\nexport type MaskOperatorConfig = {\n type: \"mask\";\n maskingCharacter: string;\n charactersToMask: number;\n direction: MaskDirection;\n};\n\nexport type OperatorSelection =\n | Exclude<OperatorType, \"mask\">\n | MaskOperatorConfig;\n\nexport type OperatorConfig = {\n /** Operator per label. Missing labels default to \"replace\". */\n operators: Record<string, OperatorSelection>;\n /** Custom replacement string for the redact operator. */\n redactString: string;\n};\n\n/** Whether an operator produces a reversible redaction entry. */\ntype OperatorReversibility = \"reversible\" | \"irreversible\" | \"preserving\";\n\nexport type AnonymisationOperator = {\n type: OperatorType;\n reversibility: OperatorReversibility;\n /**\n * Apply the operator to a single entity occurrence.\n * Returns the replacement string to embed in the document.\n */\n apply: (\n text: string,\n label: string,\n placeholder: string,\n redactString: string,\n selection: OperatorSelection,\n ) => string;\n};\n\n/**\n * Redacted document output with stable entity mapping.\n */\nexport type RedactionResult = {\n redactedText: string;\n /**\n * Maps placeholder to original text. Only populated for\n * reversible operators (replace). Empty for redact, keep, and mask.\n */\n redactionMap: Map<string, string>;\n /** Maps placeholder to the operator that produced it. */\n operatorMap: Map<string, OperatorType>;\n entityCount: number;\n};\n\n/**\n * Configuration for the detection pipeline.\n */\nexport type DenyListCategory =\n | \"Names\"\n | \"Places\"\n | \"Addresses\"\n | \"Courts\"\n | \"Financial\"\n | \"Government\"\n | \"Healthcare\"\n | \"Education\"\n | \"Political\"\n | \"Organizations\"\n | \"International\";\n\n/**\n * Metadata for a single dictionary entry in the\n * deny-list system. Mirrors the shape from\n * the anonymize-data package so consumers can pass\n * pre-loaded data without a runtime dependency.\n */\nexport type DictionaryMeta = {\n label: string;\n category: DenyListCategory;\n country: string | null;\n};\n\n/**\n * Caller-supplied exact terms for deny-list matching.\n * These entries are merged with the published deny-list\n * dictionaries when `enableDenyList` is enabled.\n */\nexport type CustomDenyListEntry = {\n value: string;\n label: string;\n variants?: readonly string[];\n};\n\n/**\n * Caller-supplied regex detector. The pattern is passed\n * to the native Rust regex engine, so use its supported\n * regex syntax. Inline flags such as `(?i)` are accepted\n * when supported by that engine.\n */\nexport type CustomRegexPattern = {\n pattern: string;\n label: string;\n score?: number;\n preparedArtifactPolicy?: \"include\" | \"omit\";\n};\n\n/**\n * Pre-loaded dictionary data for dependency injection.\n * Consumers that want name/city/deny-list detection\n * load dictionaries themselves (e.g. from the\n * anonymize-data package) and pass them here; the\n * anonymize package has zero cross-package imports.\n *\n * All fields are optional. When a field is absent,\n * the corresponding detection path is skipped (same\n * behavior as when no dictionaries are available).\n */\nexport type Dictionaries = {\n /**\n * First names per language code (e.g., \"cs\", \"de\").\n */\n firstNames?: Readonly<Record<string, readonly string[]>>;\n /**\n * Surnames per language code.\n */\n surnames?: Readonly<Record<string, readonly string[]>>;\n /**\n * Non-Western name tokens per locale code\n * (e.g., \"in\", \"ar\", \"ja-latn\", \"ko\", \"zh-latn\",\n * \"th\", \"vi\", \"fil\", \"id\"). Merged with bundled\n * names-nw-*.json data at init time.\n */\n nonWesternNames?: Readonly<Record<string, readonly string[]>>;\n /**\n * Pre-loaded deny-list dictionaries keyed by\n * dictionary ID (e.g., \"courts/CZ\", \"banks/DE\").\n * Each value is the array of terms for that\n * dictionary.\n */\n denyList?: Readonly<Record<string, readonly string[]>>;\n /**\n * Metadata per dictionary ID. Required when\n * `denyList` is provided so the pipeline knows\n * labels, categories, and country filters.\n */\n denyListMeta?: Readonly<Record<string, DictionaryMeta>>;\n /**\n * Pre-loaded city names, already merged across\n * all desired countries.\n *\n * Prefer `citiesByCountry` when callers also pass\n * `denyListCountries` / `denyListRegions`; merged\n * city arrays cannot be scoped after injection.\n */\n cities?: readonly string[];\n /**\n * Pre-loaded city names keyed by ISO 3166-1 alpha-2\n * country code. When provided, the deny-list builder\n * applies `denyListCountries` / `denyListRegions`\n * before adding city patterns to the search automaton.\n */\n citiesByCountry?: Readonly<Record<string, readonly string[]>>;\n};\n\nexport type PipelineConfig = {\n threshold: number;\n enableTriggerPhrases: boolean;\n enableRegex: boolean;\n /**\n * Expected content language codes. When present, these\n * derive default dictionary scopes for name corpus and\n * deny-list matching unless the lower-level scope fields\n * below are set explicitly.\n */\n languages?: string[];\n /**\n * Convenience form for single-language documents. Ignored\n * when `languages` is also provided.\n */\n language?: string;\n /**\n * Enables legal-form organization detection.\n * Required for typed callers; legacy untyped\n * callers that omit this field are treated as\n * enabled at runtime for backward compatibility.\n */\n enableLegalForms: boolean;\n /**\n * Enables first-name/surname/title corpus matching.\n * When deny-list mode is enabled, this also controls\n * whether name-corpus entries are injected into the\n * deny-list search automaton.\n */\n enableNameCorpus: boolean;\n /**\n * Optional language scope for first-name/surname\n * dictionaries, using the keys present in\n * `dictionaries.firstNames` / `dictionaries.surnames`\n * (for example `[\"en\", \"de\"]`). When omitted, all\n * injected name languages are used for backward\n * compatibility.\n */\n nameCorpusLanguages?: string[];\n enableDenyList: boolean;\n denyListCountries?: string[];\n denyListRegions?: string[];\n denyListExcludeCategories?: string[];\n /**\n * Caller-owned exact terms to match through the\n * deny-list layer. Requires `enableDenyList: true`.\n */\n customDenyList?: readonly CustomDenyListEntry[];\n /**\n * Caller-owned regex detectors. Requires\n * `enableRegex: true`.\n */\n customRegexes?: readonly CustomRegexPattern[];\n enableGazetteer: boolean;\n /**\n * Detect country names (ISO 3166-1 names, curated\n * aliases, alpha-3 codes). Defaults to true. Names\n * span all manifest languages plus widely-used\n * additions (Dutch, Russian, Chinese, Arabic, etc.).\n */\n enableCountries?: boolean;\n enableConfidenceBoost: boolean;\n enableCoreference: boolean;\n enableZoneClassification?: boolean;\n enableHotwordRules?: boolean;\n /**\n * Requested output labels. An empty array means\n * \"do not filter by label\" for deterministic detectors.\n */\n labels: string[];\n workspaceId: string;\n /**\n * Pre-loaded dictionary data for name, deny-list,\n * and city detection. When omitted, dictionary-based\n * detection paths are skipped. Consumers load from\n * the anonymize-data package and pass the data here.\n */\n dictionaries?: Dictionaries;\n};\n\nexport { DEFAULT_ENTITY_LABELS } from \"./constants\";\n\nexport const isLegalFormsEnabled = (\n config: Pick<PipelineConfig, \"enableLegalForms\">,\n): boolean => config.enableLegalForms !== false;\n","const normalizeLanguageCode = (language: string): string =>\n language.trim().toLowerCase();\n\nconst normalizeLanguageSelection = (\n languages: readonly string[] | undefined,\n): string[] =>\n languages === undefined\n ? []\n : languages\n .map(normalizeLanguageCode)\n .filter((language) => language.length > 0);\n\nexport const languageSelectionKey = (\n languages: readonly string[] | undefined,\n): string => {\n const normalized = normalizeLanguageSelection(languages).toSorted();\n return normalized.length === 0 ? \"*\" : normalized.join(\",\");\n};\n\nconst baseLanguage = (language: string): string => {\n const index = language.indexOf(\"-\");\n return index === -1 ? language : language.slice(0, index);\n};\n\nexport const languageConfigMatches = (\n configLanguage: string,\n selectedLanguages: readonly string[] | undefined,\n): boolean => {\n if (selectedLanguages === undefined || selectedLanguages.length === 0) {\n return true;\n }\n const normalizedSelectedLanguages =\n normalizeLanguageSelection(selectedLanguages);\n if (normalizedSelectedLanguages.length === 0) {\n return true;\n }\n\n const normalizedConfigLanguage = normalizeLanguageCode(configLanguage);\n if (normalizedConfigLanguage.length === 0) {\n return false;\n }\n\n const genericConfig =\n baseLanguage(normalizedConfigLanguage) === normalizedConfigLanguage;\n for (const normalizedLanguage of normalizedSelectedLanguages) {\n if (normalizedLanguage === normalizedConfigLanguage) {\n return true;\n }\n if (\n genericConfig &&\n baseLanguage(normalizedLanguage) === normalizedConfigLanguage\n ) {\n return true;\n }\n }\n\n return false;\n};\n","import {\n isLegalFormsEnabled,\n type GazetteerEntry,\n type PipelineConfig,\n} from \"./types\";\nimport { languageSelectionKey } from \"./util/language-selection\";\n\nconst DEFAULT_CUSTOM_REGEX_SCORE = 0.9;\n\nconst contentLanguageFingerprint = (\n config: Pick<PipelineConfig, \"language\" | \"languages\">,\n): string => {\n const languages =\n config.languages ??\n (config.language === undefined ? [] : [config.language]);\n return languageSelectionKey(languages);\n};\n\nexport const pipelineConfigKey = (\n config: PipelineConfig,\n gazetteerEntries: readonly GazetteerEntry[],\n): string => {\n const legalFormsEnabled = isLegalFormsEnabled(config);\n const customDenyFingerprint =\n config.enableDenyList && config.customDenyList\n ? config.customDenyList\n .map((entry) =>\n JSON.stringify({\n label: entry.label,\n value: entry.value,\n variants: [...(entry.variants ?? [])].sort(),\n }),\n )\n .sort()\n .join(\"\\n\")\n : \"\";\n const customRegexFingerprint =\n config.enableRegex && config.customRegexes\n ? config.customRegexes\n .map((entry) =>\n JSON.stringify({\n label: entry.label,\n pattern: entry.pattern,\n preparedArtifactPolicy: entry.preparedArtifactPolicy ?? null,\n score: entry.score ?? DEFAULT_CUSTOM_REGEX_SCORE,\n }),\n )\n .sort()\n .join(\"\\n\")\n : \"\";\n const gazFingerprint =\n config.enableGazetteer && gazetteerEntries.length > 0\n ? gazetteerEntries\n .map(\n (entry) =>\n `${entry.id}:${entry.canonical}:${entry.label}:${[\n ...entry.variants,\n ]\n .sort()\n .join(\",\")}`,\n )\n .toSorted()\n .join(\";\")\n : \"\";\n\n return (\n `${config.enableDenyList}:` +\n `${config.enableTriggerPhrases}:` +\n `${legalFormsEnabled}:` +\n `${config.enableNameCorpus}:` +\n `${contentLanguageFingerprint(config)}:` +\n `${config.nameCorpusLanguages?.toSorted().join(\",\") ?? \"\"}:` +\n `${config.enableRegex}:` +\n `${config.threshold}:` +\n `${config.enableConfidenceBoost}:` +\n `${config.enableHotwordRules === true}:` +\n `${config.enableCoreference === true}:` +\n `${config.enableZoneClassification === true}:` +\n `${config.labels.toSorted().join(\",\")}:` +\n `${config.denyListCountries?.toSorted().join(\",\") ?? \"\"}:` +\n `${config.denyListRegions?.toSorted().join(\",\") ?? \"\"}:` +\n `${config.denyListExcludeCategories?.toSorted().join(\",\") ?? \"\"}:` +\n `${customDenyFingerprint}:` +\n `${customRegexFingerprint}:` +\n `${config.enableGazetteer}:${gazFingerprint}:` +\n `${config.enableCountries !== false}`\n );\n};\n","import type { PipelineContext } from \"./context\";\nimport { defaultContext } from \"./context\";\nimport { applyPipelineLanguageScope } from \"./language-scope\";\nimport type { NativePreparedSearchConfig } from \"./native-search-config\";\nimport { pipelineConfigKey } from \"./pipeline-cache-key\";\nimport type { Dictionaries, GazetteerEntry, PipelineConfig } from \"./types\";\nimport {\n createNativePipelineFromPackage,\n PreparedNativePipeline,\n type NativeAnonymizeBinding,\n} from \"./native\";\n\nexport {\n PreparedNativePipeline,\n createNativePipelineFromPackage,\n} from \"./native\";\n\nexport type NativePipelineUnsupportedFeature = \"enableNer\";\n\nexport type NativePipelineCompatibility =\n | { status: \"supported\" }\n | {\n status: \"unsupported\";\n unsupportedFeatures: NativePipelineUnsupportedFeature[];\n };\n\nexport type NativePipelineBuildOptions = {\n binding: NativeAnonymizeBinding;\n config: PipelineConfig;\n gazetteerEntries?: GazetteerEntry[];\n context?: PipelineContext;\n};\n\nexport type NativePipelinePackageOptions = NativePipelineBuildOptions & {\n compressed?: boolean;\n};\n\nexport type { NativePipelineFromPackageOptions } from \"./native\";\n\ntype NativePipelinePackageCacheValue = Promise<Uint8Array> | Uint8Array;\n\n// Bounds each shared package cache (the dictionary-less bucket below, and\n// each per-`Dictionaries` bucket handed out by `sharedPackageCacheFor`) to a\n// fixed number of entries. `nativePackageCacheKey` fingerprints\n// caller-suppliable config (custom deny lists, custom regexes, gazetteer\n// entries) via `pipelineConfigKey`, so without a cap a caller that varies\n// those fields grows a bucket — and the multi-MB assembled packages it\n// holds — without limit.\nexport const SHARED_PACKAGE_CACHE_MAX_ENTRIES = 32;\n\nconst sharedPackageByDictionaries = new WeakMap<\n Dictionaries,\n Map<string, NativePipelinePackageCacheValue>\n>();\nconst sharedPackageWithoutDictionaries = new Map<\n string,\n NativePipelinePackageCacheValue\n>();\nconst dictionaryCacheIds = new WeakMap<Dictionaries, number>();\nlet nextDictionaryCacheId = 0;\n\n/** Record `key` as most-recently-used in `cache`, evicting the\n * least-recently-used entry first once the cache is at capacity. A `Map`'s\n * insertion order doubles as recency order here: touching an existing key\n * deletes then re-sets it to move it to the end, and eviction drops the\n * first (oldest) key.\n *\n * Evicting a still-in-flight build only drops the cache's reference to its\n * promise; the caller that started the build (and any concurrent caller that\n * already read the promise before eviction) still resolves it correctly via\n * the guarded `sharedCache.get(key) === promise` checks in\n * `getCachedNativePipelinePackage`. A later caller for the same key just\n * misses the dedupe and starts a fresh build — bounded memory takes priority\n * over perfect dedupe under cache pressure. */\nconst touchSharedPackageCacheEntry = (\n cache: Map<string, NativePipelinePackageCacheValue>,\n key: string,\n value: NativePipelinePackageCacheValue,\n): void => {\n cache.delete(key);\n if (cache.size >= SHARED_PACKAGE_CACHE_MAX_ENTRIES) {\n const oldestKey = cache.keys().next().value;\n if (oldestKey !== undefined) {\n cache.delete(oldestKey);\n }\n }\n cache.set(key, value);\n};\n\nconst dictionaryCacheKey = (dictionaries: Dictionaries | undefined): string => {\n if (dictionaries === undefined) {\n return \"none\";\n }\n const existing = dictionaryCacheIds.get(dictionaries);\n if (existing !== undefined) {\n return `dict:${existing}`;\n }\n nextDictionaryCacheId += 1;\n dictionaryCacheIds.set(dictionaries, nextDictionaryCacheId);\n return `dict:${nextDictionaryCacheId}`;\n};\n\nconst sharedPackageCacheFor = (\n dictionaries: Dictionaries | undefined,\n): Map<string, NativePipelinePackageCacheValue> => {\n if (dictionaries === undefined) {\n return sharedPackageWithoutDictionaries;\n }\n const cached = sharedPackageByDictionaries.get(dictionaries);\n if (cached !== undefined) {\n return cached;\n }\n const created = new Map<string, NativePipelinePackageCacheValue>();\n sharedPackageByDictionaries.set(dictionaries, created);\n return created;\n};\n\nexport const getNativePipelineCompatibility = (\n config: PipelineConfig,\n): NativePipelineCompatibility => {\n const unsupportedFeatures: NativePipelineUnsupportedFeature[] = [];\n\n // `enableNer` is no longer part of `PipelineConfig`; untyped callers that\n // still request it (any truthy value, e.g. `1` or `\"true\"` from loose\n // JSON) must fail fast instead of silently losing NER spans.\n if (\"enableNer\" in config && Boolean(config.enableNer)) {\n unsupportedFeatures.push(\"enableNer\");\n }\n if (unsupportedFeatures.length === 0) {\n return { status: \"supported\" };\n }\n return { status: \"unsupported\", unsupportedFeatures };\n};\n\nexport const assertNativePipelineSupported = (config: PipelineConfig): void => {\n const compatibility = getNativePipelineCompatibility(config);\n if (compatibility.status === \"supported\") {\n return;\n }\n throw new Error(\n `Native pipeline does not yet support: ${compatibility.unsupportedFeatures.join(\", \")}`,\n );\n};\n\nconst encoder = new TextEncoder();\n\ntype AssembleInputs = {\n pipelineConfigJson: Uint8Array;\n dictionariesJson: Uint8Array | undefined;\n gazetteerJson: Uint8Array | undefined;\n};\n\n/**\n * Serialize the assembler inputs the Rust binding expects. Dictionaries are\n * stripped from the pipeline config and passed out of band: the assembler reads\n * the separate bundle preferentially, and keeping the (large) dictionaries out\n * of the config JSON avoids serializing them twice.\n */\nconst toAssembleInputs = (\n { dictionaries, ...config }: PipelineConfig,\n gazetteerEntries: readonly GazetteerEntry[],\n): AssembleInputs => ({\n pipelineConfigJson: encoder.encode(JSON.stringify(config)),\n dictionariesJson:\n dictionaries === undefined\n ? undefined\n : encoder.encode(JSON.stringify(dictionaries)),\n gazetteerJson:\n gazetteerEntries.length === 0\n ? undefined\n : encoder.encode(JSON.stringify(gazetteerEntries)),\n});\n\nconst assemblePackageBytes = (\n binding: NativeAnonymizeBinding,\n { pipelineConfigJson, dictionariesJson, gazetteerJson }: AssembleInputs,\n compressed: boolean,\n): Uint8Array => {\n const assemble = compressed\n ? binding.assembleStaticSearchCompressedPackageBytes\n : binding.assembleStaticSearchPackageBytes;\n if (assemble === undefined) {\n throw new Error(\n \"Native anonymize binding does not support static-search config assembly\",\n );\n }\n return assemble(pipelineConfigJson, dictionariesJson, gazetteerJson);\n};\n\nexport const prepareNativePipelineConfig = async ({\n binding,\n config,\n gazetteerEntries = [],\n}: Omit<\n NativePipelineBuildOptions,\n \"context\"\n>): Promise<NativePreparedSearchConfig> => {\n const scopedConfig = applyPipelineLanguageScope(config);\n assertNativePipelineSupported(scopedConfig);\n const assemble = binding.assembleStaticSearchConfigJson;\n if (assemble === undefined) {\n throw new Error(\n \"Native anonymize binding does not support static-search config assembly\",\n );\n }\n const { pipelineConfigJson, dictionariesJson, gazetteerJson } =\n toAssembleInputs(scopedConfig, gazetteerEntries);\n const configJson = assemble(\n pipelineConfigJson,\n dictionariesJson,\n gazetteerJson,\n );\n return JSON.parse(new TextDecoder().decode(configJson));\n};\n\nexport const prepareNativePipelinePackage = async ({\n binding,\n config,\n gazetteerEntries = [],\n context,\n compressed = false,\n}: NativePipelinePackageOptions): Promise<Uint8Array> => {\n const packageBytes = await getCachedNativePipelinePackage({\n config,\n binding,\n gazetteerEntries,\n ...(context ? { context } : {}),\n compressed,\n });\n // Return a genuine copy: with the real NAPI binding packageBytes is a Node\n // Buffer, and Buffer.prototype.slice() yields a memory-sharing view, so a\n // caller mutating it would corrupt the shared cache and ctx.nativePipelinePackage.\n return new Uint8Array(packageBytes);\n};\n\nexport const createNativePipelineFromConfig = async ({\n binding,\n config,\n gazetteerEntries = [],\n context,\n}: NativePipelineBuildOptions): Promise<PreparedNativePipeline> => {\n const packageBytes = await getCachedNativePipelinePackage({\n binding,\n config,\n gazetteerEntries,\n ...(context ? { context } : {}),\n });\n return createNativePipelineFromPackage({ binding, packageBytes });\n};\n\nconst getCachedNativePipelinePackage = async ({\n binding,\n config,\n gazetteerEntries = [],\n context,\n compressed = false,\n}: NativePipelinePackageOptions): Promise<Uint8Array> => {\n const scopedConfig = applyPipelineLanguageScope(config);\n assertNativePipelineSupported(scopedConfig);\n const ctx = context ?? defaultContext;\n const key = nativePackageCacheKey({\n binding,\n config: scopedConfig,\n gazetteerEntries,\n compressed,\n });\n if (ctx.nativePipelinePackage && ctx.nativePipelinePackageKey === key) {\n return ctx.nativePipelinePackage;\n }\n if (\n ctx.nativePipelinePackagePromise &&\n ctx.nativePipelinePackageKey === key\n ) {\n return ctx.nativePipelinePackagePromise;\n }\n\n const sharedCache = sharedPackageCacheFor(scopedConfig.dictionaries);\n const shared = sharedCache.get(key);\n if (shared !== undefined) {\n touchSharedPackageCacheEntry(sharedCache, key, shared);\n const packageBytes = await shared;\n ctx.nativePipelinePackage = packageBytes;\n ctx.nativePipelinePackageKey = key;\n ctx.nativePipelinePackagePromise = null;\n return packageBytes;\n }\n\n ctx.nativePipelinePackage = null;\n ctx.nativePipelinePackageKey = key;\n const promise = buildNativePipelinePackage({\n binding,\n config: scopedConfig,\n gazetteerEntries,\n compressed,\n });\n ctx.nativePipelinePackagePromise = promise;\n touchSharedPackageCacheEntry(sharedCache, key, promise);\n let packageBytes: Uint8Array;\n try {\n packageBytes = await promise;\n } catch (error) {\n if (sharedCache.get(key) === promise) {\n sharedCache.delete(key);\n }\n if (\n ctx.nativePipelinePackageKey === key &&\n ctx.nativePipelinePackagePromise === promise\n ) {\n ctx.nativePipelinePackage = null;\n ctx.nativePipelinePackagePromise = null;\n }\n throw error;\n }\n if (sharedCache.get(key) === promise) {\n sharedCache.set(key, packageBytes);\n }\n if (ctx.nativePipelinePackageKey === key) {\n ctx.nativePipelinePackage = packageBytes;\n ctx.nativePipelinePackagePromise = null;\n }\n return packageBytes;\n};\n\n// `async` so the shared package cache can store the in-flight value and dedupe\n// concurrent builds for the same key, and so assembly failures (an older\n// binding without the assemble functions, or a config the assembler rejects)\n// surface as a rejected promise rather than a synchronous throw mid-cache-flow.\nconst buildNativePipelinePackage = async ({\n binding,\n config,\n gazetteerEntries,\n compressed,\n}: Required<\n Omit<NativePipelinePackageOptions, \"context\">\n>): Promise<Uint8Array> =>\n assemblePackageBytes(\n binding,\n toAssembleInputs(config, gazetteerEntries),\n compressed,\n );\n\ntype NativePackageCacheKeyOptions = {\n binding: NativeAnonymizeBinding;\n config: PipelineConfig;\n gazetteerEntries: readonly GazetteerEntry[];\n compressed: boolean;\n};\n\nconst nativePackageCacheKey = ({\n binding,\n config,\n gazetteerEntries,\n compressed,\n}: NativePackageCacheKeyOptions): string =>\n [\n binding.nativePackageVersion(),\n compressed ? \"compressed\" : \"raw\",\n dictionaryCacheKey(config.dictionaries),\n pipelineConfigKey(config, gazetteerEntries),\n ].join(\":\");\n","import { DEFAULT_ENTITY_LABELS } from \"./constants\";\nimport type { PipelineConfig } from \"./types\";\n\nexport const DEFAULT_NATIVE_PIPELINE_CONFIG: PipelineConfig = {\n threshold: 0.3,\n enableTriggerPhrases: true,\n enableRegex: true,\n enableLegalForms: true,\n enableNameCorpus: true,\n enableDenyList: true,\n enableGazetteer: false,\n enableCountries: true,\n enableConfidenceBoost: true,\n enableCoreference: true,\n enableHotwordRules: true,\n enableZoneClassification: true,\n labels: [...DEFAULT_ENTITY_LABELS],\n workspaceId: \"native-pipeline-default\",\n};\n","import { createRequire } from \"node:module\";\nimport { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport process from \"node:process\";\n\nimport {\n assertNativeBindingVersion,\n createNativePipelineFromPackage,\n type NativeOperatorConfig,\n type NativeAnonymizeBinding,\n type NativeNormalizeOptions,\n type NativeSearchPackageInput,\n PreparedNativeAnonymizer,\n PreparedNativePipeline,\n type NativeStaticRedactionResult,\n diagnostics_json as diagnosticsJsonWithBinding,\n diagnostics_stream_json as diagnosticsStreamJsonWithBinding,\n load_prepared_package as loadPreparedPackageWithBinding,\n native_package_version as nativePackageVersionWithBinding,\n normalize_for_search as normalizeForSearchWithBinding,\n prepare_search_package as prepareSearchPackageWithBinding,\n redact_text as redactTextWithBinding,\n redact_text_json as redactTextJsonWithBinding,\n redact_text_stream_json as redactTextStreamJsonWithBinding,\n summary_diagnostics_json as summaryDiagnosticsJsonWithBinding,\n} from \"./native\";\n\nexport * from \"./native\";\nexport {\n assertNativePipelineSupported,\n createNativePipelineFromConfig,\n getNativePipelineCompatibility,\n prepareNativePipelineConfig,\n prepareNativePipelinePackage,\n} from \"./native-pipeline\";\nexport type {\n NativePipelineBuildOptions,\n NativePipelineCompatibility,\n NativePipelinePackageOptions,\n NativePipelineUnsupportedFeature,\n} from \"./native-pipeline\";\n\nexport type NativeRequire = (specifier: string) => unknown;\n\nexport type NativeLibc = \"gnu\" | \"musl\";\n\nexport type LoadNativeBindingOptions = {\n expectedVersion?: string;\n platform?: string;\n arch?: string;\n libc?: NativeLibc;\n env?: Record<string, string | undefined>;\n requireModule?: NativeRequire;\n};\n\nexport type NativePipelinePackageFileOptions = LoadNativeBindingOptions & {\n binding?: NativeAnonymizeBinding;\n packagePath: string;\n};\n\nexport type NativeSdkOptions = LoadNativeBindingOptions & {\n binding?: NativeAnonymizeBinding;\n};\n\nexport type NativeSdkPackageOptions = NativeSdkOptions & {\n compressed?: boolean;\n};\n\nexport type DefaultNativePipelinePackageOptions = LoadNativeBindingOptions & {\n binding?: NativeAnonymizeBinding;\n language?: string;\n packagePath?: string;\n warmup?: DefaultNativePipelineWarmup;\n};\n\ntype ResolvedDefaultNativePipelineOptions = {\n binding: NativeAnonymizeBinding;\n language?: string;\n packagePath?: string;\n warmup: DefaultNativePipelineWarmup;\n};\n\nexport const DEFAULT_NATIVE_PIPELINE_WARMUPS = {\n lazyRegex: \"lazy-regex\",\n none: \"none\",\n} as const;\n\nexport type DefaultNativePipelineWarmup =\n (typeof DEFAULT_NATIVE_PIPELINE_WARMUPS)[keyof typeof DEFAULT_NATIVE_PIPELINE_WARMUPS];\n\nexport type DefaultNativePipelinePackageFileOptions = {\n language?: string;\n};\n\nconst LOCAL_NATIVE_LOADER = \"../index.cjs\";\nconst PACKAGE_SPECIFIC_NATIVE_PATH = \"STELLA_ANONYMIZE_NATIVE_LIBRARY_PATH\";\nconst DEFAULT_NATIVE_PIPELINE_PACKAGE_URL = new URL(\n \"../native-pipeline.stlanonpkg\",\n import.meta.url,\n);\nconst DEFAULT_NATIVE_PIPELINE_PACKAGE_DIR_URL = new URL(\"../\", import.meta.url);\nconst DEFAULT_NATIVE_PIPELINE_LANGUAGE_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;\nconst DEFAULT_NATIVE_PIPELINE_LANGUAGE_PACKAGE_PATTERN =\n /^native-pipeline\\.([a-z0-9]+(?:-[a-z0-9]+)*)\\.stlanonpkg$/u;\nconst DEFAULT_NATIVE_PIPELINE_PACKAGE_CACHE_KEY = \"<default>\";\nconst defaultNativePipelineCache = new WeakMap<\n NativeAnonymizeBinding,\n Map<string, PreparedNativePipeline>\n>();\nconst warmedDefaultNativePipelines = new WeakSet<PreparedNativePipeline>();\nconst defaultNativePipelineInflightCache = new WeakMap<\n NativeAnonymizeBinding,\n Map<string, Promise<PreparedNativePipeline>>\n>();\n\nexport { DEFAULT_NATIVE_PIPELINE_CONFIG } from \"./native-default-config\";\n\nexport const loadNativeAnonymizeBinding = (\n options: LoadNativeBindingOptions = {},\n): NativeAnonymizeBinding => {\n const requireModule = options.requireModule ?? createRequire(import.meta.url);\n const platform = options.platform ?? process.platform;\n const arch = options.arch ?? process.arch;\n const libc = options.libc ?? detectNativeLibc(platform);\n const env = options.env ?? process.env;\n const specifiers = nativeBindingSpecifiers({ arch, env, libc, platform });\n const errors: string[] = [];\n\n for (const specifier of specifiers) {\n const binding = tryLoadNativeBinding({\n specifier,\n requireModule,\n errors,\n });\n if (!binding) {\n continue;\n }\n if (options.expectedVersion !== undefined) {\n assertNativeBindingVersion({\n binding,\n expectedVersion: options.expectedVersion,\n });\n }\n return binding;\n }\n\n if (nativeBindingPackageName({ arch, libc, platform }) === null) {\n throw unsupportedNativeTargetError({ arch, errors, libc, platform });\n }\n throw new Error(\n `Unable to load native anonymize binding for ${platform}/${arch}:\\n${errors.join(\"\\n\")}`,\n );\n};\n\nexport const readNativePipelinePackageFile = (\n packagePath: string,\n): Uint8Array => readFileSync(packagePath);\n\nexport const readNativePipelinePackageFileAsync = async (\n packagePath: string,\n): Promise<Uint8Array> => readFile(packagePath);\n\nexport const native_package_version = (\n options: NativeSdkOptions = {},\n): string => nativePackageVersionWithBinding(resolveNativeSdkBinding(options));\n\nexport const normalize_for_search = (\n text: string,\n options: NativeSdkOptions = {},\n): string => {\n const args: NativeNormalizeOptions = {\n binding: resolveNativeSdkBinding(options),\n text,\n };\n return normalizeForSearchWithBinding(args);\n};\n\nexport const prepare_search_package = (\n config: NativeSearchPackageInput,\n { compressed = false, ...options }: NativeSdkPackageOptions = {},\n): Uint8Array =>\n prepareSearchPackageWithBinding({\n binding: resolveNativeSdkBinding(options),\n config,\n compressed,\n });\n\nexport const load_prepared_package = (\n packageBytes: Uint8Array,\n options: NativeSdkOptions = {},\n) =>\n loadPreparedPackageWithBinding({\n binding: resolveNativeSdkBinding(options),\n packageBytes,\n });\n\nexport const load_prepared_package_file = (\n packagePath: string,\n options: NativeSdkOptions = {},\n) => load_prepared_package(readNativePipelinePackageFile(packagePath), options);\n\nexport const redact_text = (\n config: NativeSearchPackageInput,\n fullText: string,\n operators?: NativeOperatorConfig,\n options: NativeSdkOptions = {},\n): NativeStaticRedactionResult =>\n redactTextWithBinding({\n binding: resolveNativeSdkBinding(options),\n config,\n fullText,\n ...(operators !== undefined ? { operators } : {}),\n });\n\nexport const redact_text_json = (\n config: NativeSearchPackageInput,\n fullText: string,\n operators?: NativeOperatorConfig,\n options: NativeSdkOptions = {},\n): string =>\n redactTextJsonWithBinding({\n binding: resolveNativeSdkBinding(options),\n config,\n fullText,\n ...(operators !== undefined ? { operators } : {}),\n });\n\nexport const redact_text_stream_json = (\n config: NativeSearchPackageInput,\n fullText: string,\n onEvent: (eventJson: string) => void,\n operators?: NativeOperatorConfig,\n options: NativeSdkOptions = {},\n): string | null =>\n redactTextStreamJsonWithBinding({\n binding: resolveNativeSdkBinding(options),\n config,\n fullText,\n onEvent,\n ...(operators !== undefined ? { operators } : {}),\n });\n\nexport const diagnostics_json = (\n config: NativeSearchPackageInput,\n fullText: string,\n operators?: NativeOperatorConfig,\n options: NativeSdkOptions = {},\n): string | null =>\n diagnosticsJsonWithBinding({\n binding: resolveNativeSdkBinding(options),\n config,\n fullText,\n ...(operators !== undefined ? { operators } : {}),\n });\n\nexport const diagnostics_stream_json = (\n config: NativeSearchPackageInput,\n fullText: string,\n onBatch: (diagnosticsJson: string) => void,\n operators?: NativeOperatorConfig,\n options: NativeSdkOptions = {},\n): string | null =>\n diagnosticsStreamJsonWithBinding({\n binding: resolveNativeSdkBinding(options),\n config,\n fullText,\n onBatch,\n ...(operators !== undefined ? { operators } : {}),\n });\n\nexport const summary_diagnostics_json = (\n config: NativeSearchPackageInput,\n fullText: string,\n operators?: NativeOperatorConfig,\n options: NativeSdkOptions = {},\n): string | null =>\n summaryDiagnosticsJsonWithBinding({\n binding: resolveNativeSdkBinding(options),\n config,\n fullText,\n ...(operators !== undefined ? { operators } : {}),\n });\n\nexport const readDefaultNativePipelinePackageFile = ({\n language,\n}: DefaultNativePipelinePackageFileOptions = {}): Uint8Array => {\n const packageUrl = defaultNativePipelinePackageUrl(language);\n try {\n return readFileSync(packageUrl);\n } catch (error) {\n throw new Error(\n `${defaultNativePipelinePackageDescription(language)} is unavailable: ${formatLoadError(error)}`,\n );\n }\n};\n\nexport const read_default_native_pipeline_package_file = (\n options: DefaultNativePipelinePackageFileOptions = {},\n): Uint8Array => readDefaultNativePipelinePackageFile(options);\n\nexport const availableDefaultNativePipelineLanguages = (): string[] => {\n const languages = new Set<string>();\n try {\n for (const fileName of readdirSync(\n DEFAULT_NATIVE_PIPELINE_PACKAGE_DIR_URL,\n )) {\n const match = fileName.match(\n DEFAULT_NATIVE_PIPELINE_LANGUAGE_PACKAGE_PATTERN,\n );\n if (match?.[1] !== undefined) {\n languages.add(match[1]);\n }\n }\n } catch (error) {\n throw new Error(\n `Default native pipeline package directory is unavailable: ${formatLoadError(error)}`,\n );\n }\n return [...languages].toSorted();\n};\n\nexport const available_default_native_pipeline_languages =\n availableDefaultNativePipelineLanguages;\n\nexport const readDefaultNativePipelinePackageFileAsync = async ({\n language,\n}: DefaultNativePipelinePackageFileOptions = {}): Promise<Uint8Array> => {\n const packageUrl = defaultNativePipelinePackageUrl(language);\n try {\n return await readFile(packageUrl);\n } catch (error) {\n throw new Error(\n `${defaultNativePipelinePackageDescription(language)} is unavailable: ${formatLoadError(error)}`,\n );\n }\n};\n\nexport const createNativePipelineFromPackageFile = ({\n binding,\n packagePath,\n expectedVersion,\n ...loadOptions\n}: NativePipelinePackageFileOptions): PreparedNativePipeline => {\n const resolvedBinding =\n binding ??\n loadNativeAnonymizeBinding({\n ...loadOptions,\n ...(expectedVersion !== undefined ? { expectedVersion } : {}),\n });\n if (binding && expectedVersion !== undefined) {\n assertNativeBindingVersion({ binding, expectedVersion });\n }\n return createNativePipelineFromPackage({\n binding: resolvedBinding,\n packageBytes: readNativePipelinePackageFile(packagePath),\n });\n};\n\nexport const createNativePipelineFromDefaultPackage = (\n options: DefaultNativePipelinePackageOptions = {},\n): PreparedNativePipeline => {\n const resolvedOptions = resolveDefaultNativePipelineOptions(options);\n return applyDefaultNativePipelineWarmup(\n createNativePipelineFromResolvedDefaultPackage(resolvedOptions),\n resolvedOptions.warmup,\n );\n};\n\nexport const create_native_pipeline_from_default_package = (\n options: DefaultNativePipelinePackageOptions = {},\n): PreparedNativePipeline => createNativePipelineFromDefaultPackage(options);\n\nexport const getDefaultNativePipeline = (\n options: DefaultNativePipelinePackageOptions = {},\n): PreparedNativePipeline => {\n const resolvedOptions = resolveDefaultNativePipelineOptions(options);\n const cache = defaultPipelineCacheFor(resolvedOptions.binding);\n const key = defaultPipelineCacheKey(resolvedOptions);\n const cached = cache.get(key);\n if (cached !== undefined) {\n return applyDefaultNativePipelineWarmup(cached, resolvedOptions.warmup);\n }\n const pipeline =\n createNativePipelineFromResolvedDefaultPackage(resolvedOptions);\n cache.set(key, pipeline);\n return applyDefaultNativePipelineWarmup(pipeline, resolvedOptions.warmup);\n};\n\nexport const get_default_native_pipeline = (\n options: DefaultNativePipelinePackageOptions = {},\n): PreparedNativePipeline => getDefaultNativePipeline(options);\n\nexport const preloadDefaultNativePipeline = (\n options: DefaultNativePipelinePackageOptions = {},\n): PreparedNativePipeline => {\n const pipeline = getDefaultNativePipeline(options);\n return applyDefaultNativePipelineWarmup(\n pipeline,\n DEFAULT_NATIVE_PIPELINE_WARMUPS.lazyRegex,\n );\n};\n\nexport const preload_default_native_pipeline = (\n options: DefaultNativePipelinePackageOptions = {},\n): PreparedNativePipeline => preloadDefaultNativePipeline(options);\n\nexport const redactDefaultText = (\n fullText: string,\n operators?: NativeOperatorConfig,\n options: DefaultNativePipelinePackageOptions = {},\n): NativeStaticRedactionResult =>\n getDefaultNativePipeline(options).redactText(fullText, operators);\n\nexport const redact_default_text = (\n fullText: string,\n operators?: NativeOperatorConfig,\n options: DefaultNativePipelinePackageOptions = {},\n): NativeStaticRedactionResult =>\n redactDefaultText(fullText, operators, options);\n\nexport const redactDefaultTextJson = (\n fullText: string,\n operators?: NativeOperatorConfig,\n options: DefaultNativePipelinePackageOptions = {},\n): string =>\n getDefaultNativePipeline(options).redact_text_json(fullText, operators);\n\nexport const redact_default_text_json = (\n fullText: string,\n operators?: NativeOperatorConfig,\n options: DefaultNativePipelinePackageOptions = {},\n): string => redactDefaultTextJson(fullText, operators, options);\n\nexport const preloadDefaultNativePipelineAsync = (\n options: DefaultNativePipelinePackageOptions = {},\n): Promise<PreparedNativePipeline> => {\n const resolvedOptions = {\n ...resolveDefaultNativePipelineOptions(options),\n warmup: DEFAULT_NATIVE_PIPELINE_WARMUPS.lazyRegex,\n };\n const cache = defaultPipelineCacheFor(resolvedOptions.binding);\n const key = defaultPipelineCacheKey(resolvedOptions);\n const cached = cache.get(key);\n if (cached !== undefined) {\n return Promise.resolve(\n applyDefaultNativePipelineWarmup(cached, resolvedOptions.warmup),\n );\n }\n\n const inflightCache = defaultPipelineInflightCacheFor(\n resolvedOptions.binding,\n );\n const inflight = inflightCache.get(key);\n if (inflight !== undefined) {\n return inflight;\n }\n\n const promise = createNativePipelineFromResolvedDefaultPackageAsync(\n resolvedOptions,\n )\n .then((pipeline) => {\n cache.set(key, pipeline);\n return applyDefaultNativePipelineWarmup(pipeline, resolvedOptions.warmup);\n })\n .finally(() => {\n inflightCache.delete(key);\n });\n inflightCache.set(key, promise);\n return promise;\n};\n\nconst resolveDefaultNativePipelineOptions = ({\n binding,\n language,\n packagePath,\n warmup,\n expectedVersion,\n ...loadOptions\n}: DefaultNativePipelinePackageOptions = {}): ResolvedDefaultNativePipelineOptions => {\n if (language !== undefined && packagePath !== undefined) {\n throw new Error(\"Use either language or packagePath, not both\");\n }\n const resolvedBinding =\n binding ??\n loadNativeAnonymizeBinding({\n ...loadOptions,\n ...(expectedVersion !== undefined ? { expectedVersion } : {}),\n });\n if (binding && expectedVersion !== undefined) {\n assertNativeBindingVersion({ binding, expectedVersion });\n }\n return {\n binding: resolvedBinding,\n warmup: normalizeDefaultNativePipelineWarmup(warmup),\n ...(language !== undefined\n ? { language: resolveDefaultNativePipelineLanguage(language) }\n : {}),\n ...(packagePath !== undefined ? { packagePath } : {}),\n };\n};\n\nconst applyDefaultNativePipelineWarmup = (\n pipeline: PreparedNativePipeline,\n warmup: DefaultNativePipelineWarmup,\n): PreparedNativePipeline => {\n if (warmup !== DEFAULT_NATIVE_PIPELINE_WARMUPS.lazyRegex) {\n return pipeline;\n }\n if (!warmedDefaultNativePipelines.has(pipeline)) {\n pipeline.warmLazyRegex();\n warmedDefaultNativePipelines.add(pipeline);\n }\n return pipeline;\n};\n\nconst createNativePipelineFromResolvedDefaultPackage = ({\n binding,\n language,\n packagePath,\n}: ResolvedDefaultNativePipelineOptions): PreparedNativePipeline => {\n const packageBytes =\n packagePath === undefined\n ? readDefaultNativePipelinePackageFile(\n defaultPackageFileOptions(language),\n )\n : readNativePipelinePackageFile(packagePath);\n return createNativePipelineFromTrustedDefaultPackage(binding, packageBytes);\n};\n\nconst createNativePipelineFromResolvedDefaultPackageAsync = async ({\n binding,\n language,\n packagePath,\n}: ResolvedDefaultNativePipelineOptions): Promise<PreparedNativePipeline> => {\n const packageBytes =\n packagePath === undefined\n ? await readDefaultNativePipelinePackageFileAsync(\n defaultPackageFileOptions(language),\n )\n : await readNativePipelinePackageFileAsync(packagePath);\n return createNativePipelineFromTrustedDefaultPackage(binding, packageBytes);\n};\n\nconst createNativePipelineFromTrustedDefaultPackage = (\n binding: NativeAnonymizeBinding,\n packageBytes: Uint8Array,\n): PreparedNativePipeline =>\n new PreparedNativePipeline(\n new PreparedNativeAnonymizer(\n binding.NativePreparedSearch.fromTrustedPreparedPackageBytesWithoutCache?.(\n packageBytes,\n ) ??\n binding.NativePreparedSearch.fromTrustedPreparedPackageBytes?.(\n packageBytes,\n ) ??\n binding.NativePreparedSearch.fromPreparedPackageBytesWithoutCache?.(\n packageBytes,\n ) ??\n binding.NativePreparedSearch.fromPreparedPackageBytes(packageBytes),\n ),\n );\n\nconst defaultPackageFileOptions = (\n language: string | undefined,\n): DefaultNativePipelinePackageFileOptions =>\n language === undefined ? {} : { language };\n\nconst normalizeDefaultNativePipelineWarmup = (\n warmup: DefaultNativePipelineWarmup | undefined,\n): DefaultNativePipelineWarmup => {\n if (warmup === undefined) {\n return DEFAULT_NATIVE_PIPELINE_WARMUPS.none;\n }\n switch (warmup) {\n case DEFAULT_NATIVE_PIPELINE_WARMUPS.lazyRegex:\n case DEFAULT_NATIVE_PIPELINE_WARMUPS.none:\n return warmup;\n }\n throw new Error(\n 'Default native pipeline warmup must be \"lazy-regex\" or \"none\"',\n );\n};\n\nconst resolveNativeSdkBinding = ({\n binding,\n expectedVersion,\n ...loadOptions\n}: NativeSdkOptions): NativeAnonymizeBinding => {\n const resolvedBinding =\n binding ??\n loadNativeAnonymizeBinding({\n ...loadOptions,\n ...(expectedVersion !== undefined ? { expectedVersion } : {}),\n });\n if (binding && expectedVersion !== undefined) {\n assertNativeBindingVersion({ binding, expectedVersion });\n }\n return resolvedBinding;\n};\n\nconst defaultPipelineCacheFor = (\n binding: NativeAnonymizeBinding,\n): Map<string, PreparedNativePipeline> => {\n const cached = defaultNativePipelineCache.get(binding);\n if (cached !== undefined) {\n return cached;\n }\n const created = new Map<string, PreparedNativePipeline>();\n defaultNativePipelineCache.set(binding, created);\n return created;\n};\n\nconst defaultPipelineInflightCacheFor = (\n binding: NativeAnonymizeBinding,\n): Map<string, Promise<PreparedNativePipeline>> => {\n const cached = defaultNativePipelineInflightCache.get(binding);\n if (cached !== undefined) {\n return cached;\n }\n const created = new Map<string, Promise<PreparedNativePipeline>>();\n defaultNativePipelineInflightCache.set(binding, created);\n return created;\n};\n\nconst defaultPipelineCacheKey = ({\n binding,\n language,\n packagePath,\n}: ResolvedDefaultNativePipelineOptions): string =>\n [\n binding.nativePackageVersion(),\n packagePath ??\n (language === undefined\n ? DEFAULT_NATIVE_PIPELINE_PACKAGE_CACHE_KEY\n : `language:${language}`),\n ].join(\"\\0\");\n\nconst defaultNativePipelinePackageUrl = (language: string | undefined): URL => {\n if (language === undefined) {\n return DEFAULT_NATIVE_PIPELINE_PACKAGE_URL;\n }\n const normalized = resolveDefaultNativePipelineLanguage(language);\n return defaultNativePipelineLanguagePackageUrl(normalized);\n};\n\nconst defaultNativePipelineLanguagePackageUrl = (language: string): URL =>\n new URL(`../native-pipeline.${language}.stlanonpkg`, import.meta.url);\n\nconst resolveDefaultNativePipelineLanguage = (language: string): string => {\n const normalized = normalizeDefaultNativePipelineLanguage(language);\n const exactUrl = defaultNativePipelineLanguagePackageUrl(normalized);\n if (existsSync(exactUrl)) {\n return normalized;\n }\n const baseLanguage = normalized.split(\"-\").at(0);\n if (baseLanguage === undefined || baseLanguage === normalized) {\n return normalized;\n }\n const baseUrl = defaultNativePipelineLanguagePackageUrl(baseLanguage);\n if (existsSync(baseUrl)) {\n return baseLanguage;\n }\n return normalized;\n};\n\nconst defaultNativePipelinePackageDescription = (\n language: string | undefined,\n): string =>\n language === undefined\n ? \"Default native pipeline package\"\n : `Default native pipeline package for language \"${resolveDefaultNativePipelineLanguage(language)}\"`;\n\nconst normalizeDefaultNativePipelineLanguage = (language: string): string => {\n const normalized = language.trim().toLowerCase();\n if (!DEFAULT_NATIVE_PIPELINE_LANGUAGE_PATTERN.test(normalized)) {\n throw new Error(\n `Default native pipeline language must match ${DEFAULT_NATIVE_PIPELINE_LANGUAGE_PATTERN.source}`,\n );\n }\n return normalized;\n};\n\ntype NativeBindingSpecifiersOptions = {\n arch: string;\n env: Record<string, string | undefined>;\n libc: NativeLibc | undefined;\n platform: string;\n};\n\nconst nativeBindingSpecifiers = ({\n arch,\n env,\n libc,\n platform,\n}: NativeBindingSpecifiersOptions): string[] => {\n const specifiers: string[] = [];\n const overridePath = env[PACKAGE_SPECIFIC_NATIVE_PATH];\n if (overridePath) {\n specifiers.push(overridePath);\n }\n specifiers.push(LOCAL_NATIVE_LOADER);\n const platformPackage = nativeBindingPackageName({ arch, libc, platform });\n if (platformPackage !== null) {\n specifiers.push(platformPackage);\n }\n return specifiers;\n};\n\ntype NativeBindingTarget = {\n platform: string;\n arch: string;\n libc?: NativeLibc;\n package: string;\n};\n\n// Single source of truth for published native sidecars. Both the runtime\n// package lookup and the \"unsupported target\" error message derive from this\n// table, so a target is never advertised as supported without a package (and\n// vice versa). musl Linux is intentionally absent: no musl sidecar is shipped.\nconst NATIVE_BINDING_TARGETS: readonly NativeBindingTarget[] = [\n {\n platform: \"darwin\",\n arch: \"arm64\",\n package: \"@stll/anonymize-darwin-arm64\",\n },\n { platform: \"darwin\", arch: \"x64\", package: \"@stll/anonymize-darwin-x64\" },\n {\n platform: \"linux\",\n arch: \"arm64\",\n libc: \"gnu\",\n package: \"@stll/anonymize-linux-arm64-gnu\",\n },\n {\n platform: \"linux\",\n arch: \"x64\",\n libc: \"gnu\",\n package: \"@stll/anonymize-linux-x64-gnu\",\n },\n { platform: \"win32\", arch: \"x64\", package: \"@stll/anonymize-win32-x64-msvc\" },\n];\n\ntype NativeBindingPackageNameOptions = {\n arch: string;\n libc: NativeLibc | undefined;\n platform: string;\n};\n\ntype DescribeNativeTargetOptions = {\n arch: string;\n libc?: NativeLibc | undefined;\n platform: string;\n};\n\nconst describeNativeTarget = ({\n arch,\n libc,\n platform,\n}: DescribeNativeTargetOptions): string =>\n libc === undefined ? `${platform}-${arch}` : `${platform}-${arch}-${libc}`;\n\nconst SUPPORTED_NATIVE_TARGETS: readonly string[] = NATIVE_BINDING_TARGETS.map(\n (target) => describeNativeTarget(target),\n);\n\nconst nativeBindingPackageName = ({\n arch,\n libc,\n platform,\n}: NativeBindingPackageNameOptions): string | null => {\n const match = NATIVE_BINDING_TARGETS.find(\n (target) =>\n target.platform === platform &&\n target.arch === arch &&\n (target.libc === undefined || target.libc === libc),\n );\n return match?.package ?? null;\n};\n\nconst unsupportedNativeTargetError = ({\n arch,\n errors,\n libc,\n platform,\n}: NativeBindingPackageNameOptions & { errors: string[] }): Error => {\n const target = describeNativeTarget({ arch, libc, platform });\n const supported = SUPPORTED_NATIVE_TARGETS.join(\", \");\n const attempts = errors.length > 0 ? `\\n${errors.join(\"\\n\")}` : \"\";\n return new Error(\n `No native anonymize binding is published for ${target}; supported targets: ${supported}. Set ${PACKAGE_SPECIFIC_NATIVE_PATH} to a locally built binding to run on this platform.${attempts}`,\n );\n};\n\nconst detectNativeLibc = (platform: string): NativeLibc | undefined => {\n if (platform !== \"linux\") {\n return undefined;\n }\n const report = process.report?.getReport();\n const header =\n isPropertyBag(report) && isPropertyBag(report[\"header\"])\n ? report[\"header\"]\n : null;\n return typeof header?.[\"glibcVersionRuntime\"] === \"string\" ? \"gnu\" : \"musl\";\n};\n\ntype TryLoadNativeBindingOptions = {\n specifier: string;\n requireModule: NativeRequire;\n errors: string[];\n};\n\nconst tryLoadNativeBinding = ({\n specifier,\n requireModule,\n errors,\n}: TryLoadNativeBindingOptions): NativeAnonymizeBinding | null => {\n try {\n const loaded = requireModule(specifier);\n const binding = toNativeAnonymizeBinding(loaded);\n if (binding) {\n return binding;\n }\n errors.push(`${specifier}: module does not match native binding shape`);\n } catch (error) {\n errors.push(`${specifier}: ${formatLoadError(error)}`);\n }\n return null;\n};\n\nconst toNativeAnonymizeBinding = (\n value: unknown,\n): NativeAnonymizeBinding | null => {\n const candidate =\n isPropertyBag(value) && isPropertyBag(value[\"default\"])\n ? value[\"default\"]\n : value;\n return isNativeAnonymizeBinding(candidate) ? candidate : null;\n};\n\nconst isNativeAnonymizeBinding = (\n candidate: unknown,\n): candidate is NativeAnonymizeBinding => {\n if (!isPropertyBag(candidate)) {\n return false;\n }\n if (typeof candidate[\"nativePackageVersion\"] !== \"function\") {\n return false;\n }\n if (typeof candidate[\"normalizeForSearch\"] !== \"function\") {\n return false;\n }\n if (typeof candidate[\"prepareStaticSearchPackageBytes\"] !== \"function\") {\n return false;\n }\n if (\n typeof candidate[\"prepareStaticSearchCompressedPackageBytes\"] !== \"function\"\n ) {\n return false;\n }\n const preparedSearch = candidate[\"NativePreparedSearch\"];\n if (!isPropertyBag(preparedSearch)) {\n return false;\n }\n if (typeof preparedSearch[\"fromConfigJsonBytes\"] !== \"function\") {\n return false;\n }\n if (typeof preparedSearch[\"fromPreparedPackageBytes\"] !== \"function\") {\n return false;\n }\n return true;\n};\n\nconst isPropertyBag = (value: unknown): value is Record<string, unknown> =>\n (typeof value === \"object\" && value !== null) || typeof value === \"function\";\n\nconst formatLoadError = (error: unknown): string => {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n};\n"],"mappings":";;;;;;;;AAeA,MAAa,+BAAgD;CAC3D,uBAAuB;CACvB,0BAA0B;CAC1B,8BAA8B;AAChC;;;;;;AAOA,MAAa,iBAAkC,sBAAsB;;;AEbrE,MAAM,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAAA;AAElB,MAAM,qBAAqB,aACzB,SAAS,KAAK,CAAC,CAAC,YAAY;AAE9B,MAAM,oBAAoB,aAAoC;CAC5D,MAAM,QAAQ,SAAS,QAAQ,GAAG;CAClC,OAAO,UAAU,KAAK,OAAO,SAAS,MAAM,GAAG,KAAK;AACtD;AAEA,MAAM,cAAc,QAAkB,WAAoC;CACxE,MAAM,OAAO,IAAI,IAAI,MAAM;CAC3B,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,KAAK,IAAI,KAAK,GAChB;EAEF,KAAK,IAAI,KAAK;EACd,OAAO,KAAK,KAAK;CACnB;AACF;AAEA,MAAM,wBAAwB,aAA2C;CACvE,MAAM,aAAa,kBAAkB,QAAQ;CAC7C,IAAI,WAAW,WAAW,GACxB,OAAO;CAET,MAAM,QAAQ,UAAU,UAAU;CAClC,IAAI,UAAU,KAAA,GACZ,OAAO;CAET,MAAM,WAAW,iBAAiB,UAAU;CAC5C,OAAO,aAAa,OAAO,OAAQ,UAAU,UAAU,aAAa;AACtE;AAEA,MAAM,uBAAuB,WAA8C;CACzE,IAAI,OAAO,cAAc,KAAA,GACvB,OAAO,OAAO;CAEhB,OAAO,OAAO,aAAa,KAAA,IAAY,CAAC,IAAI,CAAC,OAAO,QAAQ;AAC9D;AAWA,MAAa,8BACX,WACmB;CACnB,MAAM,YAAY,oBAAoB,MAAM;CAC5C,IAAI,UAAU,WAAW,GACvB,OAAO;CAGT,MAAM,sBAAgC,CAAC;CACvC,MAAM,oBAA8B,CAAC;CACrC,KAAK,MAAM,YAAY,WAAW;EAChC,MAAM,QAAQ,qBAAqB,QAAQ;EAC3C,IAAI,UAAU,MACZ;EAEF,WAAW,qBAAqB,MAAM,uBAAuB,CAAC,CAAC;EAC/D,WAAW,mBAAmB,MAAM,qBAAqB,CAAC,CAAC;CAC7D;CAEA,MAAM,OAAgC,CAAC;CACvC,IACE,OAAO,wBAAwB,KAAA,KAC/B,oBAAoB,SAAS,GAE7B,KAAK,sBAAsB;CAE7B,IAAI,OAAO,sBAAsB,KAAA,KAAa,kBAAkB,SAAS,GACvE,KAAK,oBAAoB;CAG3B,OAAO,OAAO,KAAK,IAAI,CAAC,CAAC,WAAW,IAAI,SAAS;EAAE,GAAG;EAAQ,GAAG;CAAK;AACxE;;;ACgXA,MAAa,uBACX,WACY,OAAO,qBAAqB;;;AChd1C,MAAM,yBAAyB,aAC7B,SAAS,KAAK,CAAC,CAAC,YAAY;AAE9B,MAAM,8BACJ,cAEA,cAAc,KAAA,IACV,CAAC,IACD,UACG,IAAI,qBAAqB,CAAC,CAC1B,QAAQ,aAAa,SAAS,SAAS,CAAC;AAEjD,MAAa,wBACX,cACW;CACX,MAAM,aAAa,2BAA2B,SAAS,CAAC,CAAC,SAAS;CAClE,OAAO,WAAW,WAAW,IAAI,MAAM,WAAW,KAAK,GAAG;AAC5D;;;ACVA,MAAM,6BAA6B;AAEnC,MAAM,8BACJ,WACW;CAIX,OAAO,qBAFL,OAAO,cACN,OAAO,aAAa,KAAA,IAAY,CAAC,IAAI,CAAC,OAAO,QAAQ,EACnB;AACvC;AAEA,MAAa,qBACX,QACA,qBACW;CACX,MAAM,oBAAoB,oBAAoB,MAAM;CACpD,MAAM,wBACJ,OAAO,kBAAkB,OAAO,iBAC5B,OAAO,eACJ,KAAK,UACJ,KAAK,UAAU;EACb,OAAO,MAAM;EACb,OAAO,MAAM;EACb,UAAU,CAAC,GAAI,MAAM,YAAY,CAAC,CAAE,CAAC,CAAC,KAAK;CAC7C,CAAC,CACH,CAAC,CACA,KAAK,CAAC,CACN,KAAK,IAAI,IACZ;CACN,MAAM,yBACJ,OAAO,eAAe,OAAO,gBACzB,OAAO,cACJ,KAAK,UACJ,KAAK,UAAU;EACb,OAAO,MAAM;EACb,SAAS,MAAM;EACf,wBAAwB,MAAM,0BAA0B;EACxD,OAAO,MAAM,SAAS;CACxB,CAAC,CACH,CAAC,CACA,KAAK,CAAC,CACN,KAAK,IAAI,IACZ;CACN,MAAM,iBACJ,OAAO,mBAAmB,iBAAiB,SAAS,IAChD,iBACG,KACE,UACC,GAAG,MAAM,GAAG,GAAG,MAAM,UAAU,GAAG,MAAM,MAAM,GAAG,CAC/C,GAAG,MAAM,QACX,CAAC,CACE,KAAK,CAAC,CACN,KAAK,GAAG,GACf,CAAC,CACA,SAAS,CAAC,CACV,KAAK,GAAG,IACX;CAEN,OACE,GAAG,OAAO,eAAe,GACtB,OAAO,qBAAqB,GAC5B,kBAAkB,GAClB,OAAO,iBAAiB,GACxB,2BAA2B,MAAM,EAAE,GACnC,OAAO,qBAAqB,SAAS,CAAC,CAAC,KAAK,GAAG,KAAK,GAAG,GACvD,OAAO,YAAY,GACnB,OAAO,UAAU,GACjB,OAAO,sBAAsB,GAC7B,OAAO,uBAAuB,KAAK,GACnC,OAAO,sBAAsB,KAAK,GAClC,OAAO,6BAA6B,KAAK,GACzC,OAAO,OAAO,SAAS,CAAC,CAAC,KAAK,GAAG,EAAE,GACnC,OAAO,mBAAmB,SAAS,CAAC,CAAC,KAAK,GAAG,KAAK,GAAG,GACrD,OAAO,iBAAiB,SAAS,CAAC,CAAC,KAAK,GAAG,KAAK,GAAG,GACnD,OAAO,2BAA2B,SAAS,CAAC,CAAC,KAAK,GAAG,KAAK,GAAG,GAC7D,sBAAsB,GACtB,uBAAuB,GACvB,OAAO,gBAAgB,GAAG,eAAe,GACzC,OAAO,oBAAoB;AAElC;ACrCA,MAAM,8CAA8B,IAAI,QAGtC;AACF,MAAM,mDAAmC,IAAI,IAG3C;AACF,MAAM,qCAAqB,IAAI,QAA8B;AAC7D,IAAI,wBAAwB;;;;;;;;;;;;;;AAe5B,MAAM,gCACJ,OACA,KACA,UACS;CACT,MAAM,OAAO,GAAG;CAChB,IAAI,MAAM,QAAA,IAA0C;EAClD,MAAM,YAAY,MAAM,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;EACtC,IAAI,cAAc,KAAA,GAChB,MAAM,OAAO,SAAS;CAE1B;CACA,MAAM,IAAI,KAAK,KAAK;AACtB;AAEA,MAAM,sBAAsB,iBAAmD;CAC7E,IAAI,iBAAiB,KAAA,GACnB,OAAO;CAET,MAAM,WAAW,mBAAmB,IAAI,YAAY;CACpD,IAAI,aAAa,KAAA,GACf,OAAO,QAAQ;CAEjB,yBAAyB;CACzB,mBAAmB,IAAI,cAAc,qBAAqB;CAC1D,OAAO,QAAQ;AACjB;AAEA,MAAM,yBACJ,iBACiD;CACjD,IAAI,iBAAiB,KAAA,GACnB,OAAO;CAET,MAAM,SAAS,4BAA4B,IAAI,YAAY;CAC3D,IAAI,WAAW,KAAA,GACb,OAAO;CAET,MAAM,0BAAU,IAAI,IAA6C;CACjE,4BAA4B,IAAI,cAAc,OAAO;CACrD,OAAO;AACT;AAEA,MAAa,kCACX,WACgC;CAChC,MAAM,sBAA0D,CAAC;CAKjE,IAAI,eAAe,UAAU,QAAQ,OAAO,SAAS,GACnD,oBAAoB,KAAK,WAAW;CAEtC,IAAI,oBAAoB,WAAW,GACjC,OAAO,EAAE,QAAQ,YAAY;CAE/B,OAAO;EAAE,QAAQ;EAAe;CAAoB;AACtD;AAEA,MAAa,iCAAiC,WAAiC;CAC7E,MAAM,gBAAgB,+BAA+B,MAAM;CAC3D,IAAI,cAAc,WAAW,aAC3B;CAEF,MAAM,IAAI,MACR,yCAAyC,cAAc,oBAAoB,KAAK,IAAI,GACtF;AACF;AAEA,MAAM,UAAU,IAAI,YAAY;;;;;;;AAchC,MAAM,oBACJ,EAAE,cAAc,GAAG,UACnB,sBACoB;CACpB,oBAAoB,QAAQ,OAAO,KAAK,UAAU,MAAM,CAAC;CACzD,kBACE,iBAAiB,KAAA,IACb,KAAA,IACA,QAAQ,OAAO,KAAK,UAAU,YAAY,CAAC;CACjD,eACE,iBAAiB,WAAW,IACxB,KAAA,IACA,QAAQ,OAAO,KAAK,UAAU,gBAAgB,CAAC;AACvD;AAEA,MAAM,wBACJ,SACA,EAAE,oBAAoB,kBAAkB,iBACxC,eACe;CACf,MAAM,WAAW,aACb,QAAQ,6CACR,QAAQ;CACZ,IAAI,aAAa,KAAA,GACf,MAAM,IAAI,MACR,yEACF;CAEF,OAAO,SAAS,oBAAoB,kBAAkB,aAAa;AACrE;AAEA,MAAa,8BAA8B,OAAO,EAChD,SACA,QACA,mBAAmB,CAAC,QAIqB;CACzC,MAAM,eAAe,2BAA2B,MAAM;CACtD,8BAA8B,YAAY;CAC1C,MAAM,WAAW,QAAQ;CACzB,IAAI,aAAa,KAAA,GACf,MAAM,IAAI,MACR,yEACF;CAEF,MAAM,EAAE,oBAAoB,kBAAkB,kBAC5C,iBAAiB,cAAc,gBAAgB;CACjD,MAAM,aAAa,SACjB,oBACA,kBACA,aACF;CACA,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC,OAAO,UAAU,CAAC;AACxD;AAEA,MAAa,+BAA+B,OAAO,EACjD,SACA,QACA,mBAAmB,CAAC,GACpB,SACA,aAAa,YAC0C;CACvD,MAAM,eAAe,MAAM,+BAA+B;EACxD;EACA;EACA;EACA,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;EAC7B;CACF,CAAC;CAID,OAAO,IAAI,WAAW,YAAY;AACpC;AAEA,MAAa,iCAAiC,OAAO,EACnD,SACA,QACA,mBAAmB,CAAC,GACpB,cACiE;CAOjE,OAAO,gCAAgC;EAAE;EAAS,cAAA,MANvB,+BAA+B;GACxD;GACA;GACA;GACA,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;EAC/B,CAAC;CAC8D,CAAC;AAClE;AAEA,MAAM,iCAAiC,OAAO,EAC5C,SACA,QACA,mBAAmB,CAAC,GACpB,SACA,aAAa,YAC0C;CACvD,MAAM,eAAe,2BAA2B,MAAM;CACtD,8BAA8B,YAAY;CAC1C,MAAM,MAAM,WAAW;CACvB,MAAM,MAAM,sBAAsB;EAChC;EACA,QAAQ;EACR;EACA;CACF,CAAC;CACD,IAAI,IAAI,yBAAyB,IAAI,6BAA6B,KAChE,OAAO,IAAI;CAEb,IACE,IAAI,gCACJ,IAAI,6BAA6B,KAEjC,OAAO,IAAI;CAGb,MAAM,cAAc,sBAAsB,aAAa,YAAY;CACnE,MAAM,SAAS,YAAY,IAAI,GAAG;CAClC,IAAI,WAAW,KAAA,GAAW;EACxB,6BAA6B,aAAa,KAAK,MAAM;EACrD,MAAM,eAAe,MAAM;EAC3B,IAAI,wBAAwB;EAC5B,IAAI,2BAA2B;EAC/B,IAAI,+BAA+B;EACnC,OAAO;CACT;CAEA,IAAI,wBAAwB;CAC5B,IAAI,2BAA2B;CAC/B,MAAM,UAAU,2BAA2B;EACzC;EACA,QAAQ;EACR;EACA;CACF,CAAC;CACD,IAAI,+BAA+B;CACnC,6BAA6B,aAAa,KAAK,OAAO;CACtD,IAAI;CACJ,IAAI;EACF,eAAe,MAAM;CACvB,SAAS,OAAO;EACd,IAAI,YAAY,IAAI,GAAG,MAAM,SAC3B,YAAY,OAAO,GAAG;EAExB,IACE,IAAI,6BAA6B,OACjC,IAAI,iCAAiC,SACrC;GACA,IAAI,wBAAwB;GAC5B,IAAI,+BAA+B;EACrC;EACA,MAAM;CACR;CACA,IAAI,YAAY,IAAI,GAAG,MAAM,SAC3B,YAAY,IAAI,KAAK,YAAY;CAEnC,IAAI,IAAI,6BAA6B,KAAK;EACxC,IAAI,wBAAwB;EAC5B,IAAI,+BAA+B;CACrC;CACA,OAAO;AACT;AAMA,MAAM,6BAA6B,OAAO,EACxC,SACA,QACA,kBACA,iBAIA,qBACE,SACA,iBAAiB,QAAQ,gBAAgB,GACzC,UACF;AASF,MAAM,yBAAyB,EAC7B,SACA,QACA,kBACA,iBAEA;CACE,QAAQ,qBAAqB;CAC7B,aAAa,eAAe;CAC5B,mBAAmB,OAAO,YAAY;CACtC,kBAAkB,QAAQ,gBAAgB;AAC5C,CAAC,CAAC,KAAK,GAAG;;;ACpWZ,MAAa,iCAAiD;CAC5D,WAAW;CACX,sBAAsB;CACtB,aAAa;CACb,kBAAkB;CAClB,kBAAkB;CAClB,gBAAgB;CAChB,iBAAiB;CACjB,iBAAiB;CACjB,uBAAuB;CACvB,mBAAmB;CACnB,oBAAoB;CACpB,0BAA0B;CAC1B,QAAQ,CAAC,GAAG,qBAAqB;CACjC,aAAa;AACf;;;ACgEA,MAAa,kCAAkC;CAC7C,WAAW;CACX,MAAM;AACR;AASA,MAAM,sBAAsB;AAC5B,MAAM,+BAA+B;AACrC,MAAM,sCAAsC,IAAI,IAC9C,iCACA,OAAO,KAAK,GACd;AACA,MAAM,0CAA0C,IAAI,IAAI,OAAO,OAAO,KAAK,GAAG;AAC9E,MAAM,2CAA2C;AACjD,MAAM,mDACJ;AACF,MAAM,4CAA4C;AAClD,MAAM,6CAA6B,IAAI,QAGrC;AACF,MAAM,+CAA+B,IAAI,QAAgC;AACzE,MAAM,qDAAqC,IAAI,QAG7C;AAIF,MAAa,8BACX,UAAoC,CAAC,MACV;CAC3B,MAAM,gBAAgB,QAAQ,iBAAiB,cAAc,OAAO,KAAK,GAAG;CAC5E,MAAM,WAAW,QAAQ,YAAY,QAAQ;CAC7C,MAAM,OAAO,QAAQ,QAAQ,QAAQ;CACrC,MAAM,OAAO,QAAQ,QAAQ,iBAAiB,QAAQ;CACtD,MAAM,MAAM,QAAQ,OAAO,QAAQ;CACnC,MAAM,aAAa,wBAAwB;EAAE;EAAM;EAAK;EAAM;CAAS,CAAC;CACxE,MAAM,SAAmB,CAAC;CAE1B,KAAK,MAAM,aAAa,YAAY;EAClC,MAAM,UAAU,qBAAqB;GACnC;GACA;GACA;EACF,CAAC;EACD,IAAI,CAAC,SACH;EAEF,IAAI,QAAQ,oBAAoB,KAAA,GAC9B,2BAA2B;GACzB;GACA,iBAAiB,QAAQ;EAC3B,CAAC;EAEH,OAAO;CACT;CAEA,IAAI,yBAAyB;EAAE;EAAM;EAAM;CAAS,CAAC,MAAM,MACzD,MAAM,6BAA6B;EAAE;EAAM;EAAQ;EAAM;CAAS,CAAC;CAErE,MAAM,IAAI,MACR,+CAA+C,SAAS,GAAG,KAAK,KAAK,OAAO,KAAK,IAAI,GACvF;AACF;AAEA,MAAa,iCACX,gBACe,aAAa,WAAW;AAEzC,MAAa,qCAAqC,OAChD,gBACwB,SAAS,WAAW;AAE9C,MAAa,0BACX,UAA4B,CAAC,MAClBC,yBAAgC,wBAAwB,OAAO,CAAC;AAE7E,MAAa,wBACX,MACA,UAA4B,CAAC,MAClB;CAKX,OAAOC,uBAA8B;EAHnC,SAAS,wBAAwB,OAAO;EACxC;CAEsC,CAAC;AAC3C;AAEA,MAAa,0BACX,QACA,EAAE,aAAa,OAAO,GAAG,YAAqC,CAAC,MAE/DC,yBAAgC;CAC9B,SAAS,wBAAwB,OAAO;CACxC;CACA;AACF,CAAC;AAEH,MAAa,yBACX,cACA,UAA4B,CAAC,MAE7BC,wBAA+B;CAC7B,SAAS,wBAAwB,OAAO;CACxC;AACF,CAAC;AAEH,MAAa,8BACX,aACA,UAA4B,CAAC,MAC1B,sBAAsB,8BAA8B,WAAW,GAAG,OAAO;AAE9E,MAAa,eACX,QACA,UACA,WACA,UAA4B,CAAC,MAE7BC,cAAsB;CACpB,SAAS,wBAAwB,OAAO;CACxC;CACA;CACA,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;AACjD,CAAC;AAEH,MAAa,oBACX,QACA,UACA,WACA,UAA4B,CAAC,MAE7BC,mBAA0B;CACxB,SAAS,wBAAwB,OAAO;CACxC;CACA;CACA,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;AACjD,CAAC;AAEH,MAAa,2BACX,QACA,UACA,SACA,WACA,UAA4B,CAAC,MAE7BC,0BAAgC;CAC9B,SAAS,wBAAwB,OAAO;CACxC;CACA;CACA;CACA,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;AACjD,CAAC;AAEH,MAAa,oBACX,QACA,UACA,WACA,UAA4B,CAAC,MAE7BC,mBAA2B;CACzB,SAAS,wBAAwB,OAAO;CACxC;CACA;CACA,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;AACjD,CAAC;AAEH,MAAa,2BACX,QACA,UACA,SACA,WACA,UAA4B,CAAC,MAE7BC,0BAAiC;CAC/B,SAAS,wBAAwB,OAAO;CACxC;CACA;CACA;CACA,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;AACjD,CAAC;AAEH,MAAa,4BACX,QACA,UACA,WACA,UAA4B,CAAC,MAE7BC,2BAAkC;CAChC,SAAS,wBAAwB,OAAO;CACxC;CACA;CACA,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;AACjD,CAAC;AAEH,MAAa,wCAAwC,EACnD,aAC2C,CAAC,MAAkB;CAC9D,MAAM,aAAa,gCAAgC,QAAQ;CAC3D,IAAI;EACF,OAAO,aAAa,UAAU;CAChC,SAAS,OAAO;EACd,MAAM,IAAI,MACR,GAAG,wCAAwC,QAAQ,EAAE,mBAAmB,gBAAgB,KAAK,GAC/F;CACF;AACF;AAEA,MAAa,6CACX,UAAmD,CAAC,MACrC,qCAAqC,OAAO;AAE7D,MAAa,gDAA0D;CACrE,MAAM,4BAAY,IAAI,IAAY;CAClC,IAAI;EACF,KAAK,MAAM,YAAY,YACrB,uCACF,GAAG;GACD,MAAM,QAAQ,SAAS,MACrB,gDACF;GACA,IAAI,QAAQ,OAAO,KAAA,GACjB,UAAU,IAAI,MAAM,EAAE;EAE1B;CACF,SAAS,OAAO;EACd,MAAM,IAAI,MACR,6DAA6D,gBAAgB,KAAK,GACpF;CACF;CACA,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC,SAAS;AACjC;AAEA,MAAa,8CACX;AAEF,MAAa,4CAA4C,OAAO,EAC9D,aAC2C,CAAC,MAA2B;CACvE,MAAM,aAAa,gCAAgC,QAAQ;CAC3D,IAAI;EACF,OAAO,MAAM,SAAS,UAAU;CAClC,SAAS,OAAO;EACd,MAAM,IAAI,MACR,GAAG,wCAAwC,QAAQ,EAAE,mBAAmB,gBAAgB,KAAK,GAC/F;CACF;AACF;AAEA,MAAa,uCAAuC,EAClD,SACA,aACA,iBACA,GAAG,kBAC2D;CAC9D,MAAM,kBACJ,WACA,2BAA2B;EACzB,GAAG;EACH,GAAI,oBAAoB,KAAA,IAAY,EAAE,gBAAgB,IAAI,CAAC;CAC7D,CAAC;CACH,IAAI,WAAW,oBAAoB,KAAA,GACjC,2BAA2B;EAAE;EAAS;CAAgB,CAAC;CAEzD,OAAO,gCAAgC;EACrC,SAAS;EACT,cAAc,8BAA8B,WAAW;CACzD,CAAC;AACH;AAEA,MAAa,0CACX,UAA+C,CAAC,MACrB;CAC3B,MAAM,kBAAkB,oCAAoC,OAAO;CACnE,OAAO,iCACL,+CAA+C,eAAe,GAC9D,gBAAgB,MAClB;AACF;AAEA,MAAa,+CACX,UAA+C,CAAC,MACrB,uCAAuC,OAAO;AAE3E,MAAa,4BACX,UAA+C,CAAC,MACrB;CAC3B,MAAM,kBAAkB,oCAAoC,OAAO;CACnE,MAAM,QAAQ,wBAAwB,gBAAgB,OAAO;CAC7D,MAAM,MAAM,wBAAwB,eAAe;CACnD,MAAM,SAAS,MAAM,IAAI,GAAG;CAC5B,IAAI,WAAW,KAAA,GACb,OAAO,iCAAiC,QAAQ,gBAAgB,MAAM;CAExE,MAAM,WACJ,+CAA+C,eAAe;CAChE,MAAM,IAAI,KAAK,QAAQ;CACvB,OAAO,iCAAiC,UAAU,gBAAgB,MAAM;AAC1E;AAEA,MAAa,+BACX,UAA+C,CAAC,MACrB,yBAAyB,OAAO;AAE7D,MAAa,gCACX,UAA+C,CAAC,MACrB;CAC3B,MAAM,WAAW,yBAAyB,OAAO;CACjD,OAAO,iCACL,UACA,gCAAgC,SAClC;AACF;AAEA,MAAa,mCACX,UAA+C,CAAC,MACrB,6BAA6B,OAAO;AAEjE,MAAa,qBACX,UACA,WACA,UAA+C,CAAC,MAEhD,yBAAyB,OAAO,CAAC,CAAC,WAAW,UAAU,SAAS;AAElE,MAAa,uBACX,UACA,WACA,UAA+C,CAAC,MAEhD,kBAAkB,UAAU,WAAW,OAAO;AAEhD,MAAa,yBACX,UACA,WACA,UAA+C,CAAC,MAEhD,yBAAyB,OAAO,CAAC,CAAC,iBAAiB,UAAU,SAAS;AAExE,MAAa,4BACX,UACA,WACA,UAA+C,CAAC,MACrC,sBAAsB,UAAU,WAAW,OAAO;AAE/D,MAAa,qCACX,UAA+C,CAAC,MACZ;CACpC,MAAM,kBAAkB;EACtB,GAAG,oCAAoC,OAAO;EAC9C,QAAQ,gCAAgC;CAC1C;CACA,MAAM,QAAQ,wBAAwB,gBAAgB,OAAO;CAC7D,MAAM,MAAM,wBAAwB,eAAe;CACnD,MAAM,SAAS,MAAM,IAAI,GAAG;CAC5B,IAAI,WAAW,KAAA,GACb,OAAO,QAAQ,QACb,iCAAiC,QAAQ,gBAAgB,MAAM,CACjE;CAGF,MAAM,gBAAgB,gCACpB,gBAAgB,OAClB;CACA,MAAM,WAAW,cAAc,IAAI,GAAG;CACtC,IAAI,aAAa,KAAA,GACf,OAAO;CAGT,MAAM,UAAU,oDACd,eACF,CAAC,CACE,MAAM,aAAa;EAClB,MAAM,IAAI,KAAK,QAAQ;EACvB,OAAO,iCAAiC,UAAU,gBAAgB,MAAM;CAC1E,CAAC,CAAC,CACD,cAAc;EACb,cAAc,OAAO,GAAG;CAC1B,CAAC;CACH,cAAc,IAAI,KAAK,OAAO;CAC9B,OAAO;AACT;AAEA,MAAM,uCAAuC,EAC3C,SACA,UACA,aACA,QACA,iBACA,GAAG,gBACoC,CAAC,MAA4C;CACpF,IAAI,aAAa,KAAA,KAAa,gBAAgB,KAAA,GAC5C,MAAM,IAAI,MAAM,8CAA8C;CAEhE,MAAM,kBACJ,WACA,2BAA2B;EACzB,GAAG;EACH,GAAI,oBAAoB,KAAA,IAAY,EAAE,gBAAgB,IAAI,CAAC;CAC7D,CAAC;CACH,IAAI,WAAW,oBAAoB,KAAA,GACjC,2BAA2B;EAAE;EAAS;CAAgB,CAAC;CAEzD,OAAO;EACL,SAAS;EACT,QAAQ,qCAAqC,MAAM;EACnD,GAAI,aAAa,KAAA,IACb,EAAE,UAAU,qCAAqC,QAAQ,EAAE,IAC3D,CAAC;EACL,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;CACrD;AACF;AAEA,MAAM,oCACJ,UACA,WAC2B;CAC3B,IAAI,WAAW,gCAAgC,WAC7C,OAAO;CAET,IAAI,CAAC,6BAA6B,IAAI,QAAQ,GAAG;EAC/C,SAAS,cAAc;EACvB,6BAA6B,IAAI,QAAQ;CAC3C;CACA,OAAO;AACT;AAEA,MAAM,kDAAkD,EACtD,SACA,UACA,kBACkE;CAClE,MAAM,eACJ,gBAAgB,KAAA,IACZ,qCACE,0BAA0B,QAAQ,CACpC,IACA,8BAA8B,WAAW;CAC/C,OAAO,8CAA8C,SAAS,YAAY;AAC5E;AAEA,MAAM,sDAAsD,OAAO,EACjE,SACA,UACA,kBAC2E;CAC3E,MAAM,eACJ,gBAAgB,KAAA,IACZ,MAAM,0CACJ,0BAA0B,QAAQ,CACpC,IACA,MAAM,mCAAmC,WAAW;CAC1D,OAAO,8CAA8C,SAAS,YAAY;AAC5E;AAEA,MAAM,iDACJ,SACA,iBAEA,IAAI,uBACF,IAAI,yBACF,QAAQ,qBAAqB,8CAC3B,YACF,KACE,QAAQ,qBAAqB,kCAC3B,YACF,KACA,QAAQ,qBAAqB,uCAC3B,YACF,KACA,QAAQ,qBAAqB,yBAAyB,YAAY,CACtE,CACF;AAEF,MAAM,6BACJ,aAEA,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS;AAE3C,MAAM,wCACJ,WACgC;CAChC,IAAI,WAAW,KAAA,GACb,OAAO,gCAAgC;CAEzC,QAAQ,QAAR;EACE,KAAK,gCAAgC;EACrC,KAAK,gCAAgC,MACnC,OAAO;CACX;CACA,MAAM,IAAI,MACR,mEACF;AACF;AAEA,MAAM,2BAA2B,EAC/B,SACA,iBACA,GAAG,kBAC2C;CAC9C,MAAM,kBACJ,WACA,2BAA2B;EACzB,GAAG;EACH,GAAI,oBAAoB,KAAA,IAAY,EAAE,gBAAgB,IAAI,CAAC;CAC7D,CAAC;CACH,IAAI,WAAW,oBAAoB,KAAA,GACjC,2BAA2B;EAAE;EAAS;CAAgB,CAAC;CAEzD,OAAO;AACT;AAEA,MAAM,2BACJ,YACwC;CACxC,MAAM,SAAS,2BAA2B,IAAI,OAAO;CACrD,IAAI,WAAW,KAAA,GACb,OAAO;CAET,MAAM,0BAAU,IAAI,IAAoC;CACxD,2BAA2B,IAAI,SAAS,OAAO;CAC/C,OAAO;AACT;AAEA,MAAM,mCACJ,YACiD;CACjD,MAAM,SAAS,mCAAmC,IAAI,OAAO;CAC7D,IAAI,WAAW,KAAA,GACb,OAAO;CAET,MAAM,0BAAU,IAAI,IAA6C;CACjE,mCAAmC,IAAI,SAAS,OAAO;CACvD,OAAO;AACT;AAEA,MAAM,2BAA2B,EAC/B,SACA,UACA,kBAEA,CACE,QAAQ,qBAAqB,GAC7B,gBACG,aAAa,KAAA,IACV,4CACA,YAAY,WACpB,CAAC,CAAC,KAAK,IAAI;AAEb,MAAM,mCAAmC,aAAsC;CAC7E,IAAI,aAAa,KAAA,GACf,OAAO;CAET,MAAM,aAAa,qCAAqC,QAAQ;CAChE,OAAO,wCAAwC,UAAU;AAC3D;AAEA,MAAM,2CAA2C,aAC/C,IAAI,IAAI,sBAAsB,SAAS,cAAc,OAAO,KAAK,GAAG;AAEtE,MAAM,wCAAwC,aAA6B;CACzE,MAAM,aAAa,uCAAuC,QAAQ;CAElE,IAAI,WADa,wCAAwC,UACnC,CAAC,GACrB,OAAO;CAET,MAAM,eAAe,WAAW,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC;CAC/C,IAAI,iBAAiB,KAAA,KAAa,iBAAiB,YACjD,OAAO;CAGT,IAAI,WADY,wCAAwC,YACnC,CAAC,GACpB,OAAO;CAET,OAAO;AACT;AAEA,MAAM,2CACJ,aAEA,aAAa,KAAA,IACT,oCACA,iDAAiD,qCAAqC,QAAQ,EAAE;AAEtG,MAAM,0CAA0C,aAA6B;CAC3E,MAAM,aAAa,SAAS,KAAK,CAAC,CAAC,YAAY;CAC/C,IAAI,CAAC,yCAAyC,KAAK,UAAU,GAC3D,MAAM,IAAI,MACR,+CAA+C,yCAAyC,QAC1F;CAEF,OAAO;AACT;AASA,MAAM,2BAA2B,EAC/B,MACA,KACA,MACA,eAC8C;CAC9C,MAAM,aAAuB,CAAC;CAC9B,MAAM,eAAe,IAAI;CACzB,IAAI,cACF,WAAW,KAAK,YAAY;CAE9B,WAAW,KAAK,mBAAmB;CACnC,MAAM,kBAAkB,yBAAyB;EAAE;EAAM;EAAM;CAAS,CAAC;CACzE,IAAI,oBAAoB,MACtB,WAAW,KAAK,eAAe;CAEjC,OAAO;AACT;AAaA,MAAM,yBAAyD;CAC7D;EACE,UAAU;EACV,MAAM;EACN,SAAS;CACX;CACA;EAAE,UAAU;EAAU,MAAM;EAAO,SAAS;CAA6B;CACzE;EACE,UAAU;EACV,MAAM;EACN,MAAM;EACN,SAAS;CACX;CACA;EACE,UAAU;EACV,MAAM;EACN,MAAM;EACN,SAAS;CACX;CACA;EAAE,UAAU;EAAS,MAAM;EAAO,SAAS;CAAiC;AAC9E;AAcA,MAAM,wBAAwB,EAC5B,MACA,MACA,eAEA,SAAS,KAAA,IAAY,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,KAAK,GAAG;AAEtE,MAAM,2BAA8C,uBAAuB,KACxE,WAAW,qBAAqB,MAAM,CACzC;AAEA,MAAM,4BAA4B,EAChC,MACA,MACA,eACoD;CAOpD,OANc,uBAAuB,MAClC,WACC,OAAO,aAAa,YACpB,OAAO,SAAS,SACf,OAAO,SAAS,KAAA,KAAa,OAAO,SAAS,KAEvC,CAAC,EAAE,WAAW;AAC3B;AAEA,MAAM,gCAAgC,EACpC,MACA,QACA,MACA,eACmE;CACnE,MAAM,SAAS,qBAAqB;EAAE;EAAM;EAAM;CAAS,CAAC;CAC5D,MAAM,YAAY,yBAAyB,KAAK,IAAI;CACpD,MAAM,WAAW,OAAO,SAAS,IAAI,KAAK,OAAO,KAAK,IAAI,MAAM;CAChE,uBAAO,IAAI,MACT,gDAAgD,OAAO,uBAAuB,UAAU,QAAQ,6BAA6B,sDAAsD,UACrL;AACF;AAEA,MAAM,oBAAoB,aAA6C;CACrE,IAAI,aAAa,SACf;CAEF,MAAM,SAAS,QAAQ,QAAQ,UAAU;CAKzC,OAAO,QAHL,cAAc,MAAM,KAAK,cAAc,OAAO,SAAS,IACnD,OAAO,YACP,KAAA,GACiB,2BAA2B,WAAW,QAAQ;AACvE;AAQA,MAAM,wBAAwB,EAC5B,WACA,eACA,aACgE;CAChE,IAAI;EACF,MAAM,SAAS,cAAc,SAAS;EACtC,MAAM,UAAU,yBAAyB,MAAM;EAC/C,IAAI,SACF,OAAO;EAET,OAAO,KAAK,GAAG,UAAU,6CAA6C;CACxE,SAAS,OAAO;EACd,OAAO,KAAK,GAAG,UAAU,IAAI,gBAAgB,KAAK,GAAG;CACvD;CACA,OAAO;AACT;AAEA,MAAM,4BACJ,UACkC;CAClC,MAAM,YACJ,cAAc,KAAK,KAAK,cAAc,MAAM,UAAU,IAClD,MAAM,aACN;CACN,OAAO,yBAAyB,SAAS,IAAI,YAAY;AAC3D;AAEA,MAAM,4BACJ,cACwC;CACxC,IAAI,CAAC,cAAc,SAAS,GAC1B,OAAO;CAET,IAAI,OAAO,UAAU,4BAA4B,YAC/C,OAAO;CAET,IAAI,OAAO,UAAU,0BAA0B,YAC7C,OAAO;CAET,IAAI,OAAO,UAAU,uCAAuC,YAC1D,OAAO;CAET,IACE,OAAO,UAAU,iDAAiD,YAElE,OAAO;CAET,MAAM,iBAAiB,UAAU;CACjC,IAAI,CAAC,cAAc,cAAc,GAC/B,OAAO;CAET,IAAI,OAAO,eAAe,2BAA2B,YACnD,OAAO;CAET,IAAI,OAAO,eAAe,gCAAgC,YACxD,OAAO;CAET,OAAO;AACT;AAEA,MAAM,iBAAiB,UACpB,OAAO,UAAU,YAAY,UAAU,QAAS,OAAO,UAAU;AAEpE,MAAM,mBAAmB,UAA2B;CAClD,IAAI,iBAAiB,OACnB,OAAO,MAAM;CAEf,OAAO,OAAO,KAAK;AACrB"}
|
package/dist/native.d.mts
CHANGED
|
@@ -569,9 +569,9 @@ type CustomDenyListEntry = {
|
|
|
569
569
|
};
|
|
570
570
|
/**
|
|
571
571
|
* Caller-supplied regex detector. The pattern is passed
|
|
572
|
-
* to the
|
|
573
|
-
*
|
|
574
|
-
*
|
|
572
|
+
* to the native Rust regex engine, so use its supported
|
|
573
|
+
* regex syntax. Inline flags such as `(?i)` are accepted
|
|
574
|
+
* when supported by that engine.
|
|
575
575
|
*/
|
|
576
576
|
type CustomRegexPattern = {
|
|
577
577
|
pattern: string;
|
|
@@ -593,12 +593,10 @@ type CustomRegexPattern = {
|
|
|
593
593
|
type Dictionaries = {
|
|
594
594
|
/**
|
|
595
595
|
* First names per language code (e.g., "cs", "de").
|
|
596
|
-
* Merged with legacy config names at init time.
|
|
597
596
|
*/
|
|
598
597
|
firstNames?: Readonly<Record<string, readonly string[]>>;
|
|
599
598
|
/**
|
|
600
599
|
* Surnames per language code.
|
|
601
|
-
* Merged with legacy config names at init time.
|
|
602
600
|
*/
|
|
603
601
|
surnames?: Readonly<Record<string, readonly string[]>>;
|
|
604
602
|
/**
|
|
@@ -699,14 +697,6 @@ type PipelineConfig = {
|
|
|
699
697
|
* additions (Dutch, Russian, Chinese, Arabic, etc.).
|
|
700
698
|
*/
|
|
701
699
|
enableCountries?: boolean;
|
|
702
|
-
/**
|
|
703
|
-
* Reserved for compatibility with the removed TypeScript pipeline.
|
|
704
|
-
* The native pipeline rejects `true`; supply deterministic custom rules today
|
|
705
|
-
* and use the future caller-detection API for model-produced spans.
|
|
706
|
-
*
|
|
707
|
-
* @deprecated Native NER is not implemented.
|
|
708
|
-
*/
|
|
709
|
-
enableNer?: boolean;
|
|
710
700
|
enableConfidenceBoost: boolean;
|
|
711
701
|
enableCoreference: boolean;
|
|
712
702
|
enableZoneClassification?: boolean;
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stll/anonymize",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Deterministic PII detection and anonymization with regex, deny lists, and coreference resolution",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"anonymization",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build": "bun run build:native-wasm && tsdown && bun scripts/build-native-node.mjs && bun run build:wasm-assets",
|
|
64
64
|
"prepublishOnly": "bun run build",
|
|
65
|
-
"typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.test.json && tsc --noEmit -p tsconfig.wasm.json",
|
|
65
|
+
"typecheck": "bun ../../scripts/tsc-native.ts --noEmit -p tsconfig.json && bun ../../scripts/tsc-native.ts --noEmit -p tsconfig.test.json && bun ../../scripts/tsc-native.ts --noEmit -p tsconfig.wasm.json",
|
|
66
66
|
"test": "bun test --timeout 15000",
|
|
67
67
|
"test:fast": "bun run test src/__test__/*.test.ts",
|
|
68
68
|
"test:native-fixtures": "ANONYMIZE_TEST_SLOW_NATIVE_FIXTURE_PARITY=1 bun test --timeout 600000 src/__test__/python-parity.test.ts",
|
|
@@ -79,11 +79,6 @@
|
|
|
79
79
|
"smoke:wasm-browser": "node scripts/smoke-wasm-browser.mjs",
|
|
80
80
|
"format": "oxfmt ."
|
|
81
81
|
},
|
|
82
|
-
"dependencies": {
|
|
83
|
-
"@huggingface/tokenizers": "^0.1.3",
|
|
84
|
-
"@stll/stdnum": "^2.1.1",
|
|
85
|
-
"@stll/text-search": "^1.0.7"
|
|
86
|
-
},
|
|
87
82
|
"peerDependencies": {
|
|
88
83
|
"@stll/anonymize-data": "^0.0.6"
|
|
89
84
|
},
|
|
@@ -93,21 +88,20 @@
|
|
|
93
88
|
}
|
|
94
89
|
},
|
|
95
90
|
"optionalDependencies": {
|
|
96
|
-
"@stll/anonymize-darwin-arm64": "2.
|
|
97
|
-
"@stll/anonymize-darwin-x64": "2.
|
|
98
|
-
"@stll/anonymize-linux-arm64-gnu": "2.
|
|
99
|
-
"@stll/anonymize-linux-x64-gnu": "2.
|
|
100
|
-
"@stll/anonymize-win32-x64-msvc": "2.
|
|
91
|
+
"@stll/anonymize-darwin-arm64": "2.2.0",
|
|
92
|
+
"@stll/anonymize-darwin-x64": "2.2.0",
|
|
93
|
+
"@stll/anonymize-linux-arm64-gnu": "2.2.0",
|
|
94
|
+
"@stll/anonymize-linux-x64-gnu": "2.2.0",
|
|
95
|
+
"@stll/anonymize-win32-x64-msvc": "2.2.0"
|
|
101
96
|
},
|
|
102
97
|
"devDependencies": {
|
|
103
|
-
"@napi-rs/cli": "^3.7.
|
|
98
|
+
"@napi-rs/cli": "^3.7.3",
|
|
104
99
|
"@stll/anonymize-data": "workspace:*",
|
|
105
|
-
"@stll/text-search-wasm": "^1.0.7",
|
|
106
100
|
"bun-types": "^1.3.14",
|
|
107
|
-
"fast-check": "^4.
|
|
101
|
+
"fast-check": "^4.9.0",
|
|
108
102
|
"puppeteer-core": "25.3.0",
|
|
109
|
-
"tsdown": "^0.22.
|
|
103
|
+
"tsdown": "^0.22.7",
|
|
110
104
|
"typescript": "^6.0.3",
|
|
111
|
-
"vite": "^8.1.
|
|
105
|
+
"vite": "^8.1.4"
|
|
112
106
|
}
|
|
113
107
|
}
|