@rexeus/typeweaver-hono 0.7.0 → 0.8.0
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 +33 -22
- package/dist/lib/TypeweaverHono.ts +165 -49
- package/dist/templates/HonoRouter.ejs +2 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -51,28 +51,24 @@ Implement your handlers and mount the generated router in a Hono app.
|
|
|
51
51
|
// api/user-handlers.ts
|
|
52
52
|
import type { Context } from "hono";
|
|
53
53
|
import { HttpStatusCode } from "@rexeus/typeweaver-core";
|
|
54
|
-
import type { IGetUserRequest, GetUserResponse
|
|
55
|
-
import {
|
|
54
|
+
import type { HonoUserApiHandler, IGetUserRequest, GetUserResponse } from "./generated";
|
|
55
|
+
import { createUserNotFoundErrorResponse, createGetUserSuccessResponse } from "./generated";
|
|
56
56
|
|
|
57
57
|
export class UserHandlers implements HonoUserApiHandler {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
// Will be properly handled by the generated router and returned as a 404 response
|
|
63
|
-
return new UserNotFoundErrorResponse({
|
|
64
|
-
statusCode: HttpStatusCode.NotFound,
|
|
65
|
-
header: { "Content-Type": "application/json" },
|
|
66
|
-
body: { message: "User not found" },
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return new GetUserSuccessResponse({
|
|
71
|
-
statusCode: HttpStatusCode.OK,
|
|
58
|
+
async handleGetUserRequest(request: IGetUserRequest, context: Context): Promise<GetUserResponse> {
|
|
59
|
+
const user = await db.findUser(request.param.userId);
|
|
60
|
+
if (!user) {
|
|
61
|
+
return createUserNotFoundErrorResponse({
|
|
72
62
|
header: { "Content-Type": "application/json" },
|
|
73
|
-
body: {
|
|
63
|
+
body: { message: "User not found" },
|
|
74
64
|
});
|
|
75
|
-
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return createGetUserSuccessResponse({
|
|
68
|
+
header: { "Content-Type": "application/json" },
|
|
69
|
+
body: { id: request.param.userId, name: "Jane", email: "jane@example.com" },
|
|
70
|
+
});
|
|
71
|
+
}
|
|
76
72
|
// Implement other operation handlers: handleCreateUserRequest, ...
|
|
77
73
|
}
|
|
78
74
|
```
|
|
@@ -91,8 +87,10 @@ const userHandlers = new UserHandlers();
|
|
|
91
87
|
const userRouter = new UserHono({
|
|
92
88
|
requestHandlers: userHandlers,
|
|
93
89
|
validateRequests: true, // default, validates requests
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
validateResponses: true, // default, validates responses and strips extra fields
|
|
91
|
+
handleRequestValidationErrors: true, // default: returns 400 with issues
|
|
92
|
+
handleResponseValidationErrors: true, // default: returns 500
|
|
93
|
+
handleHttpResponseErrors: true, // default: returns thrown typed HTTP responses as-is
|
|
96
94
|
handleUnknownErrors: true, // default: returns 500
|
|
97
95
|
});
|
|
98
96
|
|
|
@@ -110,14 +108,27 @@ serve({ fetch: app.fetch, port: 3000 }, () => {
|
|
|
110
108
|
|
|
111
109
|
- `requestHandlers`: object implementing the generated `Hono<ResourceName>ApiHandler` type
|
|
112
110
|
- `validateRequests` (default: `true`): enable/disable request validation
|
|
113
|
-
- `
|
|
111
|
+
- `validateResponses` (default: `true`): enable/disable response validation. When enabled, responses
|
|
112
|
+
are validated against the operation's schema and extra body fields are stripped before sending.
|
|
113
|
+
- `handleRequestValidationErrors`: `true` | `false` |
|
|
114
|
+
`(err, c) => IHttpResponse | Promise<IHttpResponse>`
|
|
114
115
|
- If `true` (default), returns `400 Bad Request` with validation issues in the body
|
|
115
116
|
- If `false`, disables this handler (errors fall through to the unknown error handler)
|
|
116
117
|
- If function, calls the function with the error and context, expects an `IHttpResponse` to
|
|
117
118
|
return, so you can customize the response in the way you want
|
|
119
|
+
- `handleResponseValidationErrors`: `true` | `false` |
|
|
120
|
+
`(err, response, c) => IHttpResponse | Promise<IHttpResponse>`
|
|
121
|
+
- If `true` (default), returns `500 Internal Server Error`
|
|
122
|
+
- If `false`, disables response validation error handling — the invalid response is returned
|
|
123
|
+
as-is. Validation still runs (and strips extra fields on valid responses), but invalid responses
|
|
124
|
+
pass through unchanged. Useful when you want field stripping without blocking invalid responses.
|
|
125
|
+
- If function, calls the function with the `ResponseValidationError`, the original (invalid)
|
|
126
|
+
response, and the Hono context. The function should return an `IHttpResponse`. If the custom
|
|
127
|
+
handler throws, the original response is returned as a fallback.
|
|
118
128
|
- `handleHttpResponseErrors`: `true` | `false` |
|
|
119
129
|
`(err, c) => IHttpResponse | Promise<IHttpResponse>`
|
|
120
|
-
- If `true` (default), returns thrown `
|
|
130
|
+
- If `true` (default), returns thrown typed HTTP responses (`ITypedHttpResponse`) as-is, they will
|
|
131
|
+
be sent as the response
|
|
121
132
|
- If `false`, disables this handler (errors fall through to the unknown error handler)
|
|
122
133
|
- If function, calls the function with the error and context, expects an `IHttpResponse` to
|
|
123
134
|
return, so you can customize the response in the way you want
|
|
@@ -5,11 +5,17 @@
|
|
|
5
5
|
* @generated by @rexeus/typeweaver
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
isTypedHttpResponse,
|
|
10
|
+
RequestValidationError,
|
|
11
|
+
} from "@rexeus/typeweaver-core";
|
|
9
12
|
import type {
|
|
10
13
|
IHttpRequest,
|
|
11
14
|
IHttpResponse,
|
|
12
15
|
IRequestValidator,
|
|
16
|
+
IResponseValidator,
|
|
17
|
+
ITypedHttpResponse,
|
|
18
|
+
ResponseValidationError,
|
|
13
19
|
} from "@rexeus/typeweaver-core";
|
|
14
20
|
import { Hono } from "hono";
|
|
15
21
|
import { HonoAdapter } from "./HonoAdapter";
|
|
@@ -25,7 +31,7 @@ import type { BlankEnv, BlankSchema, Env, Schema } from "hono/types";
|
|
|
25
31
|
* @returns The HTTP response to send to the client
|
|
26
32
|
*/
|
|
27
33
|
export type HonoHttpResponseErrorHandler = (
|
|
28
|
-
error:
|
|
34
|
+
error: ITypedHttpResponse,
|
|
29
35
|
context: Context
|
|
30
36
|
) => Promise<IHttpResponse> | IHttpResponse;
|
|
31
37
|
|
|
@@ -35,7 +41,7 @@ export type HonoHttpResponseErrorHandler = (
|
|
|
35
41
|
* @param context - The Hono context for the current request
|
|
36
42
|
* @returns The HTTP response to send to the client
|
|
37
43
|
*/
|
|
38
|
-
export type
|
|
44
|
+
export type HonoRequestValidationErrorHandler = (
|
|
39
45
|
error: RequestValidationError,
|
|
40
46
|
context: Context
|
|
41
47
|
) => Promise<IHttpResponse> | IHttpResponse;
|
|
@@ -51,6 +57,20 @@ export type HonoUnknownErrorHandler = (
|
|
|
51
57
|
context: Context
|
|
52
58
|
) => Promise<IHttpResponse> | IHttpResponse;
|
|
53
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Handles response validation errors.
|
|
62
|
+
* Called when a handler returns a response that does not match the expected schema.
|
|
63
|
+
* @param error - The response validation error with schema mismatch details
|
|
64
|
+
* @param response - The original (invalid) response from the handler
|
|
65
|
+
* @param context - The Hono context for the current request
|
|
66
|
+
* @returns The HTTP response to send to the client (typically a 500)
|
|
67
|
+
*/
|
|
68
|
+
export type HonoResponseValidationErrorHandler = (
|
|
69
|
+
error: ResponseValidationError,
|
|
70
|
+
response: IHttpResponse,
|
|
71
|
+
context: Context
|
|
72
|
+
) => Promise<IHttpResponse> | IHttpResponse;
|
|
73
|
+
|
|
54
74
|
/**
|
|
55
75
|
* Configuration options for TypeweaverHono routers.
|
|
56
76
|
* @template RequestHandlers - Type containing all request handler methods
|
|
@@ -64,32 +84,52 @@ export type TypeweaverHonoOptions<
|
|
|
64
84
|
* Request handler methods for each operation.
|
|
65
85
|
* Each handler receives a request (validated if `validateRequests` is true) and Hono context.
|
|
66
86
|
*/
|
|
67
|
-
requestHandlers: RequestHandlers;
|
|
87
|
+
readonly requestHandlers: RequestHandlers;
|
|
68
88
|
|
|
69
89
|
/**
|
|
70
90
|
* Enable request validation using generated validators.
|
|
71
91
|
* When false, requests are passed through without validation.
|
|
72
92
|
* @default true
|
|
73
93
|
*/
|
|
74
|
-
validateRequests?: boolean;
|
|
94
|
+
readonly validateRequests?: boolean;
|
|
75
95
|
|
|
76
96
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* - `false`: Let errors bubble up to Hono
|
|
80
|
-
* - `function`: Use custom error handler
|
|
97
|
+
* Enable response validation using generated validators.
|
|
98
|
+
* When true, responses are validated and stripped of extra fields before sending.
|
|
81
99
|
* @default true
|
|
82
100
|
*/
|
|
83
|
-
|
|
101
|
+
readonly validateResponses?: boolean;
|
|
84
102
|
|
|
85
103
|
/**
|
|
86
104
|
* Configure handling of request validation errors.
|
|
87
105
|
* - `true`: Use default handler (400 with error details)
|
|
88
106
|
* - `false`: Let errors bubble up to Hono
|
|
107
|
+
* - `function`: Use custom request validation error handler
|
|
108
|
+
* @default true
|
|
109
|
+
*/
|
|
110
|
+
readonly handleRequestValidationErrors?:
|
|
111
|
+
| HonoRequestValidationErrorHandler
|
|
112
|
+
| boolean;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Configure handling of response validation errors.
|
|
116
|
+
* - `true`: Use default handler (500 Internal Server Error)
|
|
117
|
+
* - `false`: Disable response validation error handling (return response as-is)
|
|
118
|
+
* - `function`: Use custom response validation error handler
|
|
119
|
+
* @default true
|
|
120
|
+
*/
|
|
121
|
+
readonly handleResponseValidationErrors?:
|
|
122
|
+
| HonoResponseValidationErrorHandler
|
|
123
|
+
| boolean;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Configure handling of HttpResponse errors thrown by handlers.
|
|
127
|
+
* - `true`: Use default handler (returns the error as-is)
|
|
128
|
+
* - `false`: Let errors bubble up to Hono
|
|
89
129
|
* - `function`: Use custom error handler
|
|
90
130
|
* @default true
|
|
91
131
|
*/
|
|
92
|
-
|
|
132
|
+
readonly handleHttpResponseErrors?: HonoHttpResponseErrorHandler | boolean;
|
|
93
133
|
|
|
94
134
|
/**
|
|
95
135
|
* Configure handling of unknown errors.
|
|
@@ -98,7 +138,7 @@ export type TypeweaverHonoOptions<
|
|
|
98
138
|
* - `function`: Use custom error handler
|
|
99
139
|
* @default true
|
|
100
140
|
*/
|
|
101
|
-
handleUnknownErrors?: HonoUnknownErrorHandler | boolean;
|
|
141
|
+
readonly handleUnknownErrors?: HonoUnknownErrorHandler | boolean;
|
|
102
142
|
};
|
|
103
143
|
|
|
104
144
|
/**
|
|
@@ -134,11 +174,15 @@ export abstract class TypeweaverHono<
|
|
|
134
174
|
* Resolved configuration for validation and error handling.
|
|
135
175
|
*/
|
|
136
176
|
private readonly config: {
|
|
137
|
-
validateRequests: boolean;
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
177
|
+
readonly validateRequests: boolean;
|
|
178
|
+
readonly validateResponses: boolean;
|
|
179
|
+
readonly errorHandlers: {
|
|
180
|
+
readonly requestValidation: HonoRequestValidationErrorHandler | undefined;
|
|
181
|
+
readonly responseValidation:
|
|
182
|
+
| HonoResponseValidationErrorHandler
|
|
183
|
+
| undefined;
|
|
184
|
+
readonly httpResponse: HonoHttpResponseErrorHandler | undefined;
|
|
185
|
+
readonly unknown: HonoUnknownErrorHandler | undefined;
|
|
142
186
|
};
|
|
143
187
|
};
|
|
144
188
|
|
|
@@ -146,7 +190,7 @@ export abstract class TypeweaverHono<
|
|
|
146
190
|
* Default error handlers used when custom handlers are not provided.
|
|
147
191
|
*/
|
|
148
192
|
private readonly defaultHandlers = {
|
|
149
|
-
|
|
193
|
+
requestValidation: (error: RequestValidationError): IHttpResponse => ({
|
|
150
194
|
statusCode: 400,
|
|
151
195
|
body: {
|
|
152
196
|
code: "VALIDATION_ERROR",
|
|
@@ -160,13 +204,21 @@ export abstract class TypeweaverHono<
|
|
|
160
204
|
},
|
|
161
205
|
}),
|
|
162
206
|
|
|
163
|
-
|
|
207
|
+
responseValidation: (): IHttpResponse => ({
|
|
208
|
+
statusCode: 500,
|
|
209
|
+
body: {
|
|
210
|
+
code: "INTERNAL_SERVER_ERROR",
|
|
211
|
+
message: "An unexpected error occurred",
|
|
212
|
+
},
|
|
213
|
+
}),
|
|
214
|
+
|
|
215
|
+
httpResponse: (error: ITypedHttpResponse): IHttpResponse => error,
|
|
164
216
|
|
|
165
217
|
unknown: (): IHttpResponse => ({
|
|
166
218
|
statusCode: 500,
|
|
167
219
|
body: {
|
|
168
220
|
code: "INTERNAL_SERVER_ERROR",
|
|
169
|
-
message: "An unexpected error occurred
|
|
221
|
+
message: "An unexpected error occurred",
|
|
170
222
|
},
|
|
171
223
|
}),
|
|
172
224
|
};
|
|
@@ -178,15 +230,17 @@ export abstract class TypeweaverHono<
|
|
|
178
230
|
* @param options.requestHandlers - Object containing all request handler methods
|
|
179
231
|
* @param options.validateRequests - Whether to validate requests (default: true)
|
|
180
232
|
* @param options.handleHttpResponseErrors - Handler or boolean for HTTP errors (default: true)
|
|
181
|
-
* @param options.
|
|
233
|
+
* @param options.handleRequestValidationErrors - Handler or boolean for request validation errors (default: true)
|
|
182
234
|
* @param options.handleUnknownErrors - Handler or boolean for unknown errors (default: true)
|
|
183
235
|
*/
|
|
184
236
|
public constructor(options: TypeweaverHonoOptions<RequestHandlers, HonoEnv>) {
|
|
185
237
|
const {
|
|
186
238
|
requestHandlers,
|
|
187
239
|
validateRequests = true,
|
|
240
|
+
validateResponses = true,
|
|
188
241
|
handleHttpResponseErrors,
|
|
189
|
-
|
|
242
|
+
handleRequestValidationErrors,
|
|
243
|
+
handleResponseValidationErrors,
|
|
190
244
|
handleUnknownErrors,
|
|
191
245
|
...honoOptions
|
|
192
246
|
} = options;
|
|
@@ -198,9 +252,15 @@ export abstract class TypeweaverHono<
|
|
|
198
252
|
// Resolve configuration
|
|
199
253
|
this.config = {
|
|
200
254
|
validateRequests,
|
|
255
|
+
validateResponses,
|
|
201
256
|
errorHandlers: {
|
|
202
|
-
|
|
203
|
-
|
|
257
|
+
requestValidation: this.resolveErrorHandler(
|
|
258
|
+
handleRequestValidationErrors,
|
|
259
|
+
error => this.defaultHandlers.requestValidation(error)
|
|
260
|
+
),
|
|
261
|
+
responseValidation: this.resolveErrorHandler(
|
|
262
|
+
handleResponseValidationErrors,
|
|
263
|
+
(_error, _response) => this.defaultHandlers.responseValidation()
|
|
204
264
|
),
|
|
205
265
|
httpResponse: this.resolveErrorHandler(
|
|
206
266
|
handleHttpResponseErrors,
|
|
@@ -239,24 +299,29 @@ export abstract class TypeweaverHono<
|
|
|
239
299
|
* Processes errors in order: validation, HTTP response, unknown.
|
|
240
300
|
*/
|
|
241
301
|
protected registerErrorHandler(): void {
|
|
242
|
-
this.onError(
|
|
302
|
+
this.onError(async (error, context) =>
|
|
303
|
+
this.adapter.toResponse(await this.handleError(error, context))
|
|
304
|
+
);
|
|
243
305
|
}
|
|
244
306
|
|
|
245
307
|
/**
|
|
246
308
|
* Safely executes an error handler and returns null if it fails.
|
|
247
|
-
* This allows for graceful fallback to the next handler in the chain
|
|
309
|
+
* This allows for graceful fallback to the next handler in the chain
|
|
310
|
+
* without crashing the request pipeline.
|
|
248
311
|
*
|
|
249
312
|
* @param handlerFn - Function that executes the error handler
|
|
250
|
-
* @returns
|
|
313
|
+
* @returns The handler's response if successful, null if the handler throws
|
|
251
314
|
*/
|
|
252
|
-
private async
|
|
315
|
+
private async safelyExecuteErrorHandler(
|
|
253
316
|
handlerFn: () => Promise<IHttpResponse> | IHttpResponse
|
|
254
|
-
): Promise<
|
|
317
|
+
): Promise<IHttpResponse | null> {
|
|
255
318
|
try {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
319
|
+
return await handlerFn();
|
|
320
|
+
} catch (error) {
|
|
321
|
+
console.error(
|
|
322
|
+
"TypeweaverHono: error handler threw while handling error",
|
|
323
|
+
error
|
|
324
|
+
);
|
|
260
325
|
return null;
|
|
261
326
|
}
|
|
262
327
|
}
|
|
@@ -264,24 +329,21 @@ export abstract class TypeweaverHono<
|
|
|
264
329
|
protected async handleError(
|
|
265
330
|
error: unknown,
|
|
266
331
|
context: Context
|
|
267
|
-
): Promise<
|
|
332
|
+
): Promise<IHttpResponse> {
|
|
268
333
|
// Handle validation errors
|
|
269
334
|
if (
|
|
270
335
|
error instanceof RequestValidationError &&
|
|
271
|
-
this.config.errorHandlers.
|
|
336
|
+
this.config.errorHandlers.requestValidation
|
|
272
337
|
) {
|
|
273
|
-
const response = await this.
|
|
274
|
-
this.config.errorHandlers.
|
|
338
|
+
const response = await this.safelyExecuteErrorHandler(() =>
|
|
339
|
+
this.config.errorHandlers.requestValidation!(error, context)
|
|
275
340
|
);
|
|
276
341
|
if (response) return response;
|
|
277
342
|
}
|
|
278
343
|
|
|
279
344
|
// Handle HTTP response errors
|
|
280
|
-
if (
|
|
281
|
-
|
|
282
|
-
this.config.errorHandlers.httpResponse
|
|
283
|
-
) {
|
|
284
|
-
const response = await this.safelyExecuteHandler(() =>
|
|
345
|
+
if (isTypedHttpResponse(error) && this.config.errorHandlers.httpResponse) {
|
|
346
|
+
const response = await this.safelyExecuteErrorHandler(() =>
|
|
285
347
|
this.config.errorHandlers.httpResponse!(error, context)
|
|
286
348
|
);
|
|
287
349
|
if (response) return response;
|
|
@@ -289,7 +351,7 @@ export abstract class TypeweaverHono<
|
|
|
289
351
|
|
|
290
352
|
// Handle unknown errors
|
|
291
353
|
if (this.config.errorHandlers.unknown) {
|
|
292
|
-
const response = await this.
|
|
354
|
+
const response = await this.safelyExecuteErrorHandler(() =>
|
|
293
355
|
this.config.errorHandlers.unknown!(error, context)
|
|
294
356
|
);
|
|
295
357
|
if (response) return response;
|
|
@@ -304,7 +366,8 @@ export abstract class TypeweaverHono<
|
|
|
304
366
|
*
|
|
305
367
|
* @param context - Hono context for the current request
|
|
306
368
|
* @param operationId - Unique operation identifier from the API definition
|
|
307
|
-
* @param
|
|
369
|
+
* @param requestValidator - Request validator for the specific operation
|
|
370
|
+
* @param responseValidator - Response validator for the specific operation
|
|
308
371
|
* @param handler - Type-safe request handler function
|
|
309
372
|
* @returns Hono-compatible Response object
|
|
310
373
|
*/
|
|
@@ -314,7 +377,8 @@ export abstract class TypeweaverHono<
|
|
|
314
377
|
>(
|
|
315
378
|
context: Context,
|
|
316
379
|
operationId: string,
|
|
317
|
-
|
|
380
|
+
requestValidator: IRequestValidator,
|
|
381
|
+
responseValidator: IResponseValidator,
|
|
318
382
|
handler: HonoRequestHandler<TRequest, TResponse>
|
|
319
383
|
): Promise<Response> {
|
|
320
384
|
try {
|
|
@@ -322,15 +386,67 @@ export abstract class TypeweaverHono<
|
|
|
322
386
|
|
|
323
387
|
const httpRequest = await this.adapter.toRequest(context);
|
|
324
388
|
|
|
325
|
-
// Conditionally validate
|
|
326
389
|
const validatedRequest = this.config.validateRequests
|
|
327
|
-
? (
|
|
390
|
+
? (requestValidator.validate(httpRequest) as TRequest)
|
|
328
391
|
: (httpRequest as TRequest);
|
|
329
392
|
|
|
330
393
|
const httpResponse = await handler(validatedRequest, context);
|
|
331
|
-
return this.adapter.toResponse(
|
|
394
|
+
return this.adapter.toResponse(
|
|
395
|
+
await this.validateResponse(responseValidator, httpResponse, context)
|
|
396
|
+
);
|
|
332
397
|
} catch (error) {
|
|
333
|
-
|
|
398
|
+
if (isTypedHttpResponse(error) && this.config.validateResponses) {
|
|
399
|
+
const validated = await this.validateResponse(
|
|
400
|
+
responseValidator,
|
|
401
|
+
error,
|
|
402
|
+
context
|
|
403
|
+
);
|
|
404
|
+
return this.adapter.toResponse(validated);
|
|
405
|
+
}
|
|
406
|
+
return this.adapter.toResponse(await this.handleError(error, context));
|
|
334
407
|
}
|
|
335
408
|
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Validates a response against the operation's response validator.
|
|
412
|
+
*
|
|
413
|
+
* Behavior depends on configuration:
|
|
414
|
+
* - `validateResponses: false` → returns the original response unchanged.
|
|
415
|
+
* - `validateResponses: true` (default) → runs validation:
|
|
416
|
+
* - Valid response → returns the stripped response (extra fields removed).
|
|
417
|
+
* - Invalid response + handler configured → calls the handler safely.
|
|
418
|
+
* If the handler throws, falls back to the original response.
|
|
419
|
+
* - Invalid response + `handleResponseValidationErrors: false` → returns
|
|
420
|
+
* the original (invalid) response as-is.
|
|
421
|
+
*
|
|
422
|
+
* @param responseValidator - The response validator for the operation
|
|
423
|
+
* @param response - The response to validate
|
|
424
|
+
* @param context - The Hono context for the current request
|
|
425
|
+
* @returns The validated (and stripped) response, the handler's response, or the original
|
|
426
|
+
*/
|
|
427
|
+
private async validateResponse(
|
|
428
|
+
responseValidator: IResponseValidator,
|
|
429
|
+
response: IHttpResponse,
|
|
430
|
+
context: Context
|
|
431
|
+
): Promise<IHttpResponse> {
|
|
432
|
+
if (!this.config.validateResponses) return response;
|
|
433
|
+
|
|
434
|
+
const result = responseValidator.safeValidate(response);
|
|
435
|
+
|
|
436
|
+
if (result.isValid) return result.data;
|
|
437
|
+
|
|
438
|
+
if (this.config.errorHandlers.responseValidation) {
|
|
439
|
+
const handlerResponse = await this.safelyExecuteErrorHandler(() =>
|
|
440
|
+
this.config.errorHandlers.responseValidation!(
|
|
441
|
+
result.error,
|
|
442
|
+
response,
|
|
443
|
+
context
|
|
444
|
+
)
|
|
445
|
+
);
|
|
446
|
+
|
|
447
|
+
if (handlerResponse) return handlerResponse;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
return response;
|
|
451
|
+
}
|
|
336
452
|
}
|
|
@@ -12,6 +12,7 @@ import { TypeweaverHono, type HonoRequestHandler, type TypeweaverHonoOptions } f
|
|
|
12
12
|
import type { I<%- operation.className %>Request } from "./<%- operation.className %>Request";
|
|
13
13
|
import { <%- operation.className %>RequestValidator } from "./<%- operation.className %>RequestValidator";
|
|
14
14
|
import type { <%- operation.className %>Response } from "./<%- operation.className %>Response";
|
|
15
|
+
import { <%- operation.className %>ResponseValidator } from "./<%- operation.className %>ResponseValidator";
|
|
15
16
|
<% } %>
|
|
16
17
|
|
|
17
18
|
export type Hono<%- pascalCaseEntityName %>ApiHandler = {
|
|
@@ -33,6 +34,7 @@ export class <%- pascalCaseEntityName %>Hono extends TypeweaverHono<Hono<%- pasc
|
|
|
33
34
|
context,
|
|
34
35
|
'<%- operation.operationId %>',
|
|
35
36
|
new <%- operation.className %>RequestValidator(),
|
|
37
|
+
new <%- operation.className %>ResponseValidator(),
|
|
36
38
|
this.requestHandlers.<%- operation.handlerName %>.bind(this.requestHandlers)
|
|
37
39
|
));
|
|
38
40
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rexeus/typeweaver-hono",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Generates Hono routers and handlers straight from your API definitions. Powered by Typeweaver 🧵✨",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -47,20 +47,20 @@
|
|
|
47
47
|
"homepage": "https://github.com/rexeus/typeweaver#readme",
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"hono": "^4.11.0",
|
|
50
|
-
"@rexeus/typeweaver-core": "^0.
|
|
51
|
-
"@rexeus/typeweaver-gen": "^0.
|
|
50
|
+
"@rexeus/typeweaver-core": "^0.8.0",
|
|
51
|
+
"@rexeus/typeweaver-gen": "^0.8.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"hono": "^4.11.3",
|
|
55
55
|
"test-utils": "file:../test-utils",
|
|
56
|
-
"@rexeus/typeweaver-core": "^0.
|
|
57
|
-
"@rexeus/typeweaver-gen": "^0.
|
|
56
|
+
"@rexeus/typeweaver-core": "^0.8.0",
|
|
57
|
+
"@rexeus/typeweaver-gen": "^0.8.0"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"case": "^1.6.3"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
|
-
"typecheck": "tsc --noEmit",
|
|
63
|
+
"typecheck": "tsc --noEmit -p tsconfig.typecheck.json",
|
|
64
64
|
"format": "oxfmt",
|
|
65
65
|
"build": "tsdown && mkdir -p ./dist/templates ./dist/lib && cp -r ./src/templates/* ./dist/templates/ && cp -r ./src/lib/* ./dist/lib/ && cp ../../LICENSE ../../NOTICE ./dist/",
|
|
66
66
|
"test": "vitest --run",
|