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