{"id":51324529,"url":"https://github.com/holoflash/zod-redact","last_synced_at":"2026-07-01T17:01:50.934Z","repository":{"id":367026857,"uuid":"1278913362","full_name":"holoflash/zod-redact","owner":"holoflash","description":"Post-validation data redaction for Zod schemas. Annotate fields with replacement values, then parse-and-redact in one step.","archived":false,"fork":false,"pushed_at":"2026-06-24T08:59:54.000Z","size":26,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-24T10:34:23.288Z","etag":null,"topics":["anonymize","data-masking","mask","masking","pii","plugin","privacy","redact","schema","zod"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/zod-redact","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/holoflash.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-24T07:50:21.000Z","updated_at":"2026-06-24T09:00:00.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/holoflash/zod-redact","commit_stats":null,"previous_names":["holoflash/zod-mask"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/holoflash/zod-redact","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/holoflash%2Fzod-redact","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/holoflash%2Fzod-redact/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/holoflash%2Fzod-redact/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/holoflash%2Fzod-redact/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/holoflash","download_url":"https://codeload.github.com/holoflash/zod-redact/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/holoflash%2Fzod-redact/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35015061,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-01T02:00:05.325Z","response_time":130,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anonymize","data-masking","mask","masking","pii","plugin","privacy","redact","schema","zod"],"created_at":"2026-07-01T17:01:50.135Z","updated_at":"2026-07-01T17:01:50.928Z","avatar_url":"https://github.com/holoflash.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# zod-redact\n\n[![bundle size](https://deno.bundlejs.com/badge?q=zod-redact)](https://bundlejs.com/?q=zod-redact)\n\nPost-validation data redaction for [Zod](https://zod.dev) schemas. Annotate fields with replacement values, then parse-and-redact in one step.\n\n```\npnpm install zod-redact\n```\n\nRequires `zod` as a peer dependency.\n\n## Usage\n\n```ts\nimport * as z from \"zod/v4\";\nimport { redact, parseAndRedact } from \"zod-redact\";\n\nconst User = z.object({\n  id: z.string(),\n  name: redact(z.string(), \"***\"),\n  email: redact(z.string(), [\"a@example.com\", \"b@example.com\"]),\n  ssn: redact(z.string(), (seed) =\u003e `XXX-XX-${seed.slice(-4)}`),\n  age: redact(z.number(), 0),\n  isAdmin: redact(z.boolean(), false),\n});\n\nparseAndRedact(User, rawData);\n// { id: \"usr_1\", name: \"***\", email: \"a@example.com\", ssn: \"XXX-XX-sr_1\", age: 0, isAdmin: false }\n```\n\n`redact()` annotates a schema field — it doesn't change parsing behavior. Regular `schema.parse()` still returns real data. Redaction only happens when you use the library's parse functions.\n\n## API\n\n### `redact(schema, replacement)`\n\nAnnotate a field. Returns the schema unchanged (for inline chaining).\n\n| Form | What happens |\n|------|-------------|\n| `redact(z.string(), \"***\")` | Static replacement |\n| `redact(z.string(), [\"A\", \"B\", \"C\"])` | Deterministic pick via DJB2 hash |\n| `redact(z.string(), (seed) =\u003e ...)` | Dynamic — receives a seed string |\n\nWorks with `z.string()`, `z.number()`, `z.boolean()`, and anything else.\n\n### Parse + redact\n\n| Function | Description |\n|----------|-------------|\n| `parseAndRedact(schema, data, opts?)` | Parse, then redact. Throws on invalid input. |\n| `safeParseAndRedact(schema, data, opts?)` | Safe variant — returns `{ success, data/error }`. |\n| `parseAndRedactAsync(schema, data, opts?)` | Async — for schemas with async refinements. |\n| `safeParseAndRedactAsync(schema, data, opts?)` | Async safe variant. |\n| `applyRedact(schema, data, opts?)` | Redact already-parsed data (skips parsing). |\n\n### `combine(fields, template)`\n\nCreate a derived redaction function that picks from multiple arrays and combines them. Useful for generating realistic fake data like full names or emails from component arrays.\n\n```ts\nimport { combine, redact } from \"zod-redact\";\n\nconst fullName = combine(\n  { firstName: firstNames, lastName: lastNames },\n  (first, last) =\u003e `${first} ${last}`,\n);\n\nconst email = combine(\n  { firstName: firstNames, lastName: lastNames },\n  (first, last) =\u003e `${first.toLowerCase()}.${last.toLowerCase()}@example.com`,\n);\n\nconst schema = z.object({\n  name: redact(z.string(), fullName),\n  email: redact(z.string(), email),\n});\n```\n\n### Options\n\n```ts\n{\n  seed?: string;                    // Base seed for deterministic redaction (default: \"\")\n  hash?: (str: string) =\u003e number;   // Custom hash fn (default: DJB2)\n}\n```\n\n## How seeds work\n\nArray and function replacements need a seed to produce deterministic output. The seed is resolved per object:\n\n1. If the object has an `id` field → `String(id)` is used\n2. Otherwise → redacted string field values are concatenated as a composite seed\n3. Fallback → `options.seed` (or `\"\"`)\n\nSame `id` = same redacted output across runs.\n\n## Supported types\n\nObjects, arrays, records, tuples, maps, sets, unions, discriminated unions, pipes, optionals, nullables, defaults, readonly, catch, lazy, and nested combinations of all of the above.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fholoflash%2Fzod-redact","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fholoflash%2Fzod-redact","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fholoflash%2Fzod-redact/lists"}