[{"data":1,"prerenderedAt":3981},["ShallowReactive",2],{"navigation_docs":3,"-learn-catalogs":567,"-learn-catalogs-surround":3976},[4,30,80,133,313,444,503,542],{"title":5,"path":6,"stem":7,"children":8,"page":29},"Start","\u002Fstart","1.start",[9,14,19,24],{"title":10,"path":11,"stem":12,"icon":13},"Introduction","\u002Fstart\u002Fintroduction","1.start\u002F1.introduction","i-lucide-info",{"title":15,"path":16,"stem":17,"icon":18},"Why start with evlog","\u002Fstart\u002Fwhy-evlog","1.start\u002F2.why-evlog","i-lucide-rocket",{"title":20,"path":21,"stem":22,"icon":23},"Installation","\u002Fstart\u002Finstallation","1.start\u002F3.installation","i-lucide-download",{"title":25,"path":26,"stem":27,"icon":28},"Quick Start","\u002Fstart\u002Fquick-start","1.start\u002F4.quick-start","i-lucide-zap",false,{"title":31,"path":32,"stem":33,"children":34,"page":29},"Learn","\u002Flearn","2.learn",[35,40,45,50,55,60,65,70,75],{"title":36,"path":37,"stem":38,"icon":39},"Overview","\u002Flearn\u002Foverview","2.learn\u002F0.overview","i-lucide-list",{"title":41,"path":42,"stem":43,"icon":44},"Simple Logging","\u002Flearn\u002Fsimple-logging","2.learn\u002F1.simple-logging","i-lucide-terminal",{"title":46,"path":47,"stem":48,"icon":49},"Wide Events","\u002Flearn\u002Fwide-events","2.learn\u002F2.wide-events","i-lucide-layers",{"title":51,"path":52,"stem":53,"icon":54},"Structured Errors","\u002Flearn\u002Fstructured-errors","2.learn\u002F3.structured-errors","i-lucide-shield-alert",{"title":56,"path":57,"stem":58,"icon":59},"Lifecycle","\u002Flearn\u002Flifecycle","2.learn\u002F4.lifecycle","i-lucide-arrow-right-left",{"title":61,"path":62,"stem":63,"icon":64},"Sampling","\u002Flearn\u002Fsampling","2.learn\u002F5.sampling","i-lucide-filter",{"title":66,"path":67,"stem":68,"icon":69},"Auto-Redaction","\u002Flearn\u002Fredaction","2.learn\u002F6.redaction","i-lucide-eye-off",{"title":71,"path":72,"stem":73,"icon":74},"Typed Fields","\u002Flearn\u002Ftyped-fields","2.learn\u002F7.typed-fields","i-simple-icons-typescript",{"title":76,"path":77,"stem":78,"icon":79},"Catalogs","\u002Flearn\u002Fcatalogs","2.learn\u002F8.catalogs","i-lucide-book-open",{"title":81,"path":82,"stem":83,"children":84,"page":29},"CLI","\u002Fcli","3.cli",[85,88,93,98,103,108,113,118,123,128],{"title":36,"path":86,"stem":87,"icon":44},"\u002Fcli\u002Foverview","3.cli\u002F0.overview",{"title":89,"path":90,"stem":91,"icon":92},"init","\u002Fcli\u002Finit","3.cli\u002F1.init","i-lucide-wand-sparkles",{"title":94,"path":95,"stem":96,"icon":97},"map","\u002Fcli\u002Fmap","3.cli\u002F2.map","i-lucide-radar",{"title":99,"path":100,"stem":101,"icon":102},"Rules","\u002Fcli\u002Frules","3.cli\u002F3.rules","i-lucide-list-checks",{"title":104,"path":105,"stem":106,"icon":107},"Scoring","\u002Fcli\u002Fscoring","3.cli\u002F4.scoring","i-lucide-gauge",{"title":109,"path":110,"stem":111,"icon":112},"CI","\u002Fcli\u002Fci","3.cli\u002F5.ci","i-lucide-git-pull-request",{"title":114,"path":115,"stem":116,"icon":117},"doctor","\u002Fcli\u002Fdoctor","3.cli\u002F6.doctor","i-lucide-stethoscope",{"title":119,"path":120,"stem":121,"icon":122},"telemetry","\u002Fcli\u002Ftelemetry","3.cli\u002F7.telemetry","i-lucide-bar-chart-3",{"title":124,"path":125,"stem":126,"icon":127},"agents","\u002Fcli\u002Fagents","3.cli\u002F8.agents","i-lucide-bot",{"title":129,"path":130,"stem":131,"icon":132},"Observability Score","\u002Fcli\u002Fobservability-score","3.cli\u002F9.observability-score","i-lucide-activity",{"title":134,"path":135,"stem":136,"children":137,"page":29},"Integrate","\u002Fintegrate","4.integrate",[138,142,225],{"title":36,"path":139,"stem":140,"icon":141},"\u002Fintegrate\u002Foverview","4.integrate\u002F0.overview","i-lucide-plug",{"title":143,"path":144,"stem":145,"children":146,"page":29},"Adapters","\u002Fintegrate\u002Fadapters","4.integrate\u002Fadapters",[147,150,180,205],{"title":36,"path":148,"stem":149,"icon":39},"\u002Fintegrate\u002Fadapters\u002Foverview","4.integrate\u002Fadapters\u002F01.overview",{"title":151,"path":152,"stem":153,"children":154,"page":29},"Cloud","\u002Fintegrate\u002Fadapters\u002Fcloud","4.integrate\u002Fadapters\u002Fcloud",[155,160,165,170,175],{"title":156,"path":157,"stem":158,"icon":159},"Axiom","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Faxiom","4.integrate\u002Fadapters\u002Fcloud\u002F01.axiom","i-custom-axiom",{"title":161,"path":162,"stem":163,"icon":164},"PostHog","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fposthog","4.integrate\u002Fadapters\u002Fcloud\u002F02.posthog","i-simple-icons-posthog",{"title":166,"path":167,"stem":168,"icon":169},"Sentry","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fsentry","4.integrate\u002Fadapters\u002Fcloud\u002F03.sentry","i-simple-icons-sentry",{"title":171,"path":172,"stem":173,"icon":174},"Better Stack","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fbetter-stack","4.integrate\u002Fadapters\u002Fcloud\u002F04.better-stack","i-simple-icons-betterstack",{"title":176,"path":177,"stem":178,"icon":179},"Datadog","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fdatadog","4.integrate\u002Fadapters\u002Fcloud\u002F05.datadog","i-simple-icons-datadog",{"title":181,"path":182,"stem":183,"children":184,"page":29},"Cloud or Self-Hosted","\u002Fintegrate\u002Fadapters\u002Fhybrid","4.integrate\u002Fadapters\u002Fhybrid",[185,190,195,200],{"title":186,"path":187,"stem":188,"icon":189},"Grafana Loki","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Floki","4.integrate\u002Fadapters\u002Fhybrid\u002F01.loki","i-simple-icons-grafana",{"title":191,"path":192,"stem":193,"icon":194},"ClickHouse","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fclickhouse","4.integrate\u002Fadapters\u002Fhybrid\u002F02.clickhouse","i-simple-icons-clickhouse",{"title":196,"path":197,"stem":198,"icon":199},"OTLP","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fotlp","4.integrate\u002Fadapters\u002Fhybrid\u002F03.otlp","i-simple-icons-opentelemetry",{"title":201,"path":202,"stem":203,"icon":204},"HyperDX","\u002Fintegrate\u002Fadapters\u002Fhybrid\u002Fhyperdx","4.integrate\u002Fadapters\u002Fhybrid\u002F04.hyperdx","i-custom-hyperdx",{"title":206,"path":207,"stem":208,"children":209,"page":29},"Self-Hosted","\u002Fintegrate\u002Fadapters\u002Fself-hosted","4.integrate\u002Fadapters\u002Fself-hosted",[210,215,220],{"title":211,"path":212,"stem":213,"icon":214},"File System","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Ffs","4.integrate\u002Fadapters\u002Fself-hosted\u002F01.fs","i-lucide-hard-drive",{"title":216,"path":217,"stem":218,"icon":219},"NuxtHub","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Fnuxthub","4.integrate\u002Fadapters\u002Fself-hosted\u002F02.nuxthub","i-simple-icons-nuxt",{"title":221,"path":222,"stem":223,"icon":224},"Memory","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Fmemory","4.integrate\u002Fadapters\u002Fself-hosted\u002F03.memory","i-lucide-cpu",{"title":226,"path":227,"stem":228,"children":229,"page":29},"Frameworks","\u002Fintegrate\u002Fframeworks","4.integrate\u002Fframeworks",[230,234,239,244,249,254,259,264,269,274,279,284,289,294,298,303,308],{"title":36,"path":231,"stem":232,"icon":233},"\u002Fintegrate\u002Fframeworks\u002Foverview","4.integrate\u002Fframeworks\u002F00.overview","i-lucide-layout-grid",{"title":235,"path":236,"stem":237,"icon":238},"Nuxt","\u002Fintegrate\u002Fframeworks\u002Fnuxt","4.integrate\u002Fframeworks\u002F01.nuxt","i-simple-icons-nuxtdotjs",{"title":240,"path":241,"stem":242,"icon":243},"Next.js","\u002Fintegrate\u002Fframeworks\u002Fnextjs","4.integrate\u002Fframeworks\u002F02.nextjs","i-simple-icons-nextdotjs",{"title":245,"path":246,"stem":247,"icon":248},"SvelteKit","\u002Fintegrate\u002Fframeworks\u002Fsveltekit","4.integrate\u002Fframeworks\u002F03.sveltekit","i-simple-icons-svelte",{"title":250,"path":251,"stem":252,"icon":253},"Nitro","\u002Fintegrate\u002Fframeworks\u002Fnitro","4.integrate\u002Fframeworks\u002F04.nitro","i-custom-nitro",{"title":255,"path":256,"stem":257,"icon":258},"TanStack Start","\u002Fintegrate\u002Fframeworks\u002Ftanstack-start","4.integrate\u002Fframeworks\u002F05.tanstack-start","i-custom-tanstack",{"title":260,"path":261,"stem":262,"icon":263},"NestJS","\u002Fintegrate\u002Fframeworks\u002Fnestjs","4.integrate\u002Fframeworks\u002F06.nestjs","i-simple-icons-nestjs",{"title":265,"path":266,"stem":267,"icon":268},"Express","\u002Fintegrate\u002Fframeworks\u002Fexpress","4.integrate\u002Fframeworks\u002F07.express","i-simple-icons-express",{"title":270,"path":271,"stem":272,"icon":273},"Hono","\u002Fintegrate\u002Fframeworks\u002Fhono","4.integrate\u002Fframeworks\u002F08.hono","i-simple-icons-hono",{"title":275,"path":276,"stem":277,"icon":278},"Fastify","\u002Fintegrate\u002Fframeworks\u002Ffastify","4.integrate\u002Fframeworks\u002F09.fastify","i-simple-icons-fastify",{"title":280,"path":281,"stem":282,"icon":283},"Elysia","\u002Fintegrate\u002Fframeworks\u002Felysia","4.integrate\u002Fframeworks\u002F10.elysia","i-custom-elysia",{"title":285,"path":286,"stem":287,"icon":288},"React Router","\u002Fintegrate\u002Fframeworks\u002Freact-router","4.integrate\u002Fframeworks\u002F11.react-router","i-custom-reactrouter",{"title":290,"path":291,"stem":292,"icon":293},"Cloudflare Workers","\u002Fintegrate\u002Fframeworks\u002Fcloudflare-workers","4.integrate\u002Fframeworks\u002F12.cloudflare-workers","i-simple-icons-cloudflare",{"title":295,"path":296,"stem":297,"icon":74},"Standalone","\u002Fintegrate\u002Fframeworks\u002Fstandalone","4.integrate\u002Fframeworks\u002F13.standalone",{"title":299,"path":300,"stem":301,"icon":302},"Astro","\u002Fintegrate\u002Fframeworks\u002Fastro","4.integrate\u002Fframeworks\u002F14.astro","i-simple-icons-astro",{"title":304,"path":305,"stem":306,"icon":307},"oRPC","\u002Fintegrate\u002Fframeworks\u002Forpc","4.integrate\u002Fframeworks\u002F15.orpc","i-lucide-network",{"title":309,"path":310,"stem":311,"icon":312},"AWS Lambda","\u002Fintegrate\u002Fframeworks\u002Faws-lambda","4.integrate\u002Fframeworks\u002F16.aws-lambda","i-custom-lambda",{"title":314,"path":315,"stem":316,"children":317,"page":29},"Use Cases","\u002Fuse-cases","5.use-cases",[318,321,326,354,381,413,434,439],{"title":36,"path":319,"stem":320,"icon":102},"\u002Fuse-cases\u002Foverview","5.use-cases\u002F0.overview",{"title":322,"path":323,"stem":324,"icon":325},"Client Logging","\u002Fuse-cases\u002Fclient-logging","5.use-cases\u002F1.client-logging","i-lucide-monitor",{"title":327,"icon":328,"path":329,"stem":330,"children":331,"page":29},"AI SDK","i-simple-icons-vercel","\u002Fuse-cases\u002Fai-sdk","5.use-cases\u002F2.ai-sdk",[332,335,340,345,350],{"title":36,"path":333,"stem":334,"icon":39},"\u002Fuse-cases\u002Fai-sdk\u002Foverview","5.use-cases\u002F2.ai-sdk\u002F01.overview",{"title":336,"path":337,"stem":338,"icon":339},"Usage","\u002Fuse-cases\u002Fai-sdk\u002Fusage","5.use-cases\u002F2.ai-sdk\u002F02.usage","i-lucide-code",{"title":341,"path":342,"stem":343,"icon":344},"Options","\u002Fuse-cases\u002Fai-sdk\u002Foptions","5.use-cases\u002F2.ai-sdk\u002F03.options","i-lucide-sliders",{"title":346,"path":347,"stem":348,"icon":349},"Metadata","\u002Fuse-cases\u002Fai-sdk\u002Fmetadata","5.use-cases\u002F2.ai-sdk\u002F04.metadata","i-lucide-database",{"title":351,"path":352,"stem":353,"icon":132},"Telemetry","\u002Fuse-cases\u002Fai-sdk\u002Ftelemetry","5.use-cases\u002F2.ai-sdk\u002F05.telemetry",{"title":355,"icon":356,"path":357,"stem":358,"children":359,"page":29},"Better Auth","i-simple-icons-betterauth","\u002Fuse-cases\u002Fbetter-auth","5.use-cases\u002F3.better-auth",[360,363,368,373,377],{"title":36,"path":361,"stem":362,"icon":39},"\u002Fuse-cases\u002Fbetter-auth\u002Foverview","5.use-cases\u002F3.better-auth\u002F01.overview",{"title":364,"path":365,"stem":366,"icon":367},"Identify User","\u002Fuse-cases\u002Fbetter-auth\u002Fidentify-user","5.use-cases\u002F3.better-auth\u002F02.identify-user","i-lucide-user-check",{"title":369,"path":370,"stem":371,"icon":372},"Middleware","\u002Fuse-cases\u002Fbetter-auth\u002Fmiddleware","5.use-cases\u002F3.better-auth\u002F03.middleware","i-lucide-shield",{"title":374,"path":375,"stem":376,"icon":325},"Client Sync","\u002Fuse-cases\u002Fbetter-auth\u002Fclient-sync","5.use-cases\u002F3.better-auth\u002F04.client-sync",{"title":378,"path":379,"stem":380,"icon":107},"Performance","\u002Fuse-cases\u002Fbetter-auth\u002Fperformance","5.use-cases\u002F3.better-auth\u002F05.performance",{"title":382,"icon":383,"path":384,"stem":385,"children":386,"page":29},"Audit Logs","i-lucide-shield-check","\u002Fuse-cases\u002Faudit","5.use-cases\u002F4.audit",[387,390,395,400,405,409],{"title":36,"path":388,"stem":389,"icon":39},"\u002Fuse-cases\u002Faudit\u002Foverview","5.use-cases\u002F4.audit\u002F01.overview",{"title":391,"path":392,"stem":393,"icon":394},"Schema","\u002Fuse-cases\u002Faudit\u002Fschema","5.use-cases\u002F4.audit\u002F02.schema","i-lucide-file-text",{"title":396,"path":397,"stem":398,"icon":399},"Recording","\u002Fuse-cases\u002Faudit\u002Frecording","5.use-cases\u002F4.audit\u002F03.recording","i-lucide-pen-line",{"title":401,"path":402,"stem":403,"icon":404},"Drains","\u002Fuse-cases\u002Faudit\u002Fpipeline","5.use-cases\u002F4.audit\u002F04.pipeline","i-lucide-link",{"title":406,"path":407,"stem":408,"icon":383},"Compliance","\u002Fuse-cases\u002Faudit\u002Fcompliance","5.use-cases\u002F4.audit\u002F05.compliance",{"title":410,"path":411,"stem":412,"icon":79},"Recipes","\u002Fuse-cases\u002Faudit\u002Frecipes","5.use-cases\u002F4.audit\u002F06.recipes",{"title":351,"icon":107,"path":414,"stem":415,"children":416,"page":29},"\u002Fuse-cases\u002Ftelemetry","5.use-cases\u002F4.telemetry",[417,420,425,430],{"title":36,"path":418,"stem":419,"icon":39},"\u002Fuse-cases\u002Ftelemetry\u002Foverview","5.use-cases\u002F4.telemetry\u002F01.overview",{"title":421,"path":422,"stem":423,"icon":424},"Setup","\u002Fuse-cases\u002Ftelemetry\u002Fsetup","5.use-cases\u002F4.telemetry\u002F02.setup","i-lucide-wrench",{"title":426,"path":427,"stem":428,"icon":429},"Ingest","\u002Fuse-cases\u002Ftelemetry\u002Fingest","5.use-cases\u002F4.telemetry\u002F03.ingest","i-lucide-server",{"title":431,"path":432,"stem":433,"icon":79},"Reference","\u002Fuse-cases\u002Ftelemetry\u002Freference","5.use-cases\u002F4.telemetry\u002F04.reference",{"title":435,"path":436,"stem":437,"icon":438},"Enrichers","\u002Fuse-cases\u002Fenrichers","5.use-cases\u002F5.enrichers","i-lucide-sparkles",{"title":440,"path":441,"stem":442,"icon":443},"eve","\u002Fuse-cases\u002Feve","5.use-cases\u002F5.eve","i-custom-eve",{"title":445,"path":446,"stem":447,"children":448,"page":29},"Extend","\u002Fextend","6.extend",[449,453,458,463,467,472,476,480,484,488,493,498],{"title":36,"path":450,"stem":451,"icon":452},"\u002Fextend\u002Foverview","6.extend\u002F0.overview","i-lucide-blocks",{"title":454,"path":455,"stem":456,"icon":457},"Stream","\u002Fextend\u002Fstream","6.extend\u002F1.stream","i-lucide-radio-tower",{"title":459,"path":460,"stem":461,"icon":462},"Custom framework","\u002Fextend\u002Fcustom-framework","6.extend\u002F10.custom-framework","i-lucide-puzzle",{"title":464,"path":465,"stem":466,"icon":457},"Diagnostics channel","\u002Fextend\u002Fdiagnostics-channel","6.extend\u002F11.diagnostics-channel",{"title":468,"path":469,"stem":470,"icon":471},"FS reader","\u002Fextend\u002Ffs-reader","6.extend\u002F2.fs-reader","i-lucide-folder-search",{"title":410,"path":473,"stem":474,"icon":475},"\u002Fextend\u002Fconsumer-recipes","6.extend\u002F3.consumer-recipes","i-lucide-chef-hat",{"title":477,"path":478,"stem":479,"icon":452},"Plugins","\u002Fextend\u002Fplugins","6.extend\u002F4.plugins",{"title":481,"path":482,"stem":483,"icon":438},"Custom enrichers","\u002Fextend\u002Fcustom-enrichers","6.extend\u002F5.custom-enrichers",{"title":485,"path":486,"stem":487,"icon":64},"Tail sampling","\u002Fextend\u002Ftail-sampling","6.extend\u002F6.tail-sampling",{"title":489,"path":490,"stem":491,"icon":492},"Identity headers","\u002Fextend\u002Fidentity-headers","6.extend\u002F7.identity-headers","i-lucide-fingerprint",{"title":494,"path":495,"stem":496,"icon":497},"Custom drains","\u002Fextend\u002Fcustom-drains","6.extend\u002F8.custom-drains","i-lucide-share-2",{"title":499,"path":500,"stem":501,"icon":502},"Drain pipeline","\u002Fextend\u002Fdrain-pipeline","6.extend\u002F9.drain-pipeline","i-lucide-workflow",{"title":431,"path":504,"stem":505,"children":506,"page":29},"\u002Freference","7.reference",[507,511,516,519,524,528,533,537],{"title":36,"path":508,"stem":509,"icon":510},"\u002Freference\u002Foverview","7.reference\u002F0.overview","i-lucide-book-marked",{"title":512,"path":513,"stem":514,"icon":515},"Configuration","\u002Freference\u002Fconfiguration","7.reference\u002F1.configuration","i-lucide-settings",{"title":378,"path":517,"stem":518,"icon":107},"\u002Freference\u002Fperformance","7.reference\u002F2.performance",{"title":520,"path":521,"stem":522,"icon":523},"Vite Plugin","\u002Freference\u002Fvite-plugin","7.reference\u002F3.vite-plugin","i-custom-vite",{"title":525,"path":526,"stem":527,"icon":383},"Best Practices","\u002Freference\u002Fbest-practices","7.reference\u002F4.best-practices",{"title":529,"path":530,"stem":531,"icon":532},"vs Other Loggers","\u002Freference\u002Fvs-other-loggers","7.reference\u002F5.vs-other-loggers","i-lucide-scale",{"title":534,"path":535,"stem":536,"icon":438},"Agent Skills","\u002Freference\u002Fagent-skills","7.reference\u002F6.agent-skills",{"title":538,"path":539,"stem":540,"icon":541},"Cost","\u002Freference\u002Fcost","7.reference\u002F7.cost","i-lucide-receipt",{"title":543,"path":544,"stem":545,"children":546,"page":29},"Compare","\u002Fcompare","8.compare",[547,551,555,559,563],{"title":548,"path":549,"stem":550,"icon":532},"evlog vs Pino","\u002Fcompare\u002Fpino","8.compare\u002F1.pino",{"title":552,"path":553,"stem":554,"icon":199},"evlog vs OpenTelemetry","\u002Fcompare\u002Fopentelemetry","8.compare\u002F2.opentelemetry",{"title":556,"path":557,"stem":558,"icon":532},"evlog vs LogTape","\u002Fcompare\u002Flogtape","8.compare\u002F3.logtape",{"title":560,"path":561,"stem":562,"icon":532},"evlog vs Winston: formats and request events","\u002Fcompare\u002Fwinston","8.compare\u002F4.winston",{"title":564,"path":565,"stem":566,"icon":532},"evlog vs Consola: reporters and request context","\u002Fcompare\u002Fconsola","8.compare\u002F5.consola",{"id":568,"title":76,"body":569,"description":3966,"extension":3967,"links":3968,"meta":3972,"navigation":3973,"path":77,"seo":3974,"stem":78,"__hash__":3975},"docs\u002F2.learn\u002F8.catalogs.md",{"type":570,"value":571,"toc":3939},"minimark",[572,591,742,755,760,763,866,872,876,879,884,895,1295,1299,1313,1321,1534,1544,1548,1560,1566,1746,1756,1760,1770,1776,1780,1786,1792,2043,2047,2337,2350,2354,2426,2483,2632,2653,2657,2661,2671,2899,2903,2906,2951,3073,3077,3101,3238,3242,3261,3265,3324,3330,3334,3337,3383,3466,3475,3479,3599,3606,3610,3626,3639,3655,3732,3736,3892,3898,3902,3935],[573,574,575,576,580,581,580,584,580,587,590],"p",{},"The catalog primitives (",[577,578,579],"code",{},"defineError",", ",[577,582,583],{},"defineErrorCatalog",[577,585,586],{},"defineAuditAction",[577,588,589],{},"defineAuditCatalog",") are the same regardless of project size. What changes is how you organise them. This page is the deep-dive: conventions, scaling recipes from one file to a published npm package, composition patterns, and the opt-in type augmentation.",[592,593,596,602,733],"prompt",{":actions":594,"description":595,"icon":79},"[\"copy\",\"cursor\",\"claude\"]","Set up typed error and audit catalogs in my app",[573,597,598,599,601],{},"Group errors and audit actions in typed catalogs to eliminate magic strings, get autocomplete on ",[577,600,577],{}," everywhere, and ship them as npm packages in a monorepo.",[603,604,605,617,627,641,650,660,667,674,692,699,713,723],"ul",{},[606,607,608,609,612,613,616],"li",{},"Use ",[577,610,611],{},"defineErrorCatalog(prefix, map)"," for error bundles, ",[577,614,615],{},"defineAuditCatalog(prefix, map)"," for audit bundles",[606,618,608,619,622,623,626],{},[577,620,621],{},"defineError(code, options)"," and ",[577,624,625],{},"defineAuditAction(action, opts?)"," for one-off factories that don't fit a catalog",[606,628,629,630,633,634,580,637,640],{},"Convention: UPPER_SNAKE_CASE keys, lower.dot.case prefix, wire format is ",[577,631,632],{},"${prefix}.${KEY}"," (e.g. ",[577,635,636],{},"billing.PAYMENT_DECLINED",[577,638,639],{},"billing.INVOICE_REFUND",")",[606,642,643,644,580,647,640],{},"One catalog = one bounded context = one prefix = one file (e.g. ",[577,645,646],{},"errors\u002Fbilling.ts",[577,648,649],{},"audit\u002Fbilling.ts",[606,651,652,653,656,657],{},"Throw with ",[577,654,655],{},"billingErrors.PAYMENT_DECLINED({ cause, internal })",", audit with ",[577,658,659],{},"log.audit(billingAudit.INVOICE_REFUND({ actor, target }))",[606,661,662,663,666],{},"Use templated messages (",[577,664,665],{},"message: ({ id }) => \\","User ${id} not found``) when params are dynamic and required",[606,668,669,670,673],{},"Catalog defaults for ",[577,671,672],{},"internal"," are shallow-merged with call-site values (call-site wins)",[606,675,676,677,680,681,580,684,687,688,691],{},"Add the opt-in ",[577,678,679],{},"declare module 'evlog' { interface RegisteredErrorCatalogs { billing: typeof billingErrors } }"," augmentation to surface autocomplete on ",[577,682,683],{},"createError({ code })",[577,685,686],{},"parseError(err).code",", and ",[577,689,690],{},"throwError(code)"," everywhere",[606,693,694,695,698],{},"Scale by sharding: single file → folder per domain → sub-prefixes (",[577,696,697],{},"billing.payment",") → one npm package per bounded context (each owns its prefix, no conflicts possible)",[606,700,701,702,705,706,709,710],{},"Each shared package ships its own ",[577,703,704],{},"declare module 'evlog'"," block in ",[577,707,708],{},"src\u002Findex.ts"," so the type augmentation propagates to consumers via the published ",[577,711,712],{},".d.ts",[606,714,715,716,719,720],{},"Compare on ",[577,717,718],{},"factory.code"," in tests instead of string literals so renames are TS errors, not silent breaks: ",[577,721,722],{},"expect(err.code).toBe(billingErrors.PAYMENT_DECLINED.code)",[606,724,725,726,728,729,732],{},"Never override ",[577,727,577],{}," at the call site (the catalog defines the code identity); never put ",[577,730,731],{},"declare module"," blocks in test files (they leak into the main type-checker)",[573,734,735,736],{},"Docs: ",[737,738,739],"a",{"href":739,"rel":740},"https:\u002F\u002Fwww.evlog.dev\u002Flearn\u002Fcatalogs",[741],"nofollow",[743,744,745,746,622,750,754],"tip",{},"If you haven't yet, start with ",[737,747,749],{"href":748},"\u002Flearn\u002Fstructured-errors#error-catalogs","Structured Errors → Error Catalogs",[737,751,753],{"href":752},"\u002Fuse-cases\u002Faudit\u002Frecording#defineauditcatalog","Audit → defineAuditCatalog"," for the basics. This page assumes you've used the primitives at least once.",[756,757,759],"h2",{"id":758},"conventions","Conventions",[573,761,762],{},"A single set of conventions covers both error and audit catalogs.",[764,765,766,781],"table",{},[767,768,769],"thead",{},[770,771,772,775,778],"tr",{},[773,774],"th",{},[773,776,777],{},"Convention",[773,779,780],{},"Example",[782,783,784,807,831,850],"tbody",{},[770,785,786,793,799],{},[787,788,789],"td",{},[790,791,792],"strong",{},"Catalog key",[787,794,795,798],{},[577,796,797],{},"UPPER_SNAKE_CASE"," (enum-style, scales to hundreds of entries)",[787,800,801,580,804],{},[577,802,803],{},"PAYMENT_DECLINED",[577,805,806],{},"INVOICE_REFUND",[770,808,809,814,820],{},[787,810,811],{},[790,812,813],{},"Prefix",[787,815,816,819],{},[577,817,818],{},"lower.dot.case",", can be hierarchical",[787,821,822,580,825,580,828],{},[577,823,824],{},"'billing'",[577,826,827],{},"'billing.payment'",[577,829,830],{},"'auth.session'",[770,832,833,838,843],{},[787,834,835],{},[790,836,837],{},"Wire format",[787,839,840,842],{},[577,841,632],{}," (preserved casing)",[787,844,845,580,847],{},[577,846,636],{},[577,848,849],{},"auth.INVALID_TOKEN",[770,851,852,857,860],{},[787,853,854],{},[790,855,856],{},"One catalog =",[787,858,859],{},"One bounded context, one prefix, one file",[787,861,862,580,864],{},[577,863,646],{},[577,865,649],{},[573,867,868,869,871],{},"The wire format ends up in HTTP responses, wide events, drains, and dashboards. Stick to it across services so a ",[577,870,577],{}," from one service is recognisable in another.",[756,873,875],{"id":874},"scaling-story","Scaling story",[573,877,878],{},"The same primitives cover four scales without API change.",[880,881,883],"h3",{"id":882},"_1-file-small-repo","1 file: small repo",[573,885,886,887,890,891,894],{},"One ",[577,888,889],{},"errors.ts",", one ",[577,892,893],{},"audit.ts",". Done.",[896,897,898,1144],"code-group",{},[899,900,906],"pre",{"className":901,"code":902,"filename":903,"language":904,"meta":905,"style":905},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { defineErrorCatalog } from 'evlog'\n\nexport const errors = defineErrorCatalog('app', {\n  USER_NOT_FOUND: { status: 404, message: 'User not found' },\n  FORBIDDEN: { status: 403, message: 'Forbidden' },\n  VALIDATION_FAILED: {\n    status: 400,\n    message: ({ field }: { field: string }) => `Invalid ${field}`,\n  },\n})\n","src\u002Ferrors.ts","typescript","",[577,907,908,941,948,984,1022,1054,1064,1078,1129,1135],{"__ignoreMap":905},[909,910,913,917,921,925,928,931,934,938],"span",{"class":911,"line":912},"line",1,[909,914,916],{"class":915},"s7zQu","import",[909,918,920],{"class":919},"sMK4o"," {",[909,922,924],{"class":923},"sTEyZ"," defineErrorCatalog",[909,926,927],{"class":919}," }",[909,929,930],{"class":915}," from",[909,932,933],{"class":919}," '",[909,935,937],{"class":936},"sfazB","evlog",[909,939,940],{"class":919},"'\n",[909,942,944],{"class":911,"line":943},2,[909,945,947],{"emptyLinePlaceholder":946},true,"\n",[909,949,951,954,958,961,964,967,970,973,976,978,981],{"class":911,"line":950},3,[909,952,953],{"class":915},"export",[909,955,957],{"class":956},"spNyl"," const",[909,959,960],{"class":923}," errors ",[909,962,963],{"class":919},"=",[909,965,924],{"class":966},"s2Zo4",[909,968,969],{"class":923},"(",[909,971,972],{"class":919},"'",[909,974,975],{"class":936},"app",[909,977,972],{"class":919},[909,979,980],{"class":919},",",[909,982,983],{"class":919}," {\n",[909,985,987,991,994,996,999,1001,1005,1007,1010,1012,1014,1017,1019],{"class":911,"line":986},4,[909,988,990],{"class":989},"swJcz","  USER_NOT_FOUND",[909,992,993],{"class":919},":",[909,995,920],{"class":919},[909,997,998],{"class":989}," status",[909,1000,993],{"class":919},[909,1002,1004],{"class":1003},"sbssI"," 404",[909,1006,980],{"class":919},[909,1008,1009],{"class":989}," message",[909,1011,993],{"class":919},[909,1013,933],{"class":919},[909,1015,1016],{"class":936},"User not found",[909,1018,972],{"class":919},[909,1020,1021],{"class":919}," },\n",[909,1023,1025,1028,1030,1032,1034,1036,1039,1041,1043,1045,1047,1050,1052],{"class":911,"line":1024},5,[909,1026,1027],{"class":989},"  FORBIDDEN",[909,1029,993],{"class":919},[909,1031,920],{"class":919},[909,1033,998],{"class":989},[909,1035,993],{"class":919},[909,1037,1038],{"class":1003}," 403",[909,1040,980],{"class":919},[909,1042,1009],{"class":989},[909,1044,993],{"class":919},[909,1046,933],{"class":919},[909,1048,1049],{"class":936},"Forbidden",[909,1051,972],{"class":919},[909,1053,1021],{"class":919},[909,1055,1057,1060,1062],{"class":911,"line":1056},6,[909,1058,1059],{"class":989},"  VALIDATION_FAILED",[909,1061,993],{"class":919},[909,1063,983],{"class":919},[909,1065,1067,1070,1072,1075],{"class":911,"line":1066},7,[909,1068,1069],{"class":989},"    status",[909,1071,993],{"class":919},[909,1073,1074],{"class":1003}," 400",[909,1076,1077],{"class":919},",\n",[909,1079,1081,1084,1086,1089,1093,1096,1098,1100,1102,1106,1109,1112,1115,1118,1121,1124,1127],{"class":911,"line":1080},8,[909,1082,1083],{"class":966},"    message",[909,1085,993],{"class":919},[909,1087,1088],{"class":919}," ({",[909,1090,1092],{"class":1091},"sHdIc"," field",[909,1094,1095],{"class":919}," }:",[909,1097,920],{"class":919},[909,1099,1092],{"class":989},[909,1101,993],{"class":919},[909,1103,1105],{"class":1104},"sBMFI"," string",[909,1107,1108],{"class":919}," })",[909,1110,1111],{"class":956}," =>",[909,1113,1114],{"class":919}," `",[909,1116,1117],{"class":936},"Invalid ",[909,1119,1120],{"class":919},"${",[909,1122,1123],{"class":923},"field",[909,1125,1126],{"class":919},"}`",[909,1128,1077],{"class":919},[909,1130,1132],{"class":911,"line":1131},9,[909,1133,1134],{"class":919},"  },\n",[909,1136,1138,1141],{"class":911,"line":1137},10,[909,1139,1140],{"class":919},"}",[909,1142,1143],{"class":923},")\n",[899,1145,1148],{"className":901,"code":1146,"filename":1147,"language":904,"meta":905,"style":905},"import { defineAuditCatalog } from 'evlog'\n\nexport const audit = defineAuditCatalog('app', {\n  USER_LOGIN: { target: 'user', severity: 'medium' },\n  USER_DELETE: { target: 'user', severity: 'high', requiresChanges: true, requiresReason: true },\n})\n","src\u002Faudit.ts",[577,1149,1150,1169,1173,1198,1235,1289],{"__ignoreMap":905},[909,1151,1152,1154,1156,1159,1161,1163,1165,1167],{"class":911,"line":912},[909,1153,916],{"class":915},[909,1155,920],{"class":919},[909,1157,1158],{"class":923}," defineAuditCatalog",[909,1160,927],{"class":919},[909,1162,930],{"class":915},[909,1164,933],{"class":919},[909,1166,937],{"class":936},[909,1168,940],{"class":919},[909,1170,1171],{"class":911,"line":943},[909,1172,947],{"emptyLinePlaceholder":946},[909,1174,1175,1177,1179,1182,1184,1186,1188,1190,1192,1194,1196],{"class":911,"line":950},[909,1176,953],{"class":915},[909,1178,957],{"class":956},[909,1180,1181],{"class":923}," audit ",[909,1183,963],{"class":919},[909,1185,1158],{"class":966},[909,1187,969],{"class":923},[909,1189,972],{"class":919},[909,1191,975],{"class":936},[909,1193,972],{"class":919},[909,1195,980],{"class":919},[909,1197,983],{"class":919},[909,1199,1200,1203,1205,1207,1210,1212,1214,1217,1219,1221,1224,1226,1228,1231,1233],{"class":911,"line":986},[909,1201,1202],{"class":989},"  USER_LOGIN",[909,1204,993],{"class":919},[909,1206,920],{"class":919},[909,1208,1209],{"class":989}," target",[909,1211,993],{"class":919},[909,1213,933],{"class":919},[909,1215,1216],{"class":936},"user",[909,1218,972],{"class":919},[909,1220,980],{"class":919},[909,1222,1223],{"class":989}," severity",[909,1225,993],{"class":919},[909,1227,933],{"class":919},[909,1229,1230],{"class":936},"medium",[909,1232,972],{"class":919},[909,1234,1021],{"class":919},[909,1236,1237,1240,1242,1244,1246,1248,1250,1252,1254,1256,1258,1260,1262,1265,1267,1269,1272,1274,1278,1280,1283,1285,1287],{"class":911,"line":1024},[909,1238,1239],{"class":989},"  USER_DELETE",[909,1241,993],{"class":919},[909,1243,920],{"class":919},[909,1245,1209],{"class":989},[909,1247,993],{"class":919},[909,1249,933],{"class":919},[909,1251,1216],{"class":936},[909,1253,972],{"class":919},[909,1255,980],{"class":919},[909,1257,1223],{"class":989},[909,1259,993],{"class":919},[909,1261,933],{"class":919},[909,1263,1264],{"class":936},"high",[909,1266,972],{"class":919},[909,1268,980],{"class":919},[909,1270,1271],{"class":989}," requiresChanges",[909,1273,993],{"class":919},[909,1275,1277],{"class":1276},"sfNiH"," true",[909,1279,980],{"class":919},[909,1281,1282],{"class":989}," requiresReason",[909,1284,993],{"class":919},[909,1286,1277],{"class":1276},[909,1288,1021],{"class":919},[909,1290,1291,1293],{"class":911,"line":1056},[909,1292,1140],{"class":919},[909,1294,1143],{"class":923},[880,1296,1298],{"id":1297},"_1-folder-1-file-per-domain-medium-repo","1 folder, 1 file per domain: medium repo",[573,1300,1301,1302,622,1305,1308,1309,1312],{},"Group by bounded context. One file per domain in ",[577,1303,1304],{},"src\u002Ferrors\u002F",[577,1306,1307],{},"src\u002Faudit\u002F",". An ",[577,1310,1311],{},"index.ts"," re-exports for ergonomic imports and centralises the type augmentation.",[899,1314,1319],{"className":1315,"code":1317,"language":1318},[1316],"language-text","src\u002F\n├── errors\u002F\n│   ├── billing.ts        → billingErrors (prefix: 'billing')\n│   ├── auth.ts           → authErrors    (prefix: 'auth')\n│   ├── user.ts           → userErrors    (prefix: 'user')\n│   └── index.ts          → re-export + declare module\n├── audit\u002F\n│   ├── billing.ts        → billingAudit\n│   ├── auth.ts           → authAudit\n│   └── index.ts\n","text",[577,1320,1317],{"__ignoreMap":905},[899,1322,1325],{"className":901,"code":1323,"filename":1324,"language":904,"meta":905,"style":905},"import type { authErrors } from '.\u002Fauth'\nimport type { billingErrors } from '.\u002Fbilling'\nimport type { userErrors } from '.\u002Fuser'\n\nexport { authErrors } from '.\u002Fauth'\nexport { billingErrors } from '.\u002Fbilling'\nexport { userErrors } from '.\u002Fuser'\n\ndeclare module 'evlog' {\n  interface RegisteredErrorCatalogs {\n    auth: typeof authErrors\n    billing: typeof billingErrors\n    user: typeof userErrors\n  }\n}\n","src\u002Ferrors\u002Findex.ts",[577,1326,1327,1350,1372,1394,1398,1416,1434,1452,1456,1472,1482,1496,1509,1522,1528],{"__ignoreMap":905},[909,1328,1329,1331,1334,1336,1339,1341,1343,1345,1348],{"class":911,"line":912},[909,1330,916],{"class":915},[909,1332,1333],{"class":915}," type",[909,1335,920],{"class":919},[909,1337,1338],{"class":923}," authErrors",[909,1340,927],{"class":919},[909,1342,930],{"class":915},[909,1344,933],{"class":919},[909,1346,1347],{"class":936},".\u002Fauth",[909,1349,940],{"class":919},[909,1351,1352,1354,1356,1358,1361,1363,1365,1367,1370],{"class":911,"line":943},[909,1353,916],{"class":915},[909,1355,1333],{"class":915},[909,1357,920],{"class":919},[909,1359,1360],{"class":923}," billingErrors",[909,1362,927],{"class":919},[909,1364,930],{"class":915},[909,1366,933],{"class":919},[909,1368,1369],{"class":936},".\u002Fbilling",[909,1371,940],{"class":919},[909,1373,1374,1376,1378,1380,1383,1385,1387,1389,1392],{"class":911,"line":950},[909,1375,916],{"class":915},[909,1377,1333],{"class":915},[909,1379,920],{"class":919},[909,1381,1382],{"class":923}," userErrors",[909,1384,927],{"class":919},[909,1386,930],{"class":915},[909,1388,933],{"class":919},[909,1390,1391],{"class":936},".\u002Fuser",[909,1393,940],{"class":919},[909,1395,1396],{"class":911,"line":986},[909,1397,947],{"emptyLinePlaceholder":946},[909,1399,1400,1402,1404,1406,1408,1410,1412,1414],{"class":911,"line":1024},[909,1401,953],{"class":915},[909,1403,920],{"class":919},[909,1405,1338],{"class":923},[909,1407,927],{"class":919},[909,1409,930],{"class":915},[909,1411,933],{"class":919},[909,1413,1347],{"class":936},[909,1415,940],{"class":919},[909,1417,1418,1420,1422,1424,1426,1428,1430,1432],{"class":911,"line":1056},[909,1419,953],{"class":915},[909,1421,920],{"class":919},[909,1423,1360],{"class":923},[909,1425,927],{"class":919},[909,1427,930],{"class":915},[909,1429,933],{"class":919},[909,1431,1369],{"class":936},[909,1433,940],{"class":919},[909,1435,1436,1438,1440,1442,1444,1446,1448,1450],{"class":911,"line":1066},[909,1437,953],{"class":915},[909,1439,920],{"class":919},[909,1441,1382],{"class":923},[909,1443,927],{"class":919},[909,1445,930],{"class":915},[909,1447,933],{"class":919},[909,1449,1391],{"class":936},[909,1451,940],{"class":919},[909,1453,1454],{"class":911,"line":1080},[909,1455,947],{"emptyLinePlaceholder":946},[909,1457,1458,1461,1464,1466,1468,1470],{"class":911,"line":1131},[909,1459,1460],{"class":956},"declare",[909,1462,1463],{"class":956}," module",[909,1465,933],{"class":919},[909,1467,937],{"class":936},[909,1469,972],{"class":919},[909,1471,983],{"class":919},[909,1473,1474,1477,1480],{"class":911,"line":1137},[909,1475,1476],{"class":956},"  interface",[909,1478,1479],{"class":1104}," RegisteredErrorCatalogs",[909,1481,983],{"class":919},[909,1483,1485,1488,1490,1493],{"class":911,"line":1484},11,[909,1486,1487],{"class":989},"    auth",[909,1489,993],{"class":919},[909,1491,1492],{"class":919}," typeof",[909,1494,1495],{"class":923}," authErrors\n",[909,1497,1499,1502,1504,1506],{"class":911,"line":1498},12,[909,1500,1501],{"class":989},"    billing",[909,1503,993],{"class":919},[909,1505,1492],{"class":919},[909,1507,1508],{"class":923}," billingErrors\n",[909,1510,1512,1515,1517,1519],{"class":911,"line":1511},13,[909,1513,1514],{"class":989},"    user",[909,1516,993],{"class":919},[909,1518,1492],{"class":919},[909,1520,1521],{"class":923}," userErrors\n",[909,1523,1525],{"class":911,"line":1524},14,[909,1526,1527],{"class":919},"  }\n",[909,1529,1531],{"class":911,"line":1530},15,[909,1532,1533],{"class":919},"}\n",[573,1535,1536,1537,1539,1540,1543],{},"The augmentation is purely type-level: there is no ",[577,1538,89],{}," step, no runtime registration. Importing ",[577,1541,1542],{},"~\u002Ferrors"," once anywhere in your app is enough for TypeScript to pick up the merged type.",[880,1545,1547],{"id":1546},"sub-prefixes-very-large-repo","Sub-prefixes: very large repo",[573,1549,1550,1551,580,1553,580,1556,1559],{},"Hierarchical prefixes (",[577,1552,697],{},[577,1554,1555],{},"billing.subscription",[577,1557,1558],{},"auth.session",") keep keys short while preserving namespace clarity. One catalog per sub-domain.",[899,1561,1564],{"className":1562,"code":1563,"language":1318},[1316],"src\u002Ffeatures\u002F\n├── billing\u002F\n│   └── errors\u002F\n│       ├── payment.ts        → billingPaymentErrors (prefix: 'billing.payment')\n│       ├── subscription.ts   → billingSubscriptionErrors\n│       └── invoice.ts        → billingInvoiceErrors\n├── auth\u002F\n│   └── errors\u002F\n│       ├── session.ts        → authSessionErrors (prefix: 'auth.session')\n│       ├── oauth.ts          → authOAuthErrors\n│       └── mfa.ts            → authMfaErrors\n",[577,1565,1563],{"__ignoreMap":905},[899,1567,1570],{"className":901,"code":1568,"filename":1569,"language":904,"meta":905,"style":905},"import { defineErrorCatalog } from 'evlog'\n\nexport const billingPaymentErrors = defineErrorCatalog('billing.payment', {\n  DECLINED: { status: 402, message: 'Card declined' },\n  INSUFFICIENT_FUNDS: { status: 402, message: 'Insufficient funds' },\n  EXPIRED_CARD: { status: 402, message: 'Card expired' },\n  CVV_MISMATCH: { status: 402, message: 'CVV mismatch' },\n})\n","src\u002Ffeatures\u002Fbilling\u002Ferrors\u002Fpayment.ts",[577,1571,1572,1590,1594,1619,1650,1680,1710,1740],{"__ignoreMap":905},[909,1573,1574,1576,1578,1580,1582,1584,1586,1588],{"class":911,"line":912},[909,1575,916],{"class":915},[909,1577,920],{"class":919},[909,1579,924],{"class":923},[909,1581,927],{"class":919},[909,1583,930],{"class":915},[909,1585,933],{"class":919},[909,1587,937],{"class":936},[909,1589,940],{"class":919},[909,1591,1592],{"class":911,"line":943},[909,1593,947],{"emptyLinePlaceholder":946},[909,1595,1596,1598,1600,1603,1605,1607,1609,1611,1613,1615,1617],{"class":911,"line":950},[909,1597,953],{"class":915},[909,1599,957],{"class":956},[909,1601,1602],{"class":923}," billingPaymentErrors ",[909,1604,963],{"class":919},[909,1606,924],{"class":966},[909,1608,969],{"class":923},[909,1610,972],{"class":919},[909,1612,697],{"class":936},[909,1614,972],{"class":919},[909,1616,980],{"class":919},[909,1618,983],{"class":919},[909,1620,1621,1624,1626,1628,1630,1632,1635,1637,1639,1641,1643,1646,1648],{"class":911,"line":986},[909,1622,1623],{"class":989},"  DECLINED",[909,1625,993],{"class":919},[909,1627,920],{"class":919},[909,1629,998],{"class":989},[909,1631,993],{"class":919},[909,1633,1634],{"class":1003}," 402",[909,1636,980],{"class":919},[909,1638,1009],{"class":989},[909,1640,993],{"class":919},[909,1642,933],{"class":919},[909,1644,1645],{"class":936},"Card declined",[909,1647,972],{"class":919},[909,1649,1021],{"class":919},[909,1651,1652,1655,1657,1659,1661,1663,1665,1667,1669,1671,1673,1676,1678],{"class":911,"line":1024},[909,1653,1654],{"class":989},"  INSUFFICIENT_FUNDS",[909,1656,993],{"class":919},[909,1658,920],{"class":919},[909,1660,998],{"class":989},[909,1662,993],{"class":919},[909,1664,1634],{"class":1003},[909,1666,980],{"class":919},[909,1668,1009],{"class":989},[909,1670,993],{"class":919},[909,1672,933],{"class":919},[909,1674,1675],{"class":936},"Insufficient funds",[909,1677,972],{"class":919},[909,1679,1021],{"class":919},[909,1681,1682,1685,1687,1689,1691,1693,1695,1697,1699,1701,1703,1706,1708],{"class":911,"line":1056},[909,1683,1684],{"class":989},"  EXPIRED_CARD",[909,1686,993],{"class":919},[909,1688,920],{"class":919},[909,1690,998],{"class":989},[909,1692,993],{"class":919},[909,1694,1634],{"class":1003},[909,1696,980],{"class":919},[909,1698,1009],{"class":989},[909,1700,993],{"class":919},[909,1702,933],{"class":919},[909,1704,1705],{"class":936},"Card expired",[909,1707,972],{"class":919},[909,1709,1021],{"class":919},[909,1711,1712,1715,1717,1719,1721,1723,1725,1727,1729,1731,1733,1736,1738],{"class":911,"line":1066},[909,1713,1714],{"class":989},"  CVV_MISMATCH",[909,1716,993],{"class":919},[909,1718,920],{"class":919},[909,1720,998],{"class":989},[909,1722,993],{"class":919},[909,1724,1634],{"class":1003},[909,1726,980],{"class":919},[909,1728,1009],{"class":989},[909,1730,993],{"class":919},[909,1732,933],{"class":919},[909,1734,1735],{"class":936},"CVV mismatch",[909,1737,972],{"class":919},[909,1739,1021],{"class":919},[909,1741,1742,1744],{"class":911,"line":1080},[909,1743,1140],{"class":919},[909,1745,1143],{"class":923},[573,1747,1748,1749,580,1752,1755],{},"Wire codes become ",[577,1750,1751],{},"billing.payment.DECLINED",[577,1753,1754],{},"billing.payment.INSUFFICIENT_FUNDS",", etc. The convention scales to hundreds of entries without collisions.",[880,1757,1759],{"id":1758},"npm-packages-monorepo","npm packages: monorepo",[573,1761,1762,1763,1765,1766,1769],{},"In a monorepo, each bounded context can ship as its own npm package. Type augmentation propagates through the published ",[577,1764,712],{},", so consumers get autocomplete just by ",[577,1767,1768],{},"pnpm add @acme\u002Ferrors-billing",".",[899,1771,1774],{"className":1772,"code":1773,"language":1318},[1316],"acme-monorepo\u002F\n├── packages\u002F\n│   ├── errors-billing\u002F         → @acme\u002Ferrors-billing\n│   │   └── src\u002Findex.ts\n│   ├── errors-auth\u002F            → @acme\u002Ferrors-auth\n│   │   └── src\u002Findex.ts\n│   └── audit-billing\u002F          → @acme\u002Faudit-billing\n│       └── src\u002Findex.ts\n└── apps\u002F\n    ├── api\u002F                    → imports + re-exports the catalogs\n    └── worker\u002F\n",[577,1775,1773],{"__ignoreMap":905},[756,1777,1779],{"id":1778},"publishing-a-catalog-as-an-npm-package","Publishing a catalog as an npm package",[573,1781,1782,1783,1785],{},"A catalog is just regular TypeScript that depends on ",[577,1784,937],{}," as a peer dep. Here is the minimal recipe.",[880,1787,1789],{"id":1788},"packagejson",[577,1790,1791],{},"package.json",[899,1793,1798],{"className":1794,"code":1795,"filename":1796,"language":1797,"meta":905,"style":905},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"name\": \"@acme\u002Ferrors-billing\",\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"main\": \".\u002Fdist\u002Findex.mjs\",\n  \"types\": \".\u002Fdist\u002Findex.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"import\": \".\u002Fdist\u002Findex.mjs\",\n      \"types\": \".\u002Fdist\u002Findex.d.ts\"\n    }\n  },\n  \"peerDependencies\": {\n    \"evlog\": \"^3.0.0\"\n  },\n  \"files\": [\"dist\"]\n}\n","packages\u002Ferrors-billing\u002Fpackage.json","json",[577,1799,1800,1805,1828,1848,1868,1888,1908,1921,1934,1953,1970,1975,1979,1992,2009,2013,2038],{"__ignoreMap":905},[909,1801,1802],{"class":911,"line":912},[909,1803,1804],{"class":919},"{\n",[909,1806,1807,1810,1813,1816,1818,1821,1824,1826],{"class":911,"line":943},[909,1808,1809],{"class":919},"  \"",[909,1811,1812],{"class":956},"name",[909,1814,1815],{"class":919},"\"",[909,1817,993],{"class":919},[909,1819,1820],{"class":919}," \"",[909,1822,1823],{"class":936},"@acme\u002Ferrors-billing",[909,1825,1815],{"class":919},[909,1827,1077],{"class":919},[909,1829,1830,1832,1835,1837,1839,1841,1844,1846],{"class":911,"line":950},[909,1831,1809],{"class":919},[909,1833,1834],{"class":956},"version",[909,1836,1815],{"class":919},[909,1838,993],{"class":919},[909,1840,1820],{"class":919},[909,1842,1843],{"class":936},"1.0.0",[909,1845,1815],{"class":919},[909,1847,1077],{"class":919},[909,1849,1850,1852,1855,1857,1859,1861,1864,1866],{"class":911,"line":986},[909,1851,1809],{"class":919},[909,1853,1854],{"class":956},"type",[909,1856,1815],{"class":919},[909,1858,993],{"class":919},[909,1860,1820],{"class":919},[909,1862,1863],{"class":936},"module",[909,1865,1815],{"class":919},[909,1867,1077],{"class":919},[909,1869,1870,1872,1875,1877,1879,1881,1884,1886],{"class":911,"line":1024},[909,1871,1809],{"class":919},[909,1873,1874],{"class":956},"main",[909,1876,1815],{"class":919},[909,1878,993],{"class":919},[909,1880,1820],{"class":919},[909,1882,1883],{"class":936},".\u002Fdist\u002Findex.mjs",[909,1885,1815],{"class":919},[909,1887,1077],{"class":919},[909,1889,1890,1892,1895,1897,1899,1901,1904,1906],{"class":911,"line":1056},[909,1891,1809],{"class":919},[909,1893,1894],{"class":956},"types",[909,1896,1815],{"class":919},[909,1898,993],{"class":919},[909,1900,1820],{"class":919},[909,1902,1903],{"class":936},".\u002Fdist\u002Findex.d.ts",[909,1905,1815],{"class":919},[909,1907,1077],{"class":919},[909,1909,1910,1912,1915,1917,1919],{"class":911,"line":1066},[909,1911,1809],{"class":919},[909,1913,1914],{"class":956},"exports",[909,1916,1815],{"class":919},[909,1918,993],{"class":919},[909,1920,983],{"class":919},[909,1922,1923,1926,1928,1930,1932],{"class":911,"line":1080},[909,1924,1925],{"class":919},"    \"",[909,1927,1769],{"class":1104},[909,1929,1815],{"class":919},[909,1931,993],{"class":919},[909,1933,983],{"class":919},[909,1935,1936,1939,1941,1943,1945,1947,1949,1951],{"class":911,"line":1131},[909,1937,1938],{"class":919},"      \"",[909,1940,916],{"class":1003},[909,1942,1815],{"class":919},[909,1944,993],{"class":919},[909,1946,1820],{"class":919},[909,1948,1883],{"class":936},[909,1950,1815],{"class":919},[909,1952,1077],{"class":919},[909,1954,1955,1957,1959,1961,1963,1965,1967],{"class":911,"line":1137},[909,1956,1938],{"class":919},[909,1958,1894],{"class":1003},[909,1960,1815],{"class":919},[909,1962,993],{"class":919},[909,1964,1820],{"class":919},[909,1966,1903],{"class":936},[909,1968,1969],{"class":919},"\"\n",[909,1971,1972],{"class":911,"line":1484},[909,1973,1974],{"class":919},"    }\n",[909,1976,1977],{"class":911,"line":1498},[909,1978,1134],{"class":919},[909,1980,1981,1983,1986,1988,1990],{"class":911,"line":1511},[909,1982,1809],{"class":919},[909,1984,1985],{"class":956},"peerDependencies",[909,1987,1815],{"class":919},[909,1989,993],{"class":919},[909,1991,983],{"class":919},[909,1993,1994,1996,1998,2000,2002,2004,2007],{"class":911,"line":1524},[909,1995,1925],{"class":919},[909,1997,937],{"class":1104},[909,1999,1815],{"class":919},[909,2001,993],{"class":919},[909,2003,1820],{"class":919},[909,2005,2006],{"class":936},"^3.0.0",[909,2008,1969],{"class":919},[909,2010,2011],{"class":911,"line":1530},[909,2012,1134],{"class":919},[909,2014,2016,2018,2021,2023,2025,2028,2030,2033,2035],{"class":911,"line":2015},16,[909,2017,1809],{"class":919},[909,2019,2020],{"class":956},"files",[909,2022,1815],{"class":919},[909,2024,993],{"class":919},[909,2026,2027],{"class":919}," [",[909,2029,1815],{"class":919},[909,2031,2032],{"class":936},"dist",[909,2034,1815],{"class":919},[909,2036,2037],{"class":919},"]\n",[909,2039,2041],{"class":911,"line":2040},17,[909,2042,1533],{"class":919},[880,2044,2046],{"id":2045},"source-catalog-augmentation-in-the-same-file","Source: catalog + augmentation in the same file",[899,2048,2051],{"className":901,"code":2049,"filename":2050,"language":904,"meta":905,"style":905},"import { defineErrorCatalog } from 'evlog'\n\nexport const billingErrors = defineErrorCatalog('billing', {\n  PAYMENT_DECLINED: {\n    status: 402,\n    message: 'Card declined',\n    why: 'Issuer declined the charge',\n    fix: 'Try a different payment method',\n    link: 'https:\u002F\u002Fdocs.example.com\u002Ferrors\u002Fbilling.payment_declined',\n  },\n  INSUFFICIENT_FUNDS: {\n    status: 402,\n    message: ({ available, required }: { available: number, required: number }) =>\n      `Insufficient funds: $${available}\u002F$${required}`,\n  },\n  \u002F\u002F ...\n})\n\ndeclare module 'evlog' {\n  interface RegisteredErrorCatalogs {\n    billing: typeof billingErrors\n  }\n}\n","packages\u002Ferrors-billing\u002Fsrc\u002Findex.ts",[577,2052,2053,2071,2075,2101,2110,2120,2134,2150,2166,2182,2186,2194,2204,2244,2271,2275,2281,2287,2292,2307,2316,2327,2332],{"__ignoreMap":905},[909,2054,2055,2057,2059,2061,2063,2065,2067,2069],{"class":911,"line":912},[909,2056,916],{"class":915},[909,2058,920],{"class":919},[909,2060,924],{"class":923},[909,2062,927],{"class":919},[909,2064,930],{"class":915},[909,2066,933],{"class":919},[909,2068,937],{"class":936},[909,2070,940],{"class":919},[909,2072,2073],{"class":911,"line":943},[909,2074,947],{"emptyLinePlaceholder":946},[909,2076,2077,2079,2081,2084,2086,2088,2090,2092,2095,2097,2099],{"class":911,"line":950},[909,2078,953],{"class":915},[909,2080,957],{"class":956},[909,2082,2083],{"class":923}," billingErrors ",[909,2085,963],{"class":919},[909,2087,924],{"class":966},[909,2089,969],{"class":923},[909,2091,972],{"class":919},[909,2093,2094],{"class":936},"billing",[909,2096,972],{"class":919},[909,2098,980],{"class":919},[909,2100,983],{"class":919},[909,2102,2103,2106,2108],{"class":911,"line":986},[909,2104,2105],{"class":989},"  PAYMENT_DECLINED",[909,2107,993],{"class":919},[909,2109,983],{"class":919},[909,2111,2112,2114,2116,2118],{"class":911,"line":1024},[909,2113,1069],{"class":989},[909,2115,993],{"class":919},[909,2117,1634],{"class":1003},[909,2119,1077],{"class":919},[909,2121,2122,2124,2126,2128,2130,2132],{"class":911,"line":1056},[909,2123,1083],{"class":989},[909,2125,993],{"class":919},[909,2127,933],{"class":919},[909,2129,1645],{"class":936},[909,2131,972],{"class":919},[909,2133,1077],{"class":919},[909,2135,2136,2139,2141,2143,2146,2148],{"class":911,"line":1066},[909,2137,2138],{"class":989},"    why",[909,2140,993],{"class":919},[909,2142,933],{"class":919},[909,2144,2145],{"class":936},"Issuer declined the charge",[909,2147,972],{"class":919},[909,2149,1077],{"class":919},[909,2151,2152,2155,2157,2159,2162,2164],{"class":911,"line":1080},[909,2153,2154],{"class":989},"    fix",[909,2156,993],{"class":919},[909,2158,933],{"class":919},[909,2160,2161],{"class":936},"Try a different payment method",[909,2163,972],{"class":919},[909,2165,1077],{"class":919},[909,2167,2168,2171,2173,2175,2178,2180],{"class":911,"line":1131},[909,2169,2170],{"class":989},"    link",[909,2172,993],{"class":919},[909,2174,933],{"class":919},[909,2176,2177],{"class":936},"https:\u002F\u002Fdocs.example.com\u002Ferrors\u002Fbilling.payment_declined",[909,2179,972],{"class":919},[909,2181,1077],{"class":919},[909,2183,2184],{"class":911,"line":1137},[909,2185,1134],{"class":919},[909,2187,2188,2190,2192],{"class":911,"line":1484},[909,2189,1654],{"class":989},[909,2191,993],{"class":919},[909,2193,983],{"class":919},[909,2195,2196,2198,2200,2202],{"class":911,"line":1498},[909,2197,1069],{"class":989},[909,2199,993],{"class":919},[909,2201,1634],{"class":1003},[909,2203,1077],{"class":919},[909,2205,2206,2208,2210,2212,2215,2217,2220,2222,2224,2226,2228,2231,2233,2235,2237,2239,2241],{"class":911,"line":1511},[909,2207,1083],{"class":966},[909,2209,993],{"class":919},[909,2211,1088],{"class":919},[909,2213,2214],{"class":1091}," available",[909,2216,980],{"class":919},[909,2218,2219],{"class":1091}," required",[909,2221,1095],{"class":919},[909,2223,920],{"class":919},[909,2225,2214],{"class":989},[909,2227,993],{"class":919},[909,2229,2230],{"class":1104}," number",[909,2232,980],{"class":919},[909,2234,2219],{"class":989},[909,2236,993],{"class":919},[909,2238,2230],{"class":1104},[909,2240,1108],{"class":919},[909,2242,2243],{"class":956}," =>\n",[909,2245,2246,2249,2252,2254,2257,2259,2262,2264,2267,2269],{"class":911,"line":1524},[909,2247,2248],{"class":919},"      `",[909,2250,2251],{"class":936},"Insufficient funds: $",[909,2253,1120],{"class":919},[909,2255,2256],{"class":923},"available",[909,2258,1140],{"class":919},[909,2260,2261],{"class":936},"\u002F$",[909,2263,1120],{"class":919},[909,2265,2266],{"class":923},"required",[909,2268,1126],{"class":919},[909,2270,1077],{"class":919},[909,2272,2273],{"class":911,"line":1530},[909,2274,1134],{"class":919},[909,2276,2277],{"class":911,"line":2015},[909,2278,2280],{"class":2279},"sHwdD","  \u002F\u002F ...\n",[909,2282,2283,2285],{"class":911,"line":2040},[909,2284,1140],{"class":919},[909,2286,1143],{"class":923},[909,2288,2290],{"class":911,"line":2289},18,[909,2291,947],{"emptyLinePlaceholder":946},[909,2293,2295,2297,2299,2301,2303,2305],{"class":911,"line":2294},19,[909,2296,1460],{"class":956},[909,2298,1463],{"class":956},[909,2300,933],{"class":919},[909,2302,937],{"class":936},[909,2304,972],{"class":919},[909,2306,983],{"class":919},[909,2308,2310,2312,2314],{"class":911,"line":2309},20,[909,2311,1476],{"class":956},[909,2313,1479],{"class":1104},[909,2315,983],{"class":919},[909,2317,2319,2321,2323,2325],{"class":911,"line":2318},21,[909,2320,1501],{"class":989},[909,2322,993],{"class":919},[909,2324,1492],{"class":919},[909,2326,1508],{"class":923},[909,2328,2330],{"class":911,"line":2329},22,[909,2331,1527],{"class":919},[909,2333,2335],{"class":911,"line":2334},23,[909,2336,1533],{"class":919},[573,2338,2339,2340,2342,2343,2346,2347,2349],{},"The ",[577,2341,731],{}," block lives inside the source file so the bundler emits it into the ",[577,2344,2345],{},"dist\u002Findex.d.ts",". Any consumer that imports from ",[577,2348,1823],{}," gets the augmentation transitively, with no extra setup required on their side.",[880,2351,2353],{"id":2352},"consumption","Consumption",[899,2355,2358],{"className":901,"code":2356,"filename":2357,"language":904,"meta":905,"style":905},"\u002F\u002F Importing the package activates both the runtime catalog and the type augmentation.\nimport { billingErrors } from '@acme\u002Ferrors-billing'\nimport { authErrors } from '@acme\u002Ferrors-auth'\n\n\u002F\u002F Re-export from a central place so the rest of the app has one import path.\nexport { billingErrors, authErrors }\n","apps\u002Fapi\u002Fsrc\u002Finit.ts",[577,2359,2360,2365,2383,2402,2406,2411],{"__ignoreMap":905},[909,2361,2362],{"class":911,"line":912},[909,2363,2364],{"class":2279},"\u002F\u002F Importing the package activates both the runtime catalog and the type augmentation.\n",[909,2366,2367,2369,2371,2373,2375,2377,2379,2381],{"class":911,"line":943},[909,2368,916],{"class":915},[909,2370,920],{"class":919},[909,2372,1360],{"class":923},[909,2374,927],{"class":919},[909,2376,930],{"class":915},[909,2378,933],{"class":919},[909,2380,1823],{"class":936},[909,2382,940],{"class":919},[909,2384,2385,2387,2389,2391,2393,2395,2397,2400],{"class":911,"line":950},[909,2386,916],{"class":915},[909,2388,920],{"class":919},[909,2390,1338],{"class":923},[909,2392,927],{"class":919},[909,2394,930],{"class":915},[909,2396,933],{"class":919},[909,2398,2399],{"class":936},"@acme\u002Ferrors-auth",[909,2401,940],{"class":919},[909,2403,2404],{"class":911,"line":986},[909,2405,947],{"emptyLinePlaceholder":946},[909,2407,2408],{"class":911,"line":1024},[909,2409,2410],{"class":2279},"\u002F\u002F Re-export from a central place so the rest of the app has one import path.\n",[909,2412,2413,2415,2417,2419,2421,2423],{"class":911,"line":1056},[909,2414,953],{"class":915},[909,2416,920],{"class":919},[909,2418,1360],{"class":923},[909,2420,980],{"class":919},[909,2422,1338],{"class":923},[909,2424,2425],{"class":919}," }\n",[899,2427,2430],{"className":901,"code":2428,"filename":2429,"language":904,"meta":905,"style":905},"import { billingErrors } from '~\u002Finit'\n\nthrow billingErrors.PAYMENT_DECLINED({ cause: stripeErr })\n","apps\u002Fapi\u002Fsrc\u002Froutes\u002Fcheckout.post.ts",[577,2431,2432,2451,2455],{"__ignoreMap":905},[909,2433,2434,2436,2438,2440,2442,2444,2446,2449],{"class":911,"line":912},[909,2435,916],{"class":915},[909,2437,920],{"class":919},[909,2439,1360],{"class":923},[909,2441,927],{"class":919},[909,2443,930],{"class":915},[909,2445,933],{"class":919},[909,2447,2448],{"class":936},"~\u002Finit",[909,2450,940],{"class":919},[909,2452,2453],{"class":911,"line":943},[909,2454,947],{"emptyLinePlaceholder":946},[909,2456,2457,2460,2462,2464,2466,2468,2471,2474,2476,2479,2481],{"class":911,"line":950},[909,2458,2459],{"class":915},"throw",[909,2461,1360],{"class":923},[909,2463,1769],{"class":919},[909,2465,803],{"class":966},[909,2467,969],{"class":923},[909,2469,2470],{"class":919},"{",[909,2472,2473],{"class":989}," cause",[909,2475,993],{"class":919},[909,2477,2478],{"class":923}," stripeErr ",[909,2480,1140],{"class":919},[909,2482,1143],{"class":923},[899,2484,2487],{"className":901,"code":2485,"filename":2486,"language":904,"meta":905,"style":905},"import { createError, parseError } from 'evlog'\n\nthrow createError({\n  code: 'billing.PAYMENT_DECLINED', \u002F\u002F ← autocomplete from the registered catalog\n  message: 'Card declined',\n  status: 402,\n})\n\nconst err = parseError(caught)\nif (err.code === 'billing.PAYMENT_DECLINED') retry()\n\u002F\u002F                ↑ TypeScript knows the union of all registered codes\n","Anywhere in the app — autocomplete works",[577,2488,2489,2513,2517,2527,2545,2560,2571,2577,2581,2596,2627],{"__ignoreMap":905},[909,2490,2491,2493,2495,2498,2500,2503,2505,2507,2509,2511],{"class":911,"line":912},[909,2492,916],{"class":915},[909,2494,920],{"class":919},[909,2496,2497],{"class":923}," createError",[909,2499,980],{"class":919},[909,2501,2502],{"class":923}," parseError",[909,2504,927],{"class":919},[909,2506,930],{"class":915},[909,2508,933],{"class":919},[909,2510,937],{"class":936},[909,2512,940],{"class":919},[909,2514,2515],{"class":911,"line":943},[909,2516,947],{"emptyLinePlaceholder":946},[909,2518,2519,2521,2523,2525],{"class":911,"line":950},[909,2520,2459],{"class":915},[909,2522,2497],{"class":966},[909,2524,969],{"class":923},[909,2526,1804],{"class":919},[909,2528,2529,2532,2534,2536,2538,2540,2542],{"class":911,"line":986},[909,2530,2531],{"class":989},"  code",[909,2533,993],{"class":919},[909,2535,933],{"class":919},[909,2537,636],{"class":936},[909,2539,972],{"class":919},[909,2541,980],{"class":919},[909,2543,2544],{"class":2279}," \u002F\u002F ← autocomplete from the registered catalog\n",[909,2546,2547,2550,2552,2554,2556,2558],{"class":911,"line":1024},[909,2548,2549],{"class":989},"  message",[909,2551,993],{"class":919},[909,2553,933],{"class":919},[909,2555,1645],{"class":936},[909,2557,972],{"class":919},[909,2559,1077],{"class":919},[909,2561,2562,2565,2567,2569],{"class":911,"line":1056},[909,2563,2564],{"class":989},"  status",[909,2566,993],{"class":919},[909,2568,1634],{"class":1003},[909,2570,1077],{"class":919},[909,2572,2573,2575],{"class":911,"line":1066},[909,2574,1140],{"class":919},[909,2576,1143],{"class":923},[909,2578,2579],{"class":911,"line":1080},[909,2580,947],{"emptyLinePlaceholder":946},[909,2582,2583,2586,2589,2591,2593],{"class":911,"line":1131},[909,2584,2585],{"class":956},"const",[909,2587,2588],{"class":923}," err ",[909,2590,963],{"class":919},[909,2592,2502],{"class":966},[909,2594,2595],{"class":923},"(caught)\n",[909,2597,2598,2601,2604,2606,2609,2612,2614,2616,2618,2621,2624],{"class":911,"line":1137},[909,2599,2600],{"class":915},"if",[909,2602,2603],{"class":923}," (err",[909,2605,1769],{"class":919},[909,2607,2608],{"class":923},"code ",[909,2610,2611],{"class":919},"===",[909,2613,933],{"class":919},[909,2615,636],{"class":936},[909,2617,972],{"class":919},[909,2619,2620],{"class":923},") ",[909,2622,2623],{"class":966},"retry",[909,2625,2626],{"class":923},"()\n",[909,2628,2629],{"class":911,"line":1484},[909,2630,2631],{"class":2279},"\u002F\u002F                ↑ TypeScript knows the union of all registered codes\n",[2633,2634,2637,2640,2641,2643,2644,580,2647,2643,2649,2652],"callout",{"color":2635,"icon":2636},"neutral","i-lucide-package",[790,2638,2639],{},"Each shared package owns its prefix."," ",[577,2642,1823],{}," owns ",[577,2645,2646],{},"billing.*",[577,2648,2399],{},[577,2650,2651],{},"auth.*",". Conflicts are impossible by construction. Bumping a catalog to a new minor (adding entries) propagates to consumers via the regular semver upgrade path: no codegen, no migration step.",[756,2654,2656],{"id":2655},"composition-patterns","Composition patterns",[880,2658,2660],{"id":2659},"mix-catalogs-and-standalone-factories","Mix catalogs and standalone factories",[573,2662,2663,622,2665,2667,2668,2670],{},[577,2664,579],{},[577,2666,583],{}," produce identical call-site shapes. Use catalogs for grouped errors, ",[577,2669,579],{}," for one-offs (e.g. cross-cutting concerns like rate-limiting that don't belong to a specific domain).",[899,2672,2674],{"className":901,"code":2673,"filename":1324,"language":904,"meta":905,"style":905},"import { defineError, defineErrorCatalog } from 'evlog'\n\nexport const billingErrors = defineErrorCatalog('billing', {\n  PAYMENT_DECLINED: { status: 402, message: 'Card declined' },\n})\n\nexport const rateLimited = defineError('app.RATE_LIMITED', {\n  status: 429,\n  message: ({ retryAfter }: { retryAfter: number }) =>\n    `Rate limited: retry in ${retryAfter}s`,\n})\n\n\u002F\u002F Both look identical at the call site:\nthrow billingErrors.PAYMENT_DECLINED()\nthrow rateLimited({ retryAfter: 30 })\n",[577,2675,2676,2699,2703,2727,2755,2761,2765,2791,2802,2827,2850,2856,2860,2865,2877],{"__ignoreMap":905},[909,2677,2678,2680,2682,2685,2687,2689,2691,2693,2695,2697],{"class":911,"line":912},[909,2679,916],{"class":915},[909,2681,920],{"class":919},[909,2683,2684],{"class":923}," defineError",[909,2686,980],{"class":919},[909,2688,924],{"class":923},[909,2690,927],{"class":919},[909,2692,930],{"class":915},[909,2694,933],{"class":919},[909,2696,937],{"class":936},[909,2698,940],{"class":919},[909,2700,2701],{"class":911,"line":943},[909,2702,947],{"emptyLinePlaceholder":946},[909,2704,2705,2707,2709,2711,2713,2715,2717,2719,2721,2723,2725],{"class":911,"line":950},[909,2706,953],{"class":915},[909,2708,957],{"class":956},[909,2710,2083],{"class":923},[909,2712,963],{"class":919},[909,2714,924],{"class":966},[909,2716,969],{"class":923},[909,2718,972],{"class":919},[909,2720,2094],{"class":936},[909,2722,972],{"class":919},[909,2724,980],{"class":919},[909,2726,983],{"class":919},[909,2728,2729,2731,2733,2735,2737,2739,2741,2743,2745,2747,2749,2751,2753],{"class":911,"line":986},[909,2730,2105],{"class":989},[909,2732,993],{"class":919},[909,2734,920],{"class":919},[909,2736,998],{"class":989},[909,2738,993],{"class":919},[909,2740,1634],{"class":1003},[909,2742,980],{"class":919},[909,2744,1009],{"class":989},[909,2746,993],{"class":919},[909,2748,933],{"class":919},[909,2750,1645],{"class":936},[909,2752,972],{"class":919},[909,2754,1021],{"class":919},[909,2756,2757,2759],{"class":911,"line":1024},[909,2758,1140],{"class":919},[909,2760,1143],{"class":923},[909,2762,2763],{"class":911,"line":1056},[909,2764,947],{"emptyLinePlaceholder":946},[909,2766,2767,2769,2771,2774,2776,2778,2780,2782,2785,2787,2789],{"class":911,"line":1066},[909,2768,953],{"class":915},[909,2770,957],{"class":956},[909,2772,2773],{"class":923}," rateLimited ",[909,2775,963],{"class":919},[909,2777,2684],{"class":966},[909,2779,969],{"class":923},[909,2781,972],{"class":919},[909,2783,2784],{"class":936},"app.RATE_LIMITED",[909,2786,972],{"class":919},[909,2788,980],{"class":919},[909,2790,983],{"class":919},[909,2792,2793,2795,2797,2800],{"class":911,"line":1080},[909,2794,2564],{"class":989},[909,2796,993],{"class":919},[909,2798,2799],{"class":1003}," 429",[909,2801,1077],{"class":919},[909,2803,2804,2806,2808,2810,2813,2815,2817,2819,2821,2823,2825],{"class":911,"line":1131},[909,2805,2549],{"class":966},[909,2807,993],{"class":919},[909,2809,1088],{"class":919},[909,2811,2812],{"class":1091}," retryAfter",[909,2814,1095],{"class":919},[909,2816,920],{"class":919},[909,2818,2812],{"class":989},[909,2820,993],{"class":919},[909,2822,2230],{"class":1104},[909,2824,1108],{"class":919},[909,2826,2243],{"class":956},[909,2828,2829,2832,2835,2837,2840,2842,2845,2848],{"class":911,"line":1137},[909,2830,2831],{"class":919},"    `",[909,2833,2834],{"class":936},"Rate limited: retry in ",[909,2836,1120],{"class":919},[909,2838,2839],{"class":923},"retryAfter",[909,2841,1140],{"class":919},[909,2843,2844],{"class":936},"s",[909,2846,2847],{"class":919},"`",[909,2849,1077],{"class":919},[909,2851,2852,2854],{"class":911,"line":1484},[909,2853,1140],{"class":919},[909,2855,1143],{"class":923},[909,2857,2858],{"class":911,"line":1498},[909,2859,947],{"emptyLinePlaceholder":946},[909,2861,2862],{"class":911,"line":1511},[909,2863,2864],{"class":2279},"\u002F\u002F Both look identical at the call site:\n",[909,2866,2867,2869,2871,2873,2875],{"class":911,"line":1524},[909,2868,2459],{"class":915},[909,2870,1360],{"class":923},[909,2872,1769],{"class":919},[909,2874,803],{"class":966},[909,2876,2626],{"class":923},[909,2878,2879,2881,2884,2886,2888,2890,2892,2895,2897],{"class":911,"line":1530},[909,2880,2459],{"class":915},[909,2882,2883],{"class":966}," rateLimited",[909,2885,969],{"class":923},[909,2887,2470],{"class":919},[909,2889,2812],{"class":989},[909,2891,993],{"class":919},[909,2893,2894],{"class":1003}," 30",[909,2896,927],{"class":919},[909,2898,1143],{"class":923},[880,2900,2902],{"id":2901},"re-export-from-one-entry-per-domain","Re-export from one entry per domain",[573,2904,2905],{},"If a feature ships errors and audits together, give it a single re-export module so call sites only import once.",[899,2907,2910],{"className":901,"code":2908,"filename":2909,"language":904,"meta":905,"style":905},"export { billingErrors } from '.\u002Ferrors\u002Fbilling'\nexport { billingAudit } from '.\u002Faudit\u002Fbilling'\n","src\u002Ffeatures\u002Fbilling\u002Findex.ts",[577,2911,2912,2931],{"__ignoreMap":905},[909,2913,2914,2916,2918,2920,2922,2924,2926,2929],{"class":911,"line":912},[909,2915,953],{"class":915},[909,2917,920],{"class":919},[909,2919,1360],{"class":923},[909,2921,927],{"class":919},[909,2923,930],{"class":915},[909,2925,933],{"class":919},[909,2927,2928],{"class":936},".\u002Ferrors\u002Fbilling",[909,2930,940],{"class":919},[909,2932,2933,2935,2937,2940,2942,2944,2946,2949],{"class":911,"line":943},[909,2934,953],{"class":915},[909,2936,920],{"class":919},[909,2938,2939],{"class":923}," billingAudit",[909,2941,927],{"class":919},[909,2943,930],{"class":915},[909,2945,933],{"class":919},[909,2947,2948],{"class":936},".\u002Faudit\u002Fbilling",[909,2950,940],{"class":919},[899,2952,2955],{"className":901,"code":2953,"filename":2954,"language":904,"meta":905,"style":905},"import { billingErrors, billingAudit } from '~\u002Ffeatures\u002Fbilling'\n\nif (!cart.items.length) throw billingErrors.CART_EMPTY()\n\nlog.audit(billingAudit.INVOICE_REFUND({ actor, target: { id: 'inv_889' } }))\n","server\u002Fapi\u002Frefund.post.ts",[577,2956,2957,2980,2984,3018,3022],{"__ignoreMap":905},[909,2958,2959,2961,2963,2965,2967,2969,2971,2973,2975,2978],{"class":911,"line":912},[909,2960,916],{"class":915},[909,2962,920],{"class":919},[909,2964,1360],{"class":923},[909,2966,980],{"class":919},[909,2968,2939],{"class":923},[909,2970,927],{"class":919},[909,2972,930],{"class":915},[909,2974,933],{"class":919},[909,2976,2977],{"class":936},"~\u002Ffeatures\u002Fbilling",[909,2979,940],{"class":919},[909,2981,2982],{"class":911,"line":943},[909,2983,947],{"emptyLinePlaceholder":946},[909,2985,2986,2988,2991,2994,2997,2999,3002,3004,3007,3009,3011,3013,3016],{"class":911,"line":950},[909,2987,2600],{"class":915},[909,2989,2990],{"class":923}," (",[909,2992,2993],{"class":919},"!",[909,2995,2996],{"class":923},"cart",[909,2998,1769],{"class":919},[909,3000,3001],{"class":923},"items",[909,3003,1769],{"class":919},[909,3005,3006],{"class":923},"length) ",[909,3008,2459],{"class":915},[909,3010,1360],{"class":923},[909,3012,1769],{"class":919},[909,3014,3015],{"class":966},"CART_EMPTY",[909,3017,2626],{"class":923},[909,3019,3020],{"class":911,"line":986},[909,3021,947],{"emptyLinePlaceholder":946},[909,3023,3024,3027,3029,3032,3035,3037,3039,3041,3043,3046,3048,3050,3052,3054,3057,3059,3061,3064,3066,3068,3070],{"class":911,"line":1024},[909,3025,3026],{"class":923},"log",[909,3028,1769],{"class":919},[909,3030,3031],{"class":966},"audit",[909,3033,3034],{"class":923},"(billingAudit",[909,3036,1769],{"class":919},[909,3038,806],{"class":966},[909,3040,969],{"class":923},[909,3042,2470],{"class":919},[909,3044,3045],{"class":923}," actor",[909,3047,980],{"class":919},[909,3049,1209],{"class":989},[909,3051,993],{"class":919},[909,3053,920],{"class":919},[909,3055,3056],{"class":989}," id",[909,3058,993],{"class":919},[909,3060,933],{"class":919},[909,3062,3063],{"class":936},"inv_889",[909,3065,972],{"class":919},[909,3067,927],{"class":919},[909,3069,927],{"class":919},[909,3071,3072],{"class":923},"))\n",[880,3074,3076],{"id":3075},"override-catalog-defaults-at-the-call-site","Override catalog defaults at the call site",[573,3078,3079,3080,580,3083,580,3086,580,3089,580,3092,580,3095,3097,3098,3100],{},"Every entry's defaults (",[577,3081,3082],{},"message",[577,3084,3085],{},"status",[577,3087,3088],{},"why",[577,3090,3091],{},"fix",[577,3093,3094],{},"link",[577,3096,672],{},") are overridable per call. ",[577,3099,672],{}," is shallow-merged (call-site wins on conflict).",[899,3102,3104],{"className":901,"code":3103,"language":904,"meta":905,"style":905},"\u002F\u002F Catalog default:\n\u002F\u002F message: 'Card declined'\n\u002F\u002F internal: { category: 'gateway' }\n\nthrow billingErrors.PAYMENT_DECLINED({\n  message: 'Custom message for this specific call',\n  internal: { stripeRef: 'ch_x', category: 'gateway-overridden' },\n  cause: stripeErr,\n})\n\n\u002F\u002F Resulting EvlogError:\n\u002F\u002F - message: 'Custom message for this specific call' (override)\n\u002F\u002F - status: 402 (catalog default)\n\u002F\u002F - why: 'Issuer declined the charge' (catalog default)\n\u002F\u002F - internal: { category: 'gateway-overridden', stripeRef: 'ch_x' }\n",[577,3105,3106,3111,3116,3121,3125,3139,3154,3191,3203,3209,3213,3218,3223,3228,3233],{"__ignoreMap":905},[909,3107,3108],{"class":911,"line":912},[909,3109,3110],{"class":2279},"\u002F\u002F Catalog default:\n",[909,3112,3113],{"class":911,"line":943},[909,3114,3115],{"class":2279},"\u002F\u002F message: 'Card declined'\n",[909,3117,3118],{"class":911,"line":950},[909,3119,3120],{"class":2279},"\u002F\u002F internal: { category: 'gateway' }\n",[909,3122,3123],{"class":911,"line":986},[909,3124,947],{"emptyLinePlaceholder":946},[909,3126,3127,3129,3131,3133,3135,3137],{"class":911,"line":1024},[909,3128,2459],{"class":915},[909,3130,1360],{"class":923},[909,3132,1769],{"class":919},[909,3134,803],{"class":966},[909,3136,969],{"class":923},[909,3138,1804],{"class":919},[909,3140,3141,3143,3145,3147,3150,3152],{"class":911,"line":1056},[909,3142,2549],{"class":989},[909,3144,993],{"class":919},[909,3146,933],{"class":919},[909,3148,3149],{"class":936},"Custom message for this specific call",[909,3151,972],{"class":919},[909,3153,1077],{"class":919},[909,3155,3156,3159,3161,3163,3166,3168,3170,3173,3175,3177,3180,3182,3184,3187,3189],{"class":911,"line":1066},[909,3157,3158],{"class":989},"  internal",[909,3160,993],{"class":919},[909,3162,920],{"class":919},[909,3164,3165],{"class":989}," stripeRef",[909,3167,993],{"class":919},[909,3169,933],{"class":919},[909,3171,3172],{"class":936},"ch_x",[909,3174,972],{"class":919},[909,3176,980],{"class":919},[909,3178,3179],{"class":989}," category",[909,3181,993],{"class":919},[909,3183,933],{"class":919},[909,3185,3186],{"class":936},"gateway-overridden",[909,3188,972],{"class":919},[909,3190,1021],{"class":919},[909,3192,3193,3196,3198,3201],{"class":911,"line":1080},[909,3194,3195],{"class":989},"  cause",[909,3197,993],{"class":919},[909,3199,3200],{"class":923}," stripeErr",[909,3202,1077],{"class":919},[909,3204,3205,3207],{"class":911,"line":1131},[909,3206,1140],{"class":919},[909,3208,1143],{"class":923},[909,3210,3211],{"class":911,"line":1137},[909,3212,947],{"emptyLinePlaceholder":946},[909,3214,3215],{"class":911,"line":1484},[909,3216,3217],{"class":2279},"\u002F\u002F Resulting EvlogError:\n",[909,3219,3220],{"class":911,"line":1498},[909,3221,3222],{"class":2279},"\u002F\u002F - message: 'Custom message for this specific call' (override)\n",[909,3224,3225],{"class":911,"line":1511},[909,3226,3227],{"class":2279},"\u002F\u002F - status: 402 (catalog default)\n",[909,3229,3230],{"class":911,"line":1524},[909,3231,3232],{"class":2279},"\u002F\u002F - why: 'Issuer declined the charge' (catalog default)\n",[909,3234,3235],{"class":911,"line":1530},[909,3236,3237],{"class":2279},"\u002F\u002F - internal: { category: 'gateway-overridden', stripeRef: 'ch_x' }\n",[756,3239,3241],{"id":3240},"type-augmentation-deep-dive","Type augmentation: deep dive",[573,3243,3244,3245,3247,3248,580,3250,3252,3253,3256,3257,3260],{},"The opt-in ",[577,3246,704],{}," block is what surfaces autocomplete on ",[577,3249,683],{},[577,3251,686],{},", and the typed ",[577,3254,3255],{},"ErrorCode"," \u002F ",[577,3258,3259],{},"AuditAction"," exports.",[880,3262,3264],{"id":3263},"where-to-put-the-augmentation","Where to put the augmentation",[764,3266,3267,3277],{},[767,3268,3269],{},[770,3270,3271,3274],{},[773,3272,3273],{},"Repo shape",[773,3275,3276],{},"Recommended location",[782,3278,3279,3289,3303,3316],{},[770,3280,3281,3286],{},[787,3282,3283,3284,640],{},"Single file (",[577,3285,903],{},[787,3287,3288],{},"At the bottom of the same file",[770,3290,3291,3297],{},[787,3292,3293,3294,640],{},"Folder (",[577,3295,3296],{},"src\u002Ferrors\u002F*.ts",[787,3298,3299,3300,3302],{},"In ",[577,3301,1324],{}," (centralised) or each catalog file (decentralised)",[770,3304,3305,3308],{},[787,3306,3307],{},"npm package",[787,3309,3310,3311,3313,3314],{},"At the bottom of the package's main ",[577,3312,708],{}," so it ships in the published ",[577,3315,712],{},[770,3317,3318,3321],{},[787,3319,3320],{},"Monorepo",[787,3322,3323],{},"One augmentation per package, no central registry needed",[573,3325,3326,3327,3329],{},"Both centralised and decentralised work, because TypeScript merges multiple ",[577,3328,704],{}," blocks across files automatically.",[880,3331,3333],{"id":3332},"how-to-add-custom-domains","How to add custom domains",[573,3335,3336],{},"Each augmentation key is the namespace name. Multiple catalogs sharing a prefix can either be merged into one key or split:",[899,3338,3341],{"className":901,"code":3339,"filename":3340,"language":904,"meta":905,"style":905},"declare module 'evlog' {\n  interface RegisteredErrorCatalogs {\n    billing: typeof billingErrors\n  }\n}\n","Centralised — one key per package",[577,3342,3343,3357,3365,3375,3379],{"__ignoreMap":905},[909,3344,3345,3347,3349,3351,3353,3355],{"class":911,"line":912},[909,3346,1460],{"class":956},[909,3348,1463],{"class":956},[909,3350,933],{"class":919},[909,3352,937],{"class":936},[909,3354,972],{"class":919},[909,3356,983],{"class":919},[909,3358,3359,3361,3363],{"class":911,"line":943},[909,3360,1476],{"class":956},[909,3362,1479],{"class":1104},[909,3364,983],{"class":919},[909,3366,3367,3369,3371,3373],{"class":911,"line":950},[909,3368,1501],{"class":989},[909,3370,993],{"class":919},[909,3372,1492],{"class":919},[909,3374,1508],{"class":923},[909,3376,3377],{"class":911,"line":986},[909,3378,1527],{"class":919},[909,3380,3381],{"class":911,"line":1024},[909,3382,1533],{"class":919},[899,3384,3387],{"className":901,"code":3385,"filename":3386,"language":904,"meta":905,"style":905},"declare module 'evlog' {\n  interface RegisteredErrorCatalogs {\n    'billing.payment': typeof billingPaymentErrors\n    'billing.subscription': typeof billingSubscriptionErrors\n    'billing.invoice': typeof billingInvoiceErrors\n  }\n}\n","Decentralised — one key per sub-domain",[577,3388,3389,3403,3411,3427,3442,3458,3462],{"__ignoreMap":905},[909,3390,3391,3393,3395,3397,3399,3401],{"class":911,"line":912},[909,3392,1460],{"class":956},[909,3394,1463],{"class":956},[909,3396,933],{"class":919},[909,3398,937],{"class":936},[909,3400,972],{"class":919},[909,3402,983],{"class":919},[909,3404,3405,3407,3409],{"class":911,"line":943},[909,3406,1476],{"class":956},[909,3408,1479],{"class":1104},[909,3410,983],{"class":919},[909,3412,3413,3416,3418,3420,3422,3424],{"class":911,"line":950},[909,3414,3415],{"class":919},"    '",[909,3417,697],{"class":936},[909,3419,972],{"class":919},[909,3421,993],{"class":919},[909,3423,1492],{"class":919},[909,3425,3426],{"class":923}," billingPaymentErrors\n",[909,3428,3429,3431,3433,3435,3437,3439],{"class":911,"line":986},[909,3430,3415],{"class":919},[909,3432,1555],{"class":936},[909,3434,972],{"class":919},[909,3436,993],{"class":919},[909,3438,1492],{"class":919},[909,3440,3441],{"class":923}," billingSubscriptionErrors\n",[909,3443,3444,3446,3449,3451,3453,3455],{"class":911,"line":1024},[909,3445,3415],{"class":919},[909,3447,3448],{"class":936},"billing.invoice",[909,3450,972],{"class":919},[909,3452,993],{"class":919},[909,3454,1492],{"class":919},[909,3456,3457],{"class":923}," billingInvoiceErrors\n",[909,3459,3460],{"class":911,"line":1056},[909,3461,1527],{"class":919},[909,3463,3464],{"class":911,"line":1066},[909,3465,1533],{"class":919},[573,3467,2339,3468,3471,3472,3474],{},[577,3469,3470],{},"_codes"," literal union is what produces the actual ",[577,3473,3255],{}," type. The keys themselves are arbitrary, choose what feels right for your structure.",[880,3476,3478],{"id":3477},"verifying-the-augmentation","Verifying the augmentation",[899,3480,3483],{"className":901,"code":3481,"filename":3482,"language":904,"meta":905,"style":905},"import type { ErrorCode, AuditAction } from 'evlog'\n\n\u002F\u002F Hover the type in your IDE — should show the union of all registered codes.\ntype AllErrorCodes = ErrorCode\ntype AllAuditActions = AuditAction\n\n\u002F\u002F Compile-time check:\nconst validCode: ErrorCode = 'billing.PAYMENT_DECLINED' \u002F\u002F OK\nconst invalidCode: ErrorCode = 'billing.NOPE' \u002F\u002F ← TS error if catalog is registered\n","Anywhere in the codebase",[577,3484,3485,3511,3515,3520,3533,3545,3549,3554,3576],{"__ignoreMap":905},[909,3486,3487,3489,3491,3493,3496,3498,3501,3503,3505,3507,3509],{"class":911,"line":912},[909,3488,916],{"class":915},[909,3490,1333],{"class":915},[909,3492,920],{"class":919},[909,3494,3495],{"class":923}," ErrorCode",[909,3497,980],{"class":919},[909,3499,3500],{"class":923}," AuditAction",[909,3502,927],{"class":919},[909,3504,930],{"class":915},[909,3506,933],{"class":919},[909,3508,937],{"class":936},[909,3510,940],{"class":919},[909,3512,3513],{"class":911,"line":943},[909,3514,947],{"emptyLinePlaceholder":946},[909,3516,3517],{"class":911,"line":950},[909,3518,3519],{"class":2279},"\u002F\u002F Hover the type in your IDE — should show the union of all registered codes.\n",[909,3521,3522,3524,3527,3530],{"class":911,"line":986},[909,3523,1854],{"class":956},[909,3525,3526],{"class":1104}," AllErrorCodes",[909,3528,3529],{"class":919}," =",[909,3531,3532],{"class":1104}," ErrorCode\n",[909,3534,3535,3537,3540,3542],{"class":911,"line":1024},[909,3536,1854],{"class":956},[909,3538,3539],{"class":1104}," AllAuditActions",[909,3541,3529],{"class":919},[909,3543,3544],{"class":1104}," AuditAction\n",[909,3546,3547],{"class":911,"line":1056},[909,3548,947],{"emptyLinePlaceholder":946},[909,3550,3551],{"class":911,"line":1066},[909,3552,3553],{"class":2279},"\u002F\u002F Compile-time check:\n",[909,3555,3556,3558,3561,3563,3565,3567,3569,3571,3573],{"class":911,"line":1080},[909,3557,2585],{"class":956},[909,3559,3560],{"class":923}," validCode",[909,3562,993],{"class":919},[909,3564,3495],{"class":1104},[909,3566,3529],{"class":919},[909,3568,933],{"class":919},[909,3570,636],{"class":936},[909,3572,972],{"class":919},[909,3574,3575],{"class":2279}," \u002F\u002F OK\n",[909,3577,3578,3580,3583,3585,3587,3589,3591,3594,3596],{"class":911,"line":1131},[909,3579,2585],{"class":956},[909,3581,3582],{"class":923}," invalidCode",[909,3584,993],{"class":919},[909,3586,3495],{"class":1104},[909,3588,3529],{"class":919},[909,3590,933],{"class":919},[909,3592,3593],{"class":936},"billing.NOPE",[909,3595,972],{"class":919},[909,3597,3598],{"class":2279}," \u002F\u002F ← TS error if catalog is registered\n",[573,3600,3601,3602,3605],{},"If autocomplete is empty, either no catalog is registered yet, or the augmentation file is not in the TypeScript program (check ",[577,3603,3604],{},"tsconfig.json"," includes).",[756,3607,3609],{"id":3608},"common-pitfalls","Common pitfalls",[3611,3612,3613,3619,3620,3622,3623,1769],"warning",{},[790,3614,3615,3616,3618],{},"Don't put ",[577,3617,731],{}," blocks in test files."," Augmentations from test files leak into the type-checker for the rest of the codebase if the test files are included in the main ",[577,3621,3604],{},". Keep augmentations next to the catalog source, never inside ",[577,3624,3625],{},"*.test.ts",[3611,3627,3628,3631,3632,3635,3636,3638],{},[790,3629,3630],{},"Avoid prefix collisions across packages."," If two packages augment the same ",[577,3633,3634],{},"RegisteredErrorCatalogs"," key (say both ship a ",[577,3637,2094],{}," catalog), TypeScript merges them silently and the runtime keeps the last-registered factory. Convention: one prefix per package, no overlap.",[3611,3640,3641,3647,3648,3651,3652,3654],{},[790,3642,3643,3644,3646],{},"Never override the ",[577,3645,577],{}," at the call site."," The catalog defines the code identity, and overriding it would break dashboards, alerts, and consumer code branching on ",[577,3649,3650],{},"err.code",". The factory's call-site signature deliberately omits ",[577,3653,577],{}," from the overridable fields.",[743,3656,3657,3666],{},[573,3658,3659,3665],{},[790,3660,3661,3662,3664],{},"Prefer ",[577,3663,718],{}," over string comparisons in tests."," Both forms below are valid; the first survives renames (refactor-safe), the second doesn't.",[899,3667,3669],{"className":901,"code":3668,"language":904,"meta":905,"style":905},"expect(err.code).toBe(billingErrors.PAYMENT_DECLINED.code) \u002F\u002F ✓ refactor-safe\nexpect(err.code).toBe('billing.PAYMENT_DECLINED')          \u002F\u002F ✗ string literal\n",[577,3670,3671,3704],{"__ignoreMap":905},[909,3672,3673,3676,3679,3681,3684,3686,3689,3692,3694,3696,3698,3701],{"class":911,"line":912},[909,3674,3675],{"class":966},"expect",[909,3677,3678],{"class":923},"(err",[909,3680,1769],{"class":919},[909,3682,3683],{"class":923},"code)",[909,3685,1769],{"class":919},[909,3687,3688],{"class":966},"toBe",[909,3690,3691],{"class":923},"(billingErrors",[909,3693,1769],{"class":919},[909,3695,803],{"class":923},[909,3697,1769],{"class":919},[909,3699,3700],{"class":923},"code) ",[909,3702,3703],{"class":2279},"\u002F\u002F ✓ refactor-safe\n",[909,3705,3706,3708,3710,3712,3714,3716,3718,3720,3722,3724,3726,3729],{"class":911,"line":943},[909,3707,3675],{"class":966},[909,3709,3678],{"class":923},[909,3711,1769],{"class":919},[909,3713,3683],{"class":923},[909,3715,1769],{"class":919},[909,3717,3688],{"class":966},[909,3719,969],{"class":923},[909,3721,972],{"class":919},[909,3723,636],{"class":936},[909,3725,972],{"class":919},[909,3727,3728],{"class":923},")          ",[909,3730,3731],{"class":2279},"\u002F\u002F ✗ string literal\n",[756,3733,3735],{"id":3734},"api-reference","API reference",[764,3737,3738,3751],{},[767,3739,3740],{},[770,3741,3742,3745,3748],{},[773,3743,3744],{},"Symbol",[773,3746,3747],{},"Kind",[773,3749,3750],{},"Purpose",[782,3752,3753,3765,3776,3787,3816,3832,3846,3858,3870,3881],{},[770,3754,3755,3759,3762],{},[787,3756,3757],{},[577,3758,621],{},[787,3760,3761],{},"factory",[787,3763,3764],{},"Standalone single-error factory. No prefix derivation.",[770,3766,3767,3771,3773],{},[787,3768,3769],{},[577,3770,611],{},[787,3772,3761],{},[787,3774,3775],{},"Bundle of typed errors sharing a prefix.",[770,3777,3778,3782,3784],{},[787,3779,3780],{},[577,3781,625],{},[787,3783,3761],{},[787,3785,3786],{},"Standalone single-action audit factory.",[770,3788,3789,3793,3795],{},[787,3790,3791],{},[577,3792,615],{},[787,3794,3761],{},[787,3796,3797,3798,580,3801,580,3804,580,3807,580,3810,580,3813,1769],{},"Bundle of typed audit actions sharing a prefix. Each entry accepts ",[577,3799,3800],{},"target",[577,3802,3803],{},"description",[577,3805,3806],{},"severity",[577,3808,3809],{},"requiresChanges",[577,3811,3812],{},"requiresReason",[577,3814,3815],{},"redactPaths",[770,3817,3818,3823,3825],{},[787,3819,3820],{},[577,3821,3822],{},"AuditCatalogEntry",[787,3824,1854],{},[787,3826,3827,3828,3831],{},"Metadata shape for a single catalog entry (alias of ",[577,3829,3830],{},"AuditActionDefinition",").",[770,3833,3834,3839,3841],{},[787,3835,3836],{},[577,3837,3838],{},"AuditSeverity",[787,3840,1854],{},[787,3842,3843,1769],{},[577,3844,3845],{},"'low' | 'medium' | 'high' | 'critical'",[770,3847,3848,3852,3855],{},[787,3849,3850],{},[577,3851,3634],{},[787,3853,3854],{},"interface",[787,3856,3857],{},"Augmentable registry of error catalogs.",[770,3859,3860,3865,3867],{},[787,3861,3862],{},[577,3863,3864],{},"RegisteredAuditCatalogs",[787,3866,3854],{},[787,3868,3869],{},"Augmentable registry of audit catalogs.",[770,3871,3872,3876,3878],{},[787,3873,3874],{},[577,3875,3255],{},[787,3877,1854],{},[787,3879,3880],{},"Union of all registered error codes.",[770,3882,3883,3887,3889],{},[787,3884,3885],{},[577,3886,3259],{},[787,3888,1854],{},[787,3890,3891],{},"Union of all registered audit actions.",[573,3893,3894,3895,3897],{},"Everything ships from the main ",[577,3896,937],{}," entrypoint.",[756,3899,3901],{"id":3900},"next-steps","Next Steps",[603,3903,3904,3917,3930],{},[606,3905,3906,3908,3909,3912,3913,3916],{},[737,3907,51],{"href":52},": The full ",[577,3910,3911],{},"createError"," API and ",[577,3914,3915],{},"parseError"," reference.",[606,3918,3919,3922,3923,580,3926,3929],{},[737,3920,3921],{"href":397},"Audit → Recording",": All audit-emission APIs (",[577,3924,3925],{},"log.audit",[577,3927,3928],{},"withAudit",", etc.).",[606,3931,3932,3934],{},[737,3933,226],{"href":231},": Auto-managed per-request loggers and HTTP error serialization.",[3936,3937,3938],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":905,"searchDepth":943,"depth":943,"links":3940},[3941,3942,3948,3953,3958,3963,3964,3965],{"id":758,"depth":943,"text":759},{"id":874,"depth":943,"text":875,"children":3943},[3944,3945,3946,3947],{"id":882,"depth":950,"text":883},{"id":1297,"depth":950,"text":1298},{"id":1546,"depth":950,"text":1547},{"id":1758,"depth":950,"text":1759},{"id":1778,"depth":943,"text":1779,"children":3949},[3950,3951,3952],{"id":1788,"depth":950,"text":1791},{"id":2045,"depth":950,"text":2046},{"id":2352,"depth":950,"text":2353},{"id":2655,"depth":943,"text":2656,"children":3954},[3955,3956,3957],{"id":2659,"depth":950,"text":2660},{"id":2901,"depth":950,"text":2902},{"id":3075,"depth":950,"text":3076},{"id":3240,"depth":943,"text":3241,"children":3959},[3960,3961,3962],{"id":3263,"depth":950,"text":3264},{"id":3332,"depth":950,"text":3333},{"id":3477,"depth":950,"text":3478},{"id":3608,"depth":943,"text":3609},{"id":3734,"depth":943,"text":3735},{"id":3900,"depth":943,"text":3901},"Scale typed error and audit catalogs from one file to a monorepo: conventions, an npm packaging recipe, and type augmentation.","md",[3969,3971],{"label":51,"icon":54,"to":52,"color":2635,"variant":3970},"subtle",{"label":382,"icon":383,"to":388,"color":2635,"variant":3970},{},{"icon":79},{"title":76,"description":3966},"NUxZaMv3cQfVBsDotTV-75fNLWT_Vt6hbdPGF7RYNC0",[3977,3979],{"title":71,"path":72,"stem":73,"description":3978,"icon":74,"children":-1},"Add compile-time type safety to your wide events with TypeScript module augmentation. Prevent typos and ensure consistent field names across your codebase.",{"title":36,"path":86,"stem":87,"description":3980,"icon":44,"children":-1},"Use the evlog CLI to check logging patterns in supported source files, diagnose your setup, and control telemetry. Includes flags and exit codes.",1789048083444]