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