honertia 0.1.21 → 0.1.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1402,25 +1402,132 @@ registerErrorHandlers(app, {
1402
1402
  })
1403
1403
  ```
1404
1404
 
1405
- Your `Error` component receives:
1405
+ Your `Error` component receives structured error props that vary by environment:
1406
+
1407
+ **In Development** (`ENVIRONMENT=development`):
1408
+
1409
+ ```json
1410
+ {
1411
+ "status": 500,
1412
+ "code": "HON_CFG_100_DATABASE_NOT_CONFIGURED",
1413
+ "title": "Database Not Configured",
1414
+ "message": "DatabaseService is not configured. Add it to setupHonertia.",
1415
+ "hint": "Add database to setupHonertia config",
1416
+ "fixes": [{ "description": "Add database config", "confidence": "high" }],
1417
+ "source": { "file": "src/routes/projects.ts", "line": 42 },
1418
+ "docsUrl": "https://..."
1419
+ }
1420
+ ```
1421
+
1422
+ **In Production** (`ENVIRONMENT=production` or unset):
1423
+
1424
+ ```json
1425
+ {
1426
+ "status": 500,
1427
+ "code": "HON_CFG_100_DATABASE_NOT_CONFIGURED",
1428
+ "title": "Database Not Configured",
1429
+ "message": "An error occurred. Please try again later."
1430
+ }
1431
+ ```
1432
+
1433
+ In production, sensitive details (stack traces, source locations, hints, fixes) are automatically hidden while the error code and title remain visible for debugging reference.
1434
+
1435
+ **Example React Error Component:**
1406
1436
 
1407
1437
  ```tsx
1408
1438
  // src/pages/Error.tsx
1409
1439
  interface ErrorProps {
1410
- status: number // 404, 500, etc.
1411
- message: string // Error message (detailed in dev, generic in prod)
1440
+ status: number
1441
+ code: string
1442
+ title: string
1443
+ message: string
1444
+ hint?: string
1445
+ fixes?: Array<{ description: string; confidence: string }>
1446
+ source?: { file: string; line: number }
1447
+ docsUrl?: string
1412
1448
  }
1413
1449
 
