bxo 0.0.5-dev.21 → 0.0.5-dev.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 +1 -1
- package/index.ts +55 -5
- package/package.json +1 -1
package/README.md
CHANGED
package/index.ts
CHANGED
@@ -3,6 +3,18 @@ import { z } from 'zod';
|
|
3
3
|
// Type utilities for extracting types from Zod schemas
|
4
4
|
type InferZodType<T> = T extends z.ZodType<infer U> ? U : never;
|
5
5
|
|
6
|
+
// Response configuration types
|
7
|
+
type ResponseSchema = z.ZodSchema<any>;
|
8
|
+
type StatusResponseSchema = Record<number, ResponseSchema>;
|
9
|
+
type ResponseConfig = ResponseSchema | StatusResponseSchema;
|
10
|
+
|
11
|
+
// Type utility to extract response type from response config
|
12
|
+
type InferResponseType<T> = T extends ResponseSchema
|
13
|
+
? InferZodType<T>
|
14
|
+
: T extends StatusResponseSchema
|
15
|
+
? { [K in keyof T]: InferZodType<T[K]> }[keyof T]
|
16
|
+
: never;
|
17
|
+
|
6
18
|
// Cookie interface
|
7
19
|
interface Cookie {
|
8
20
|
name: string;
|
@@ -35,7 +47,7 @@ interface RouteConfig {
|
|
35
47
|
body?: z.ZodSchema<any>;
|
36
48
|
headers?: z.ZodSchema<any>;
|
37
49
|
cookies?: z.ZodSchema<any>;
|
38
|
-
response?:
|
50
|
+
response?: ResponseConfig;
|
39
51
|
detail?: RouteDetail;
|
40
52
|
}
|
41
53
|
|
@@ -53,11 +65,12 @@ export type Context<TConfig extends RouteConfig = {}> = {
|
|
53
65
|
headers?: Record<string, string>;
|
54
66
|
cookies?: Cookie[];
|
55
67
|
};
|
68
|
+
status: (code: number, data?: any) => any;
|
56
69
|
[key: string]: any;
|
57
70
|
};
|
58
71
|
|
59
|
-
// Handler function type
|
60
|
-
type Handler<TConfig extends RouteConfig = {}, EC = {}> = (ctx: Context<TConfig> & EC) => Promise<any> | any;
|
72
|
+
// Handler function type with proper response typing
|
73
|
+
type Handler<TConfig extends RouteConfig = {}, EC = {}> = (ctx: Context<TConfig> & EC) => Promise<InferResponseType<TConfig['response']> | any> | InferResponseType<TConfig['response']> | any;
|
61
74
|
|
62
75
|
// Route definition
|
63
76
|
interface Route {
|
@@ -433,6 +446,38 @@ export default class BXO {
|
|
433
446
|
return schema.parse(data);
|
434
447
|
}
|
435
448
|
|
449
|
+
// Validate response against response config (supports both simple and status-based schemas)
|
450
|
+
private validateResponse(responseConfig: ResponseConfig | undefined, data: any, status: number = 200): any {
|
451
|
+
if (!responseConfig) return data;
|
452
|
+
|
453
|
+
// If it's a simple schema (not status-based)
|
454
|
+
if ('parse' in responseConfig && typeof responseConfig.parse === 'function') {
|
455
|
+
return responseConfig.parse(data);
|
456
|
+
}
|
457
|
+
|
458
|
+
// If it's a status-based schema
|
459
|
+
if (typeof responseConfig === 'object' && !('parse' in responseConfig)) {
|
460
|
+
const statusSchema = responseConfig[status];
|
461
|
+
if (statusSchema) {
|
462
|
+
return statusSchema.parse(data);
|
463
|
+
}
|
464
|
+
|
465
|
+
// If no specific status schema found, try to find a fallback
|
466
|
+
// Common fallback statuses: 200, 201, 400, 500
|
467
|
+
const fallbackStatuses = [200, 201, 400, 500];
|
468
|
+
for (const fallbackStatus of fallbackStatuses) {
|
469
|
+
if (responseConfig[fallbackStatus]) {
|
470
|
+
return responseConfig[fallbackStatus].parse(data);
|
471
|
+
}
|
472
|
+
}
|
473
|
+
|
474
|
+
// If no schema found for the status, return data as-is
|
475
|
+
return data;
|
476
|
+
}
|
477
|
+
|
478
|
+
return data;
|
479
|
+
}
|
480
|
+
|
436
481
|
// Main request handler
|
437
482
|
private async handleRequest(request: Request, server?: any): Promise<Response | undefined> {
|
438
483
|
const url = new URL(request.url);
|
@@ -514,7 +559,11 @@ export default class BXO {
|
|
514
559
|
cookies: validatedCookies,
|
515
560
|
path: pathname,
|
516
561
|
request,
|
517
|
-
set: {}
|
562
|
+
set: {},
|
563
|
+
status: (code: number, data?: any) => {
|
564
|
+
ctx.set.status = code;
|
565
|
+
return data;
|
566
|
+
}
|
518
567
|
};
|
519
568
|
} catch (validationError) {
|
520
569
|
// Validation failed - return error response
|
@@ -575,7 +624,8 @@ export default class BXO {
|
|
575
624
|
if (route.config?.response && !(response instanceof Response)) {
|
576
625
|
try {
|
577
626
|
console.log('response', response);
|
578
|
-
|
627
|
+
const status = ctx.set.status || 200;
|
628
|
+
response = this.validateResponse(route.config.response, response, status);
|
579
629
|
} catch (validationError) {
|
580
630
|
// Response validation failed
|
581
631
|
|