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