honertia 0.1.15 → 0.1.17

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
@@ -1243,7 +1243,204 @@ return yield* forbidden('You cannot edit this project')
1243
1243
 
1244
1244
  ## Error Handling
1245
1245
 
1246
- Honertia provides typed errors:
1246
+ Honertia provides typed errors that integrate with Effect's error channel. Each error type has specific handling behavior designed for Inertia-style applications.
1247
+
1248
+ ### Built-in Error Types
1249
+
1250
+ | Error Type | HTTP Status | Handling Behavior |
1251
+ |------------|-------------|-------------------|
1252
+ | `ValidationError` | 422 / redirect | Re-renders form with field errors, or redirects back |
1253
+ | `UnauthorizedError` | 302/303 | Redirects to login page |
1254
+ | `NotFoundError` | 404 | Uses Hono's `notFound()` handler → renders via Honertia |
1255
+ | `ForbiddenError` | 403 | Returns JSON response (for API compatibility) |
1256
+ | `HttpError` | Custom | Returns JSON with custom status (developer-controlled) |
1257
+ | `RouteConfigurationError` | 500 | Throws to Hono's `onError` → renders error page |
1258
+ | Unexpected errors | 500 | Throws to Hono's `onError` → renders error page |
1259
+
1260
+ ### Error Type Details
1261
+
1262
+ #### `ValidationError`
1263
+
1264
+ Thrown when request validation fails. Automatically re-renders the form with field-level errors.
1265
+
1266
+ ```typescript
1267
+ import { ValidationError, validateRequest } from 'honertia/effect'
1268
+
1269
+ // Automatic: validateRequest throws ValidationError on failure
1270
+ const input = yield* validateRequest(schema, {
1271
+ errorComponent: 'Projects/Create', // Re-renders this component with errors
1272
+ })
1273
+
1274
+ // Manual: throw ValidationError directly
1275
+ yield* Effect.fail(new ValidationError({
1276
+ errors: { email: 'Invalid email format' },
1277
+ component: 'Auth/Register', // Optional: component to re-render
1278
+ }))
1279
+ ```
1280
+
1281
+ **Behavior:**
1282
+ - If request prefers JSON (API calls): returns `{ errors: {...} }` with 422 status
1283
+ - If `component` is set: re-renders that component with errors in props
1284
+ - Otherwise: redirects back to referer with errors in session
1285
+
1286
+ #### `UnauthorizedError`
1287
+
1288
+ Thrown when authentication is required but the user is not logged in.
1289
+
1290
+ ```typescript
1291
+ import { UnauthorizedError, authorize } from 'honertia/effect'
1292
+
1293
+ // Automatic: authorize() throws UnauthorizedError if no user
1294
+ const auth = yield* authorize()
1295
+
1296
+ // Manual: throw with custom redirect
1297
+ yield* Effect.fail(new UnauthorizedError({
1298
+ message: 'Please log in to continue',
1299
+ redirectTo: '/login', // Defaults to '/login'
1300
+ }))
1301
+ ```
1302
+
1303
+ **Behavior:** Redirects to the specified URL (302 for regular requests, 303 for Inertia requests).
1304
+
1305
+ #### `NotFoundError`
1306
+
1307
+ Thrown when a requested resource doesn't exist.
1308
+
1309
+ ```typescript
1310
+ import { NotFoundError, notFound } from 'honertia/effect'
1311
+
1312
+ // Helper function
1313
+ return yield* notFound('Project', projectId)
1314
+
1315
+ // Manual
1316
+ yield* Effect.fail(new NotFoundError({
1317
+ resource: 'Project',
1318
+ id: projectId,
1319
+ }))
1320
+ ```
1321
+
1322
+ **Behavior:** Triggers Hono's `notFound()` handler. If you've set up `registerErrorHandlers()`, this renders your error component with status 404.
1323
+
1324
+ #### `ForbiddenError`
1325
+
1326
+ Thrown when the user is authenticated but not authorized to perform an action.
1327
+
1328
+ ```typescript
1329
+ import { ForbiddenError, forbidden, authorize } from 'honertia/effect'
1330
+
1331
+ // Automatic: authorize() throws ForbiddenError if check fails
1332
+ const auth = yield* authorize((a) => a.user.role === 'admin')
1333
+
1334
+ // Helper function
1335
+ return yield* forbidden('You cannot edit this project')
1336
+
1337
+ // Manual
1338
+ yield* Effect.fail(new ForbiddenError({
1339
+ message: 'Admin access required',
1340
+ }))
1341
+ ```
1342
+
1343
+ **Behavior:** Returns JSON `{ message: "..." }` with 403 status. This is intentionally JSON for API compatibility.
1344
+
1345
+ #### `HttpError`
1346
+
1347
+ A generic error for custom HTTP responses. Use when you need precise control over the response.
1348
+
1349
+ ```typescript
1350
+ import { HttpError, httpError } from 'honertia/effect'
1351
+
1352
+ // Helper function
1353
+ return yield* httpError(429, 'Rate limited', { retryAfter: 60 })
1354
+
1355
+ // Manual
1356
+ yield* Effect.fail(new HttpError({
1357
+ status: 429,
1358
+ message: 'Too many requests',
1359
+ body: { retryAfter: 60 }, // Optional additional data
1360
+ }))
1361
+ ```
1362
+
1363
+ **Behavior:** Returns JSON `{ message: "...", ...body }` with the specified status code.
1364
+
1365
+ #### `RouteConfigurationError`
1366
+
1367
+ Thrown when there's a developer configuration error, such as using route model binding without providing a schema.
1368
+
1369
+ ```typescript
1370
+ import { RouteConfigurationError } from 'honertia/effect'
1371
+
1372
+ // This error is thrown automatically when:
1373
+ // - You use bound('project') but didn't pass schema to effectRoutes()
1374
+ // - Other route configuration mistakes
1375
+
1376
+ // You typically don't throw this manually
1377
+ ```
1378
+
1379
+ **Behavior:** Re-throws to Hono's `onError` handler, which renders your error component. The error message and hint are logged to the console for debugging.
1380
+
1381
+ ### Setting Up Error Pages
1382
+
1383
+ To render errors via Honertia instead of returning plain text/JSON, use `registerErrorHandlers`:
1384
+
1385
+ ```typescript
1386
+ import { registerErrorHandlers } from 'honertia'
1387
+
1388
+ // In your app setup
1389
+ registerErrorHandlers(app, {
1390
+ component: 'Error', // Your error page component
1391
+ showDevErrors: true, // Show detailed errors in development
1392
+ envKey: 'ENVIRONMENT', // Env var to check
1393
+ devValue: 'development', // Value that enables dev errors
1394
+ })
1395
+ ```
1396
+
1397
+ Your `Error` component receives:
1398
+
1399
+ ```tsx
1400
+ // src/pages/Error.tsx
1401
+ interface ErrorProps {
1402
+ status: number // 404, 500, etc.
1403
+ message: string // Error message (detailed in dev, generic in prod)
1404
+ }
1405
+
1406
+ export default function Error({ status, message }: ErrorProps) {
1407
+ return (
1408
+ <div className="error-page">
1409
+ <h1>{status}</h1>
1410
+ <p>{message}</p>
1411
+ </div>
1412
+ )
1413
+ }
1414
+ ```
1415
+
1416
+ ### Error Handling Flow
1417
+
1418
+ ```
1419
+ Effect Handler
1420
+
1421
+
1422
+ ┌─────────────────────────────────────────────────────────┐
1423
+ │ errorToResponse() │
1424
+ ├─────────────────────────────────────────────────────────┤
1425
+ │ ValidationError → Re-render form / redirect back │
1426
+ │ UnauthorizedError → Redirect to login │
1427
+ │ NotFoundError → c.notFound() → Hono notFound handler │
1428
+ │ ForbiddenError → JSON 403 │
1429
+ │ HttpError → JSON with custom status │
1430
+ │ Other errors → throw → Hono onError handler │
1431
+ └─────────────────────────────────────────────────────────┘
1432
+
1433
+ ▼ (for thrown errors)
1434
+ ┌─────────────────────────────────────────────────────────┐
1435
+ │ Hono onError handler │
1436
+ │ (from registerErrorHandlers) │
1437
+ ├─────────────────────────────────────────────────────────┤
1438
+ │ Renders error component via Honertia │
1439
+ │ Shows detailed message in dev, generic in prod │
1440
+ └─────────────────────────────────────────────────────────┘
1441
+ ```
1442
+
1443
+ ### Usage Examples
1247
1444
 