1414
- export default function Error({ status, message }: ErrorProps) {
1450
+ export default function Error(props: ErrorProps) {
1451
+ const { status, title, message, hint, fixes, source, docsUrl } = props
1452
+
1415
1453
  return (
1416
1454
  <div className="error-page">
1417
1455
  <h1>{status}</h1>
1456
+ <h2>{title}</h2>
1418
1457
  <p>{message}</p>
1458
+
1459
+ {/* Only shown in dev (these props won't exist in prod) */}
1460
+ {hint && <p className="hint">{hint}</p>}
1461
+
1462
+ {source && (
1463
+ <code>{source.file}:{source.line}</code>
1464
+ )}
1465
+
1466
+ {fixes?.map((fix, i) => (
1467
+ <div key={i} className={`fix fix-${fix.confidence}`}>
1468
+ {fix.description}
1469
+ </div>
1470
+ ))}
1471
+
1472
+ {docsUrl && <a href={docsUrl}>View Documentation</a>}
1419
1473
  </div>
1420
1474
  )
1421
1475
  }
1422
1476
  ```
1423
1477
 
1478
+ ### Environment Detection
1479
+
1480
+ Honertia automatically detects development mode by checking environment variables:
1481
+
1482
+ ```typescript
1483
+ // Checks these in order:
1484
+ // 1. env.ENVIRONMENT === 'development'
1485
+ // 2. env.NODE_ENV === 'development'
1486
+ // 3. env.CF_PAGES_BRANCH !== undefined (Cloudflare Pages preview deployments)
1487
+ ```
1488
+
1489
+ To enable development mode, set the environment variable in your Hono app:
1490
+
1491
+ ```toml
1492
+ # wrangler.toml
1493
+ [vars]
1494
+ ENVIRONMENT = "development"
1495
+ ```
1496
+
1497
+ Or for Bun/Node:
1498
+
1499
+ ```typescript
1500
+ // Pass env via Bun.serve or test setup
1501
+ const app = new Hono<{ Bindings: { ENVIRONMENT: string } }>()
1502
+ ```
1503
+
1504
+ ### Safe Message Filtering
1505
+
1506
+ For sensitive error categories, production automatically shows generic messages instead of implementation details:
1507
+
1508
+ | Category | Production Message |
1509
+ |----------|-------------------|
1510
+ | `configuration` | "An error occurred. Please try again later." |
1511
+ | `internal` | "An error occurred. Please try again later." |
1512
+ | `database` | "An error occurred. Please try again later." |
1513
+ | `validation` | Original message (safe to show) |
1514
+ | `auth` | Original message (safe to show) |
1515
+
1516
+ This ensures that configuration mistakes, database errors, and internal implementation details are never leaked to end users in production.
1517
+
1518
+ ### Error Handler Options
1519
+
1520
+ The `registerErrorHandlers` function accepts these options:
1521
+
1522
+ ```typescript
1523
+ registerErrorHandlers(app, {
1524
+ component: 'Error', // React component name (required)
1525
+ showDevErrors: true, // Set false to always hide details (default: true)
1526
+ envKey: 'ENVIRONMENT', // Which env var to check (default: 'ENVIRONMENT')
1527
+ devValue: 'development', // What value means "dev mode" (default: 'development')
1528
+ })
1529
+ ```
1530
+
1424
1531
  ### Error Handling Flow
1425
1532
 
1426
1533
  ```
@@ -1 +1 @@
1
- {"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../../src/effect/binding.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../../src/effect/binding.ts"],"names":[],"mappings":"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"}
@@ -63,10 +63,7 @@ export const bound = (key) => Effect.gen(function* () {
63
63
  const models = yield* BoundModels;
64
64
  // Check if schema was not configured (sentinel value set by routing.ts)
65
65
  if (models.has('__schema_not_configured__')) {
66
- return yield* new RouteConfigurationError({
67
- message: `Route model binding requires schema configuration. Cannot resolve bound('${key}') without schema.`,
68
- hint: `Pass your schema to setupHonertia: setupHonertia({ honertia: { schema } })`
69
- });
66
+ return yield* RouteConfigurationError.schemaNotConfigured(key);
70
67
  }
71
68
  const model = models.get(key);
72
69
  if (!model) {
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/effect/bridge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAA;AAE9C,OAAO,KAAK,EAAE,OAAO,IAAI,WAAW,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAC1E,OAAO,EACL,eAAe,EACf,WAAW,EACX,eAAe,EACf,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,eAAe,EAQhB,MAAM,eAAe,CAAA;AAEtB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,GAAG,EAAE,cAAc,GAAG,KAAK;IACvE;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;IAC3E;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC;AAED;;GAEG;AACH,QAAA,MAAM,cAAc,eAA0B,CAAA;AAE9C;;GAEG;AACH,QAAA,MAAM,aAAa,eAAyB,CAAA;AA8B5C;;GAEG;AACH,OAAO,QAAQ,MAAM,CAAC;IACpB,UAAU,kBAAkB;QAC1B,CAAC,cAAc,CAAC,CAAC,EAAE,cAAc,CAAC,cAAc,CAC5C,eAAe,GACf,WAAW,GACX,eAAe,GACf,eAAe,GACf,cAAc,GACd,sBAAsB,EACxB,KAAK,CACN,CAAA;QACD,CAAC,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAC1C;CACF;AAsDD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,GAAG,EAAE,cAAc,GAAG,KAAK,EACrE,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EACjB,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAC,EAAE,cAAc,CAAC,GAC7C,KAAK,CAAC,KAAK,CACV,cAAc,GACd,sBAAsB,GACtB,eAAe,GACf,eAAe,GACf,WAAW,GACX,eAAe,GACf,eAAe,GACf,cAAc,EAChB,KAAK,EACL,KAAK,CACN,CAkEA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,GAAG,EAC5C,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GAChB,cAAc,CAAC,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,SAAS,CAEvD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,GAAG,EAAE,cAAc,GAAG,KAAK,EAChE,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAC,EAAE,cAAc,CAAC,GAC7C,iBAAiB,CAAC,CAAC,CAAC,CAoBtB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,GAAG,EAC3C,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAErC"}
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/effect/bridge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAA;AAG9C,OAAO,KAAK,EAAE,OAAO,IAAI,WAAW,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAC1E,OAAO,EACL,eAAe,EACf,WAAW,EACX,eAAe,EACf,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,eAAe,EAQhB,MAAM,eAAe,CAAA;AAEtB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,GAAG,EAAE,cAAc,GAAG,KAAK;IACvE;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;IAC3E;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC;AAED;;GAEG;AACH,QAAA,MAAM,cAAc,eAA0B,CAAA;AAE9C;;GAEG;AACH,QAAA,MAAM,aAAa,eAAyB,CAAA;AAsC5C;;GAEG;AACH,OAAO,QAAQ,MAAM,CAAC;IACpB,UAAU,kBAAkB;QAC1B,CAAC,cAAc,CAAC,CAAC,EAAE,cAAc,CAAC,cAAc,CAC5C,eAAe,GACf,WAAW,GACX,eAAe,GACf,eAAe,GACf,cAAc,GACd,sBAAsB,EACxB,KAAK,CACN,CAAA;QACD,CAAC,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAC1C;CACF;AAsDD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,GAAG,EAAE,cAAc,GAAG,KAAK,EACrE,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EACjB,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAC,EAAE,cAAc,CAAC,GAC7C,KAAK,CAAC,KAAK,CACV,cAAc,GACd,sBAAsB,GACtB,eAAe,GACf,eAAe,GACf,WAAW,GACX,eAAe,GACf,eAAe,GACf,cAAc,EAChB,KAAK,EACL,KAAK,CACN,CAoEA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,GAAG,EAC5C,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GAChB,cAAc,CAAC,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,SAAS,CAEvD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,GAAG,EAAE,cAAc,GAAG,KAAK,EAChE,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAC,EAAE,cAAc,CAAC,GAC7C,iBAAiB,CAAC,CAAC,CAAC,CAoBtB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,GAAG,EAC3C,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAErC"}
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { Layer, ManagedRuntime } from 'effect';
7
7
  import { HonertiaConfigurationError } from './errors.js';
8
+ import { ErrorCodes } from './error-catalog.js';
8
9
  import { DatabaseService, AuthService, AuthUserService, HonertiaService, RequestService, ResponseFactoryService, BindingsService, } from './services.js';
9
10
  /**
10
11
  * Symbol for storing Effect runtime in Hono context.
@@ -17,8 +18,13 @@ const EFFECT_SCHEMA = Symbol('effectSchema');
17
18
  /**
18
19
  * Creates a proxy that throws a helpful error when any property is accessed.
19
20
  * Used when a service (database, auth) is not configured but the user tries to use it.
21
+ *
22
+ * @param serviceName - The name of the unconfigured service.
23
+ * @param configPath - The configuration path hint (e.g., 'database: (c) => ...').
24
+ * @param example - An example of how to configure the service.
25
+ * @param errorCode - The specific error code to use.
20
26
  */
21
- function createUnconfiguredServiceProxy(serviceName, configPath, example) {
27
+ function createUnconfiguredServiceProxy(serviceName, configPath, example, errorCode) {
22
28
  const message = `${serviceName} is not configured. Add it to setupHonertia: setupHonertia({ honertia: { ${configPath} } })`;
23
29
  return new Proxy({}, {
24
30
  get(_, prop) {
@@ -29,6 +35,8 @@ function createUnconfiguredServiceProxy(serviceName, configPath, example) {
29
35
  throw new HonertiaConfigurationError({
30
36
  message,
31
37
  hint: `Example: ${example}`,
38
+ code: errorCode,
39
+ service: serviceName,
32
40
  });
33
41
  },
34
42
  });
@@ -94,11 +102,11 @@ export function buildContextLayer(c, config) {
94
102
  // Database layer - provide helpful error proxy if not configured
95
103
  const db = c.var?.db;
96
104
  const databaseLayer = Layer.succeed(DatabaseService, (db ??
97
- createUnconfiguredServiceProxy('DatabaseService', 'database: (c) => createDb(...)', 'database: (c) => drizzle(c.env.DB)')));
105
+ createUnconfiguredServiceProxy('DatabaseService', 'database: (c) => createDb(...)', 'database: (c) => drizzle(c.env.DB)', ErrorCodes.CFG_300_DATABASE_NOT_CONFIGURED)));
98
106
  // Auth layer - provide helpful error proxy if not configured
99
107
  const auth = c.var?.auth;
100
108
  const authLayer = Layer.succeed(AuthService, (auth ??
101
- createUnconfiguredServiceProxy('AuthService', 'auth: (c) => createAuth(...)', 'auth: (c) => betterAuth({ database: c.var.db, ... })')));
109
+ createUnconfiguredServiceProxy('AuthService', 'auth: (c) => createAuth(...)', 'auth: (c) => betterAuth({ database: c.var.db, ... })', ErrorCodes.CFG_301_AUTH_NOT_CONFIGURED)));
102
110
  let baseLayer = Layer.mergeAll(requestLayer, responseLayer, honertiaLayer, bindingsLayer, databaseLayer, authLayer);
103
111
  if (c.var?.authUser) {
104
112
  baseLayer = Layer.merge(baseLayer, Layer.succeed(AuthUserService, c.var.authUser));
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Error Catalog for Honertia
3
+ *
4
+ * Central registry of all error codes with fix generators.
5
+ * This is the single source of truth for error definitions.
6
+ */
7
+ import type { ErrorCategory, ErrorContext, ErrorDefinition, HonertiaStructuredError } from './error-types.js';
8
+ /**
9
+ * All Honertia error codes organized by category.
10
+ *
11
+ * Naming convention: HON_<CATEGORY>_<NUMBER>_<NAME>
12
+ *
13
+ * Categories:
14
+ * - VAL (001-099): Validation errors
15
+ * - AUTH (100-199): Authentication/authorization
16
+ * - RES (200-299): Resource errors
17
+ * - CFG (300-399): Configuration errors
18
+ * - HTTP (400-499): HTTP errors
19
+ * - DB (500-599): Database errors
20
+ * - RTE (600-699): Routing errors
21
+ * - SVC (700-799): Service errors
22
+ * - INT (800-899): Internal errors
23
+ */
24
+ export declare const ErrorCodes: {
25
+ readonly VAL_001_FIELD_REQUIRED: "HON_VAL_001_FIELD_REQUIRED";
26
+ readonly VAL_002_FIELD_INVALID: "HON_VAL_002_FIELD_INVALID";
27
+ readonly VAL_003_BODY_PARSE_FAILED: "HON_VAL_003_BODY_PARSE_FAILED";
28
+ readonly VAL_004_SCHEMA_MISMATCH: "HON_VAL_004_SCHEMA_MISMATCH";
29
+ readonly VAL_005_TYPE_COERCION_FAILED: "HON_VAL_005_TYPE_COERCION_FAILED";
30
+ readonly AUTH_100_UNAUTHENTICATED: "HON_AUTH_100_UNAUTHENTICATED";
31
+ readonly AUTH_101_SESSION_EXPIRED: "HON_AUTH_101_SESSION_EXPIRED";
32
+ readonly AUTH_102_FORBIDDEN: "HON_AUTH_102_FORBIDDEN";
33
+ readonly AUTH_103_INVALID_CREDENTIALS: "HON_AUTH_103_INVALID_CREDENTIALS";
34
+ readonly RES_200_NOT_FOUND: "HON_RES_200_NOT_FOUND";
35
+ readonly RES_201_ALREADY_EXISTS: "HON_RES_201_ALREADY_EXISTS";
36
+ readonly RES_202_GONE: "HON_RES_202_GONE";
37
+ readonly CFG_300_DATABASE_NOT_CONFIGURED: "HON_CFG_300_DATABASE_NOT_CONFIGURED";
38
+ readonly CFG_301_AUTH_NOT_CONFIGURED: "HON_CFG_301_AUTH_NOT_CONFIGURED";
39
+ readonly CFG_302_SCHEMA_NOT_CONFIGURED: "HON_CFG_302_SCHEMA_NOT_CONFIGURED";
40
+ readonly CFG_303_HONERTIA_NOT_CONFIGURED: "HON_CFG_303_HONERTIA_NOT_CONFIGURED";
41
+ readonly CFG_304_BINDINGS_NOT_CONFIGURED: "HON_CFG_304_BINDINGS_NOT_CONFIGURED";
42
+ readonly CFG_305_INVALID_CONFIG: "HON_CFG_305_INVALID_CONFIG";
43
+ readonly HTTP_400_BAD_REQUEST: "HON_HTTP_400_BAD_REQUEST";
44
+ readonly HTTP_429_RATE_LIMITED: "HON_HTTP_429_RATE_LIMITED";
45
+ readonly HTTP_500_INTERNAL_ERROR: "HON_HTTP_500_INTERNAL_ERROR";
46
+ readonly HTTP_502_BAD_GATEWAY: "HON_HTTP_502_BAD_GATEWAY";
47
+ readonly HTTP_503_SERVICE_UNAVAILABLE: "HON_HTTP_503_SERVICE_UNAVAILABLE";
48
+ readonly DB_500_CONNECTION_FAILED: "HON_DB_500_CONNECTION_FAILED";
49
+ readonly DB_501_QUERY_FAILED: "HON_DB_501_QUERY_FAILED";
50
+ readonly DB_502_CONSTRAINT_VIOLATION: "HON_DB_502_CONSTRAINT_VIOLATION";
51
+ readonly DB_503_TRANSACTION_FAILED: "HON_DB_503_TRANSACTION_FAILED";
52
+ readonly RTE_600_BINDING_NOT_FOUND: "HON_RTE_600_BINDING_NOT_FOUND";
53
+ readonly RTE_601_TABLE_NOT_FOUND: "HON_RTE_601_TABLE_NOT_FOUND";
54
+ readonly RTE_602_PARAM_VALIDATION: "HON_RTE_602_PARAM_VALIDATION";
55
+ readonly RTE_603_RELATION_NOT_FOUND: "HON_RTE_603_RELATION_NOT_FOUND";
56
+ readonly SVC_700_SERVICE_UNAVAILABLE: "HON_SVC_700_SERVICE_UNAVAILABLE";
57
+ readonly SVC_701_SERVICE_ERROR: "HON_SVC_701_SERVICE_ERROR";
58
+ readonly INT_800_UNEXPECTED: "HON_INT_800_UNEXPECTED";
59
+ readonly INT_801_EFFECT_DEFECT: "HON_INT_801_EFFECT_DEFECT";
60
+ };
61
+ export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
62
+ /**
63
+ * The error catalog with all error definitions.
64
+ */
65
+ export declare const ErrorCatalog: Record<ErrorCode, ErrorDefinition>;
66
+ /**
67
+ * Create a structured error from an error code and parameters.
68
+ *
69
+ * @param code - The error code (from ErrorCodes) or any string. Unknown codes fallback to INT_800_UNEXPECTED.
70
+ * @param params - Parameters to interpolate into the message template.
71
+ * @param context - The error context (route, request, handler info).
72
+ * @returns A fully structured error with fix suggestions.
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * const error = createStructuredError(
77
+ * ErrorCodes.VAL_001_FIELD_REQUIRED,
78
+ * { field: 'email' },
79
+ * captureErrorContext(c)
80
+ * )
81
+ * ```
82
+ */
83
+ export declare function createStructuredError(code: ErrorCode | string, params: Record<string, unknown>, context: ErrorContext): HonertiaStructuredError;
84
+ /**
85
+ * Get an error definition by code.
86
+ */
87
+ export declare function getErrorDefinition(code: ErrorCode): ErrorDefinition | undefined;
88
+ /**
89
+ * Get all error codes for a category.
90
+ */
91
+ export declare function getErrorsByCategory(category: ErrorCategory): ErrorCode[];
92
+ /**
93
+ * Determine the appropriate configuration error code from a service name or message.
94
+ *
95
+ * @param serviceName - The service name (e.g., 'DatabaseService').
96
+ * @param message - Optional message to check if service name doesn't match.
97
+ * @returns The appropriate error code, defaulting to CFG_305_INVALID_CONFIG.
98
+ */
99
+ export declare function getConfigErrorCode(serviceName?: string, message?: string): ErrorCode;
100
+ //# sourceMappingURL=error-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-catalog.d.ts","sourceRoot":"","sources":["../../src/effect/error-catalog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,eAAe,EAGf,uBAAuB,EACxB,MAAM,kBAAkB,CAAA;AAEzB;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqDb,CAAA;AAEV,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAA;AA8JpE;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,eAAe,CAmb3D,CAAA;AAOD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,SAAS,GAAG,MAAM,EACxB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,YAAY,GACpB,uBAAuB,CAwCzB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,GAAG,eAAe,GAAG,SAAS,CAE/E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,aAAa,GAAG,SAAS,EAAE,CAIxE;AAWD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM,GACf,SAAS,CAUX"}