> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bensevern.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript API

> GoldenMatch as an npm package with full feature parity with the Python toolkit: edge-safe core, Node-only additions, and all scoring, blocking, and golden-record strategies.

GoldenMatch is also published as an npm package with full feature parity with the Python toolkit.

```bash theme={null}
npm install goldenmatch
```

## Quick Start

```typescript theme={null}
import { dedupe } from "goldenmatch";

const rows = [
  { id: 1, name: "John Smith", email: "john@example.com", zip: "12345" },
  { id: 2, name: "Jon Smith",  email: "john@example.com", zip: "12345" },
  { id: 3, name: "Jane Doe",   email: "jane@example.com", zip: "54321" },
];

const result = dedupe(rows, {
  fuzzy: { name: 0.85 },
  blocking: ["zip"],
  threshold: 0.85,
});

console.log(result.stats);
```

## Two Entrypoints

The package ships with two separate entry points so the core stays edge-safe and dependency-free:

* **`goldenmatch`** — edge-safe core. Works in browsers, Cloudflare Workers, Vercel Edge Runtime, Deno, Bun, and Node.
* **`goldenmatch/node`** — adds Node-only features: file I/O (CSV, JSON), HTTP servers, DB connectors.

```typescript theme={null}
// Edge-safe core (pure TS, no Node APIs)
import { dedupe, match, scoreStrings, applyTransforms } from "goldenmatch";

// Node-only additions
import { readFile, writeCsv, dedupeFile, startApiServer } from "goldenmatch/node";
```

## Core API

### dedupe(rows, options)

Deduplicate an array of rows.

```typescript theme={null}
interface DedupeOptions {
  config?: GoldenMatchConfig;
  exact?: readonly string[];
  fuzzy?: Record<string, number>;
  blocking?: readonly string[];
  threshold?: number;
  llmScorer?: boolean;
}

interface DedupeResult {
  goldenRecords: readonly Row[];
  clusters: ReadonlyMap<number, ClusterInfo>;
  dupes: readonly Row[];
  unique: readonly Row[];
  stats: DedupeStats;
  scoredPairs: readonly ScoredPair[];
  config: GoldenMatchConfig;
}
```

### match(target, reference, options)

Match target records against a reference dataset. Returns matched pairs with confidence scores.

### scoreStrings(a, b, scorer?)

Score similarity between two strings. Available scorers:
`exact`, `jaro_winkler`, `levenshtein`, `token_sort`, `soundex_match`, `dice`, `jaccard`, `ensemble`, `given_name_aliased_jw`, `name_freq_weighted_jw`.

```typescript theme={null}
import { scoreStrings } from "goldenmatch";

const score = scoreStrings("MARTHA", "MARHTA", "jaro_winkler");
// 0.9611
```

### applyTransforms(value, transforms)

Apply a chain of normalization transforms to a value.

```typescript theme={null}
import { applyTransforms } from "goldenmatch";

applyTransforms("  John Q. Smith  ", ["strip", "lowercase", "alpha_only"]);
// "johnqsmith"
```

## Scorers

All scorers implement the same interface as Python `goldenmatch.core.scorer`:

| Scorer                       | Use case                                                                     |
| ---------------------------- | ---------------------------------------------------------------------------- |
| **jaro\_winkler**            | Short strings (names). `MARTHA`/`MARHTA` -> 0.9611                           |
| **levenshtein**              | Normalized edit distance                                                     |
| **token\_sort**              | Word reordering tolerant (rapidfuzz-compatible)                              |
| **soundex\_match**           | Phonetic matching (1.0 if same code)                                         |
| **ensemble**                 | Weighted combination of jaro\_winkler + levenshtein + token\_sort + dice     |
| **dice**, **jaccard**        | Set-based similarity for hex-encoded bloom filters (PPRL)                    |
| **embedding**                | Cosine similarity of embeddings                                              |
| **record\_embedding**        | Cosine similarity across whole records                                       |
| **given\_name\_aliased\_jw** | First names — alias-aware JW (William/Bill -> 1.0), bundled given-name table |
| **name\_freq\_weighted\_jw** | Surnames — JW reweighted by US Census surname IDF in the borderline zone     |

The two `*_jw` scorers are refdata-aware and edge-safe: their bundled lookup tables (a given-name alias corpus and the US Census 2010 top-10k surname table) ship inside the npm package, generated from the Python source of truth and drift-guarded in CI. Auto-config swaps them in automatically for first-name and last-name columns. See [Reference Data](/docs/goldenmatch/reference-data) for the algorithms.