1248
1445
  ```typescript
1249
1446
  import {
@@ -1252,7 +1449,7 @@ import {
1252
1449
  NotFoundError,
1253
1450
  ForbiddenError,
1254
1451
  HttpError,
1255
- } from 'honertia'
1452
+ } from 'honertia/effect'
1256
1453
 
1257
1454
  // Validation errors automatically re-render with field errors
1258
1455
  const input = yield* validateRequest(schema, {
@@ -7,6 +7,7 @@
7
7
  import { Context, Effect } from 'effect';
8
8
  import type { Table } from 'drizzle-orm';
9
9
  import type { SchemaType } from './services.js';
10
+ import { RouteConfigurationError } from './errors.js';
10
11
  declare const BoundModelNotFound_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
11
12
  readonly _tag: "BoundModelNotFound";
12
13
  } & Readonly<A>;
@@ -79,7 +80,7 @@ export type BoundModel<K extends string> = SchemaType extends {
79
80
  * return inertia('Projects/Show', { project })
80
81
  * })
81
82
  */
82
- export declare const bound: <K extends string>(key: K) => Effect.Effect<BoundModel<K>, BoundModelNotFound, BoundModels>;
83
+ export declare const bound: <K extends string>(key: K) => Effect.Effect<BoundModel<K>, BoundModelNotFound | RouteConfigurationError, BoundModels>;
83
84
  /**
84
85
  * Pluralize a singular word.
85
86
  * Handles common English pluralization rules.
@@ -1 +1 @@
1
- {"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../../src/effect/binding.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAQ,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC9C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;;;;AAE/C;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,wBAAuC;IAC7E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB,CAAC;IACA,IAAI,OAAO,WAEV;CACF;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAA;IACb,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAa3D;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;;AAED;;;GAGG;AACH,qBAAa,WAAY,SAAQ,gBAG9B;CAAG;AAEN;;;GAGG;AACH,KAAK,SAAS,CAAC,CAAC,SAAS,MAAM,IAC7B,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,GAC/D,CAAC,SAAS,GAAG,MAAM,IAAI,GAAG,GAAG,GAAG,IAAI,KAAK,GACzC,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,GAAG,GAAG,CAAC,IAAI,GAC/E,GAAG,CAAC,GAAG,CAAA;AAET;;GAEG;AACH,UAAU,uBAAuB,CAAC,CAAC,SAAS,MAAM;IAChD,QAAQ,CAAC,OAAO,EAAE,gCAAgC,CAAC,oDAAoD,CAAA;IACvG,QAAQ,CAAC,MAAM,EAAE,wHAAwH,CAAA;CAC1I;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,MAAM,IAErC,UAAU,SAAS;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAClC,uBAAuB,CAAC,CAAC,CAAC,GAC1B,SAAS,CAAC,CAAC,CAAC,SAAS,MAAM,UAAU,GACnC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,GACpC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,GACxC,OAAO,GACT,CAAC,SAAS,MAAM,UAAU,GACxB,UAAU,CAAC,CAAC,CAAC,SAAS,KAAK,GACzB,UAAU,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,GAC7B,OAAO,GACT,OAAO,CAAA;AAEjB;;;;;;;;GAQG;AACH,eAAO,MAAM,KAAK,GAAI,CAAC,SAAS,MAAM,EACpC,KAAK,CAAC,KACL,MAAM,CAAC,MAAM,CACd,UAAU,CAAC,CAAC,CAAC,EACb,kBAAkB,EAClB,WAAW,CAST,CAAA;AAEJ;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAS9C;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAA;IAClB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,GACtB,YAAY,GAAG,IAAI,CA2CrB"}
1
+ {"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../../src/effect/binding.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@
5
5
  * Automatically resolves route parameters to database models.
6
6
  */
7
7
  import { Context, Data, Effect } from 'effect';
8
+ import { RouteConfigurationError } from './errors.js';
8
9
  /**
9
10
  * Error thrown when a bound model is not found in the BoundModels context.
10
11
  * This indicates a programming error - the binding key doesn't match any resolved model.
@@ -60,9 +61,16 @@ export class BoundModels extends Context.Tag('honertia/BoundModels')() {
60
61
  */
61
62
  export const bound = (key) => Effect.gen(function* () {
62
63
  const models = yield* BoundModels;
64
+ // Check if schema was not configured (sentinel value set by routing.ts)
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 effectRoutes: effectRoutes(app, { schema })`
69
+ });
70
+ }
63
71
  const model = models.get(key);
