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