# Dedup Schemas _(no submodules)_ ## Purpose Zod schemas for the `@suaveplan/dedup` package's configuration types. These schemas serve as the single source of truth for runtime validation of `DedupConfig`, `MatchKey`, and `ScoringRule` objects supplied by callers. All engine constructors run inputs through these schemas before use, ensuring invalid configurations fail fast with clear error messages. ## Features - `MatchKeySchema` — validates field path, weight (0–1), strategy, and optional case-sensitivity flag - `ScoringRuleSchema` — validates the name string of a scoring rule - `DedupConfigSchema` — composes the above with threshold and max-group-size defaults - Coerced defaults: `mergeThreshold` defaults to `0.85`, `maxGroupSize` to `100` - All schemas export inferred TypeScript types via `z.infer` ## Usage: Basic Example ```ts import { DedupConfigSchema } from '@suaveplan/dedup'; import type { DedupConfig } from '@suaveplan/dedup'; const raw = { matchKeys: [{ field: 'email', weight: 1, strategy: 'exact' }], scoringRules: [], }; const config: DedupConfig = DedupConfigSchema.parse(raw); ``` ## Usage: Advanced Example ```ts import { DedupConfigSchema } from '@suaveplan/dedup'; // Validate at API boundary before constructing engine function createEngine(raw: unknown) { const result = DedupConfigSchema.safeParse(raw); if (!result.success) { throw new Error(`Invalid dedup config: ${result.error.message}`); } return new DedupEngine(result.data); } // Multi-key config with custom thresholds const config = DedupConfigSchema.parse({ matchKeys: [ { field: 'email', weight: 0.6, strategy: 'exact' }, { field: 'firstName', weight: 0.2, strategy: 'jaro-winkler' }, { field: 'lastName', weight: 0.2, strategy: 'jaro-winkler' }, ], scoringRules: [], mergeThreshold: 0.75, maxGroupSize: 50, }); ``` ## API Reference ### `MatchKeySchema` ```ts z.object({ field: z.string().min(1), weight: z.number().min(0).max(1), strategy: z.enum(['exact', 'jaro-winkler', 'levenshtein', 'phonetic']), caseSensitive: z.boolean().optional(), }) ``` ### `ScoringRuleSchema` ```ts z.object({ name: z.string().min(1), }) ``` ### `DedupConfigSchema` ```ts z.object({ matchKeys: z.array(MatchKeySchema).min(1), scoringRules: z.array(ScoringRuleSchema), mergeThreshold: z.number().min(0).max(1).optional().default(0.85), maxGroupSize: z.number().int().positive().optional().default(100), }) ``` Inferred types (`MatchKey`, `ScoringRule`, `DedupConfig`) are exported from the package root alongside the schemas. ## Implementation Notes Schemas are defined in a dedicated `.schema.ts` file and excluded from coverage reporting (per project convention). The `ScoringRuleSchema` currently only validates `name` because the `evaluate` function is a runtime interface — Zod cannot validate function types. Callers providing custom scoring rules must implement the `ScoringRule` interface directly. The `weight` field on `MatchKeySchema` is validated to the range `[0, 1]` but the engine does not enforce that all weights sum to exactly 1.0 — this is intentional. Weights below 1 produce a score ceiling below the default threshold, which is a valid configuration for partial-match scenarios. Callers should set `mergeThreshold` accordingly when using sub-unity weight sums.