64
72
  if (!model) {
65
- return yield* Effect.fail(new BoundModelNotFound({ key }));
73
+ return yield* new BoundModelNotFound({ key });
66
74
  }
67
75
  return model;
68
76
  });
@@ -58,6 +58,18 @@ export declare class HttpError extends HttpError_base<{
58
58
  readonly body?: unknown;
59
59
  }> {
60
60
  }
61
+ declare const RouteConfigurationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
62
+ readonly _tag: "RouteConfigurationError";
63
+ } & Readonly<A>;
64
+ /**
65
+ * Route Configuration Error - Missing or invalid route configuration
66
+ * These are developer errors that should be fixed in code, not runtime errors.
67
+ */
68
+ export declare class RouteConfigurationError extends RouteConfigurationError_base<{
69
+ readonly message: string;
70
+ readonly hint?: string;
71
+ }> {
72
+ }
61
73
  declare const Redirect_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => Readonly<A> & {
62
74
  readonly _tag: "Redirect";
63
75
  };
@@ -73,6 +85,6 @@ export declare class Redirect extends Redirect_base<{
73
85
  /**
74
86
  * Union of all application errors
75
87
  */
76
- export type AppError = ValidationError | UnauthorizedError | NotFoundError | ForbiddenError | HttpError;
88
+ export type AppError = ValidationError | UnauthorizedError | NotFoundError | ForbiddenError | HttpError | RouteConfigurationError;
77
89
  export {};
78
90
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/effect/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;;;AAIH;;GAEG;AACH,qBAAa,eAAgB,SAAQ,qBAAoC;IACvE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B,CAAC;CAAG;;;;AAEL;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,uBAAsC;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAC;CAAG;;;;AAEL;;GAEG;AACH,qBAAa,aAAc,SAAQ,mBAAkC;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAC9B,CAAC;CAAG;;;;AAEL;;GAEG;AACH,qBAAa,cAAe,SAAQ,oBAAmC;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB,CAAC;CAAG;;;;AAEL;;GAEG;AACH,qBAAa,SAAU,SAAQ,eAA8B;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CACxB,CAAC;CAAG;;;;AAEL;;;GAGG;AACH,qBAAa,QAAS,SAAQ,cAA6B;IACzD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAA;CAC3B,CAAC;CAAG;AAEL;;GAEG;AACH,MAAM,MAAM,QAAQ,GAChB,eAAe,GACf,iBAAiB,GACjB,aAAa,GACb,cAAc,GACd,SAAS,CAAA"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/effect/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;;;AAIH;;GAEG;AACH,qBAAa,eAAgB,SAAQ,qBAAoC;IACvE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B,CAAC;CAAG;;;;AAEL;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,uBAAsC;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAC;CAAG;;;;AAEL;;GAEG;AACH,qBAAa,aAAc,SAAQ,mBAAkC;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAC9B,CAAC;CAAG;;;;AAEL;;GAEG;AACH,qBAAa,cAAe,SAAQ,oBAAmC;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB,CAAC;CAAG;;;;AAEL;;GAEG;AACH,qBAAa,SAAU,SAAQ,eAA8B;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CACxB,CAAC;CAAG;;;;AAEL;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,6BAA4C;IACvF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB,CAAC;CAAG;;;;AAEL;;;GAGG;AACH,qBAAa,QAAS,SAAQ,cAA6B;IACzD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAA;CAC3B,CAAC;CAAG;AAEL;;GAEG;AACH,MAAM,MAAM,QAAQ,GAChB,eAAe,GACf,iBAAiB,GACjB,aAAa,GACb,cAAc,GACd,SAAS,GACT,uBAAuB,CAAA"}
@@ -29,6 +29,12 @@ export class ForbiddenError extends Data.TaggedError('ForbiddenError') {
29
29
  */
30
30
  export class HttpError extends Data.TaggedError('HttpError') {
31
31
  }
32
+ /**
33
+ * Route Configuration Error - Missing or invalid route configuration
34
+ * These are developer errors that should be fixed in code, not runtime errors.
35
+ */
36
+ export class RouteConfigurationError extends Data.TaggedError('RouteConfigurationError') {
37
+ }
32
38
  /**
33
39
  * Redirect - Not an error, but uses same control flow
34
40
  * This is a tagged class (not error) for redirects
@@ -8,6 +8,11 @@ import type { Context as HonoContext, MiddlewareHandler, Env } from 'hono';
8
8
  import { Redirect, type AppError } from './errors.js';
9
9
  /**
10
10
  * Convert an Effect error to an HTTP response.
11
+ *
12
+ * Most errors are re-thrown so Hono's onError handler can render them
13
+ * via Honertia's error component. Only errors that need special handling
14
+ * (ValidationError for form re-rendering, UnauthorizedError for redirects)
15
+ * return responses directly.
11
16
  */
12
17
  export declare function errorToResponse<E extends Env>(error: AppError, c: HonoContext<E>): Promise<Response>;
13
18
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/effect/handler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAA+B,MAAM,QAAQ,CAAA;AAC5D,OAAO,KAAK,EAAE,OAAO,IAAI,WAAW,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAE1E,OAAO,EAML,QAAQ,EACR,KAAK,QAAQ,EACd,MAAM,aAAa,CAAA;AAGpB;;GAEG;AACH,wBAAsB,eAAe,CAAC,CAAC,SAAS,GAAG,EACjD,KAAK,EAAE,QAAQ,EACf,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GAChB,OAAO,CAAC,QAAQ,CAAC,CA6CnB;AAgBD;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC,EAAE,GAAG,SAAS,QAAQ,EAClE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,GAAG,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,GACjD,iBAAiB,CAAC,CAAC,CAAC,CAoBtB;AAsCD;;GAEG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC,EAAE,GAAG,SAAS,QAAQ,EAC3D,EAAE,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,GAAG,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,GACnD,iBAAiB,CAAC,CAAC,CAAC,CAEtB;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,sBAAgB,CAAA"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/effect/handler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAA+B,MAAM,QAAQ,CAAA;AAC5D,OAAO,KAAK,EAAE,OAAO,IAAI,WAAW,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAE1E,OAAO,EAML,QAAQ,EACR,KAAK,QAAQ,EACd,MAAM,aAAa,CAAA;AAuBpB;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,CAAC,SAAS,GAAG,EACjD,KAAK,EAAE,QAAQ,EACf,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GAChB,OAAO,CAAC,QAAQ,CAAC,CAiDnB;AAgBD;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC,EAAE,GAAG,SAAS,QAAQ,EAClE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,GAAG,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,GACjD,iBAAiB,CAAC,CAAC,CAAC,CAoBtB;AAgDD;;GAEG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC,EAAE,GAAG,SAAS,QAAQ,EAC3D,EAAE,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,GAAG,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,GACnD,iBAAiB,CAAC,CAAC,CAAC,CAEtB;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,sBAAgB,CAAA"}
@@ -5,11 +5,36 @@
5
5
  */