## Optional WASM acceleration

The pure-TS scorers run everywhere (browser, Workers, edge, Node) with zero dependencies — that's the default. For workloads that score large blocks you can **optionally** swap in a WebAssembly backend that wraps the same Rust `score-core` kernel the Python package and the SQL UDFs use:

```ts theme={null}
import { dedupe, enableWasm, disableWasm } from "goldenmatch";

await enableWasm();        // async: loads + instantiates the .wasm once
const result = await dedupe(rows, { /* ... */ }); // covered scorers now run in WASM
disableWasm();             // back to pure-TS (e.g. for test isolation)
```

* **Opt-in; pure-TS stays the default and the fallback.** Default users download and parse **zero** wasm bytes (the loader/glue/bytes load only on `enableWasm()`). It returns `false` (pure-TS stays active) on any load failure; pass `{ require: true }` to throw instead.
* **Covered scorers:** `jaro_winkler` / `levenshtein` / `token_sort` / `exact` — the ops `score-core` implements. Every other scorer always stays pure-TS, even when WASM is enabled. The swap is at the NxN block boundary (one JS↔WASM crossing per block, never per pair).
* **Edge-safe + portable:** Node, browsers, and Workers. The `.wasm` ships inside the npm package; the loader resolves it at runtime.
* **Parity-guaranteed:** the WASM kernel *is* rapidfuzz, and the pure-TS scorers are aligned with rapidfuzz to 4 decimals — so enabling WASM does not change results, it just runs them faster.

`goldenanalysis` exposes the same opt-in pattern for its aggregation primitives via `enableAnalysisWasm()` — see [GoldenAnalysis › Native accelerator](/docs/goldenanalysis/native).

## Blocking Strategies

* `static` — single blocking key with transforms
* `multi_pass` — multiple blocking keys, union of blocks
* `sorted_neighborhood` — sliding window over sorted data
* `adaptive` — static + auto-split oversized blocks
* `ann` — approximate nearest neighbor (requires `hnswlib-node` peer dep)
* `canopy` — TF-IDF canopy clustering
* `learned` — data-driven predicate selection

## Golden Record Strategies

* `most_complete` — pick longest string
* `majority_vote` — pick most frequent
* `source_priority` — pick first non-null from priority list
* `most_recent` — pick value with most recent date
* `first_non_null` — pick first non-null

## Transforms

Applied at matchkey time. Same names as the Python toolkit:

`lowercase`, `uppercase`, `strip`, `strip_all`, `soundex`, `metaphone`,
`digits_only`, `alpha_only`, `normalize_whitespace`, `token_sort`,
`first_token`, `last_token`, `substring:start:end`, `qgram:n`.

## CLI

The npm package ships a `goldenmatch-js` binary:

```bash theme={null}
# Dedupe a CSV
npx goldenmatch-js dedupe data.csv --output golden.csv

# Score two strings
npx goldenmatch-js score "MARTHA" "MARHTA" --scorer jaro_winkler
# jaro_winkler: 0.9611

# Match two datasets
npx goldenmatch-js match target.csv reference.csv -o matched.csv

# Profile a dataset
npx goldenmatch-js profile data.csv

# Launch interactive TUI (requires ink peer deps)
npx goldenmatch-js tui data.csv
```

## Servers

### MCP server (Claude Desktop / Claude Code)

```bash theme={null}
npx goldenmatch-js mcp-serve
```

Exposes 45 MCP tools over JSON-RPC on stdio.

### REST API server

```bash theme={null}
npx goldenmatch-js serve --port 8000
```

Endpoints: `/health`, `/dedupe`, `/match`, `/score`, `/explain`, `/profile`, `/clusters`, `/reviews`.

### A2A agent server

```bash theme={null}
npx goldenmatch-js agent-serve --port 8200
```

Agent card at `/.well-known/agent.json` advertises 36 skills (the union of the base A2A skills plus the agent, memory, and identity registries, de-duped by id).

### Interactive TUI

```bash theme={null}
npx goldenmatch-js tui
```

Requires the Ink peer deps (see below).

## Optional Peer Dependencies

All peer deps are optional. Install only what you need:

| Peer dep                                                                                         | Unlocks                                                  |
| ------------------------------------------------------------------------------------------------ | -------------------------------------------------------- |
| `yaml`                                                                                           | YAML config file loading                                 |
| `hnswlib-node`                                                                                   | Sub-linear ANN blocking (vs brute-force)                 |
| `@huggingface/transformers`                                                                      | ONNX cross-encoder reranking (MiniLM)                    |
| `piscina`                                                                                        | Worker-thread parallel block scoring                     |
| `better-sqlite3`                                                                                 | SQLite-backed Learning Memory / review-queue persistence |
| `ink`, `react`, `ink-table`, `ink-select-input`, `ink-text-input`, `ink-spinner`, `ink-gradient` | Interactive TUI                                          |

The database connectors below are **not declared peers** — they are loaded via
runtime dynamic `import()` only when you use the matching Node connector, so
install whichever you need directly: `pg` (Postgres), `@duckdb/node-api`
(DuckDB), `snowflake-sdk` (Snowflake), `@google-cloud/bigquery` (BigQuery),
`@databricks/sql` (Databricks).

## Advanced Features

* **Probabilistic matching** — Fellegi-Sunter with Splink-style EM
* **Splink config converter** — `import-splink` CLI / `convert_splink_config` MCP tool / `fromSplink()` API converts a Splink settings (or trained-model) JSON into a GoldenMatch config, importing trained m/u probabilities directly
* **Negative evidence on Fellegi-Sunter matchkeys** — goldenmatch-js 1.3.0 is a full FS-NE mirror of Python (trainEM / scoring / validation / loader matrix; new exports `neFired`, `fsWeightRange`, `NegativeEvidenceUnsupportedError`; the loader now parses `negative_evidence` for all matchkey types instead of silently dropping it). The TS pipeline (`dedupe` / `matchRecords`) throws on probabilistic+NE (its probabilistic scoring is a simplified weighted-style average), the continuous path rejects NE, and `derive_from` NE is rejected in TS — materialize the column first, or use Python
* **PPRL** — Privacy-preserving record linkage with SHA-256 bloom filters (3 security levels: standard, high, paranoid)
* **Graph ER** — Multi-table entity resolution with evidence propagation
* **Streaming** — Incremental single-record matching
* **Memory** — Persistent corrections + threshold learning
* **Sensitivity analysis** — Parameter sweep with CCMS / TWI cluster comparison
* **Lineage tracking** — Full provenance per field per golden record

## Examples

See [`packages/goldenmatch-js/examples/`](https://github.com/benseverndev-oss/goldenmatch/tree/main/packages/goldenmatch-js/examples) for 11 full end-to-end TypeScript examples covering dedupe, match, PPRL, streaming, graph ER, Fellegi-Sunter, and more.

## Source

* **npm**: [https://www.npmjs.com/package/goldenmatch](https://www.npmjs.com/package/goldenmatch)
* **GitHub**: [https://github.com/benseverndev-oss/goldenmatch/tree/main/packages/goldenmatch-js](https://github.com/benseverndev-oss/goldenmatch/tree/main/packages/goldenmatch-js)

## Comparison With Python

| Feature                                                               | Python                                            | TypeScript                                                   |
| --------------------------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------ |
| Core matching                                                         | Polars + rapidfuzz                                | Pure TS                                                      |
| Refdata name scorers                                                  | `given_name_aliased_jw` + `name_freq_weighted_jw` | Both (bundled tables, 4-decimal parity)                      |
| Fellegi-Sunter                                                        | Yes                                               | Yes                                                          |
| Splink config converter (`import-splink` / `convert_splink_config`)   | Yes                                               | Yes                                                          |
| FS negative evidence (`negative_evidence` on probabilistic matchkeys) | Yes                                               | Yes (direct FS APIs; the pipeline declines probabilistic+NE) |
| PPRL                                                                  | SHA-256                                           | SHA-256 (interop verified byte-for-byte)                     |
| Graph ER                                                              | Yes                                               | Yes                                                          |
| LLM scorer                                                            | Yes                                               | Yes (via fetch, edge-safe)                                   |
| Cross-encoder                                                         | sentence-transformers                             | @huggingface/transformers (ONNX)                             |
| ANN blocking                                                          | FAISS                                             | hnswlib-node                                                 |
| Parallel scoring                                                      | Threads + Ray                                     | piscina worker threads                                       |
| Interactive UI                                                        | Textual TUI                                       | Ink TUI                                                      |
| MCP server                                                            | 69 tools                                          | 45 tools                                                     |
| REST API                                                              | Yes                                               | Yes                                                          |
| A2A server                                                            | Yes                                               | Yes                                                          |
| YAML configs                                                          | Yes                                               | Yes (round-trippable)                                        |
| Edge-safe core                                                        | No                                                | Yes                                                          |