6
6
  import { Effect, Exit, Cause, ManagedRuntime } from 'effect';
7
7
  import { getEffectRuntime, buildContextLayer } from './bridge.js';
8
- import { ValidationError, UnauthorizedError, NotFoundError, ForbiddenError, HttpError, Redirect, } from './errors.js';
8
+ import { ValidationError, UnauthorizedError, NotFoundError, HttpError, RouteConfigurationError, Redirect, } from './errors.js';
9
+ /**
10
+ * Convert an AppError to a throwable Error for Hono's onError handler.
11
+ * Preserves error metadata like status codes and hints.
12
+ */
13
+ function toThrowableError(error) {
14
+ const err = new Error(error.message);
15
+ err.name = error._tag;
16
+ // Preserve status for HttpError
17
+ if (error instanceof HttpError) {
18
+ ;
19
+ err.status = error.status;
20
+ }
21
+ // Preserve hint for RouteConfigurationError
22
+ if (error instanceof RouteConfigurationError && error.hint) {
23
+ ;
24
+ err.hint = error.hint;
25
+ }
26
+ return err;
27
+ }
9
28
  /**
10
29
  * Convert an Effect error to an HTTP response.
30
+ *
31
+ * Most errors are re-thrown so Hono's onError handler can render them
32
+ * via Honertia's error component. Only errors that need special handling
33
+ * (ValidationError for form re-rendering, UnauthorizedError for redirects)
34
+ * return responses directly.
11
35
  */
12
36
  export async function errorToResponse(error, c) {
37
+ // ValidationError: re-render form with errors or redirect back
13
38
  if (error instanceof ValidationError) {
14
39
  const isInertia = c.req.header('X-Inertia') === 'true';
15
40
  const prefersJson = c.req.header('Accept')?.includes('application/json') ||
@@ -28,23 +53,26 @@ export async function errorToResponse(error, c) {
28
53
  c.var?.honertia?.setErrors(error.errors);
29
54
  return c.redirect(referer, 303);
30
55
  }
56
+ // UnauthorizedError: redirect to login
31
57
  if (error instanceof UnauthorizedError) {
32
58
  const isInertia = c.req.header('X-Inertia') === 'true';
33
59
  const redirectTo = error.redirectTo ?? '/login';
34
60
  return c.redirect(redirectTo, isInertia ? 303 : 302);
35
61
  }
36
- if (error instanceof ForbiddenError) {
37
- return c.json({ message: error.message }, 403);
38
- }
62
+ // NotFoundError: use Hono's notFound handler (renders via Honertia if configured)
39
63
  if (error instanceof NotFoundError) {
40
64
  return c.notFound();
41
65
  }
66
+ // ForbiddenError: return 403 JSON (useful for API routes)
67
+ if ('_tag' in error && error._tag === 'ForbiddenError') {
68
+ return c.json({ message: error.message }, 403);
69
+ }
70
+ // HttpError: return custom status JSON (gives developers control over HTTP responses)
42
71
  if (error instanceof HttpError) {
43
72
  return c.json({ message: error.message, ...error.body }, error.status);
44
73
  }
45
- // Unknown error
46
- console.error('Unhandled error:', error);
47
- return c.json({ message: 'Internal server error' }, 500);
74
+ // All other errors (RouteConfigurationError, etc.): throw to Hono's onError handler
75
+ throw toThrowableError(error);
48
76
  }
49
77
  /**
50
78
  * Handle a Redirect value (which is not an error).
@@ -82,6 +110,9 @@ export function effectHandler(effect) {
82
110
  }
83
111
  /**
84
112
  * Handle an Effect exit value.
113
+ *
114
+ * Failures are converted to responses via errorToResponse.
115
+ * Defects (unexpected errors) are re-thrown for Hono's onError handler.
85
116
  */
86
117
  async function handleExit(exit, c) {
87
118
  if (Exit.isSuccess(exit)) {
@@ -91,7 +122,7 @@ async function handleExit(exit, c) {
91
122
  }
92
123
  return value;
93
124
  }
94
- // Handle failure
125
+ // Handle typed failures
95
126
  const cause = exit.cause;
96
127
  if (Cause.isFailure(cause)) {
97
128
  const error = Cause.failureOption(cause);
@@ -99,14 +130,21 @@ async function handleExit(exit, c) {
99
130
  return await errorToResponse(error.value, c);
100
131
  }
101
132
  }
102
- // Handle defects (unexpected errors)
133
+ // Handle defects (unexpected errors) - throw to Hono's onError handler
103
134
  if (Cause.isDie(cause)) {
104
135
  const defect = Cause.dieOption(cause);
105
136
  if (defect._tag === 'Some') {
106
- console.error('Effect defect:', defect.value);
137
+ const err = defect.value;
138
+ // If it's already an Error, throw it directly
139
+ if (err instanceof Error) {
140
+ throw err;
141
+ }
142
+ // Otherwise wrap it
143
+ throw new Error(String(err));
107
144
  }
108
145
  }
109
- return c.json({ message: 'Internal server error' }, 500);
146
+ // Fallback: throw generic error for Hono's onError handler
147
+ throw new Error('Unknown effect failure');
110
148
  }
111
149
  /**
112
150
  * Create a handler from a function that returns an Effect.
@@ -4,7 +4,7 @@
4
4
  * Re-exports all Effect-related functionality.
5
5
  */
6
6
  export { DatabaseService, AuthService, AuthUserService, HonertiaService, RequestService, ResponseFactoryService, type AuthUser, type HonertiaRenderer, type RequestContext, type ResponseFactory, type HonertiaDatabaseType, type HonertiaAuthType, type DatabaseType, type SchemaType, type AuthType, } from './services.js';
7
- export { ValidationError, UnauthorizedError, NotFoundError, ForbiddenError, HttpError, Redirect, type AppError, } from './errors.js';
7
+ export { ValidationError, UnauthorizedError, NotFoundError, ForbiddenError, HttpError, RouteConfigurationError, Redirect, type AppError, } from './errors.js';
8
8
  export * from './schema.js';
9
9
  export { getValidationData, formatSchemaErrors, validate, validateRequest, asValidated, asTrusted, type Validated, type Trusted, } from './validation.js';
10
10
  export { effectBridge, buildContextLayer, getEffectRuntime, type EffectBridgeConfig, } from './bridge.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/effect/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,eAAe,EACf,WAAW,EACX,eAAe,EACf,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,QAAQ,GACd,MAAM,eAAe,CAAA;AAGtB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,SAAS,EACT,QAAQ,EACR,KAAK,QAAQ,GACd,MAAM,aAAa,CAAA;AAGpB,cAAc,aAAa,CAAA;AAG3B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,eAAe,EACf,WAAW,EACX,SAAS,EACT,KAAK,SAAS,EACd,KAAK,OAAO,GACb,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,aAAa,EACb,MAAM,EACN,MAAM,EACN,eAAe,GAChB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,MAAM,EACN,SAAS,EACT,UAAU,EACV,aAAa,EACb,KAAK,MAAM,GACZ,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,QAAQ,EACR,MAAM,EACN,gBAAgB,EAChB,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,SAAS,EACT,WAAW,EACX,YAAY,EACZ,KAAK,GACN,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,kBAAkB,GACxB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,KAAK,EACL,SAAS,EACT,aAAa,EACb,UAAU,EACV,KAAK,aAAa,EAClB,KAAK,UAAU,GAChB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,WAAW,EACX,YAAY,EACZ,SAAS,EACT,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,QAAQ,EACR,KAAK,gBAAgB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC5B,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/effect/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,eAAe,EACf,WAAW,EACX,eAAe,EACf,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,QAAQ,GACd,MAAM,eAAe,CAAA;AAGtB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,SAAS,EACT,uBAAuB,EACvB,QAAQ,EACR,KAAK,QAAQ,GACd,MAAM,aAAa,CAAA;AAGpB,cAAc,aAAa,CAAA;AAG3B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,eAAe,EACf,WAAW,EACX,SAAS,EACT,KAAK,SAAS,EACd,KAAK,OAAO,GACb,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,aAAa,EACb,MAAM,EACN,MAAM,EACN,eAAe,GAChB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,MAAM,EACN,SAAS,EACT,UAAU,EACV,aAAa,EACb,KAAK,MAAM,GACZ,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,QAAQ,EACR,MAAM,EACN,gBAAgB,EAChB,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,SAAS,EACT,WAAW,EACX,YAAY,EACZ,KAAK,GACN,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,kBAAkB,GACxB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,KAAK,EACL,SAAS,EACT,aAAa,EACb,UAAU,EACV,KAAK,aAAa,EAClB,KAAK,UAAU,GAChB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,WAAW,EACX,YAAY,EACZ,SAAS,EACT,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,QAAQ,EACR,KAAK,gBAAgB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC5B,MAAM,WAAW,CAAA"}
@@ -6,7 +6,7 @@
6
6
  // Services
7
7
  export { DatabaseService, AuthService, AuthUserService, HonertiaService, RequestService, ResponseFactoryService, } from './services.js';
8
8
  // Errors
9
- export { ValidationError, UnauthorizedError, NotFoundError, ForbiddenError, HttpError, Redirect, } from './errors.js';
9
+ export { ValidationError, UnauthorizedError, NotFoundError, ForbiddenError, HttpError, RouteConfigurationError, Redirect, } from './errors.js';
10
10
  // Schema Validators
11
11
  export * from './schema.js';
12
12
  // Validation Helpers
@@ -1 +1 @@
1
- {"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/effect/routing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/effect/routing.ts"],"names":[],"mappings":"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"}
@@ -136,8 +136,14 @@ export class EffectRouteBuilder {
136
136
  }
137
137
  boundModelsLayer = Layer.succeed(BoundModels, result);
138
138
  }
139
+ else if (bindings.length > 0 && !bridgeConfig?.schema) {
140
+ // Bindings exist but no schema - provide a map that signals this for better errors
141
+ const unconfiguredMap = new Map();
142
+ unconfiguredMap.set('__schema_not_configured__', true);
143
+ boundModelsLayer = Layer.succeed(BoundModels, unconfiguredMap);
144
+ }
139
145
  else {
140
- // Empty bound models for routes without bindings
146
+ // No bindings - empty bound models
141
147
  boundModelsLayer = Layer.succeed(BoundModels, new Map());
142
148
  }
143
149
  // Combine with provided layers
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "honertia",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "Inertia.js-style server-driven SPA adapter for Hono",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",