@mpen/routekit 0.1.0 → 0.1.2
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/dist/bin.d.mts +4 -0
- package/dist/client/react.d.mts +178 -0
- package/dist/client/react.mjs +142 -0
- package/dist/client.d.mts +433 -0
- package/dist/client.mjs +264 -0
- package/dist/content-BuDOmhH_.mjs +102 -0
- package/dist/core-CzUCxvGk.d.mts +140 -0
- package/dist/core-DbmQauwS.mjs +81 -0
- package/dist/handlers.d.mts +72 -0
- package/dist/handlers.mjs +153 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +1152 -0
- package/dist/middleware.d.mts +388 -0
- package/dist/middleware.mjs +1222 -0
- package/dist/request-Dn0zc-xm.mjs +1025 -0
- package/dist/response/content.d.mts +79 -0
- package/dist/response/content.mjs +2 -0
- package/dist/response/json-rpc.d.mts +1 -0
- package/dist/response/json-rpc.mjs +1 -0
- package/dist/response/problem/valibot.d.mts +230 -0
- package/dist/response/problem/valibot.mjs +258 -0
- package/dist/response/problem.d.mts +415 -0
- package/dist/response/problem.mjs +183 -0
- package/dist/response/status.d.mts +45 -0
- package/dist/response/status.mjs +2 -0
- package/dist/responses-B379Ep9Y.d.mts +296 -0
- package/dist/responses-BpVrgeYi.mjs +101 -0
- package/dist/router-Cwb7ak0J.d.mts +1819 -0
- package/dist/routes.d.mts +282 -0
- package/dist/routes.mjs +311 -0
- package/dist/status-C-8mw-FB.mjs +59 -0
- package/dist/valibot-D7liFYyB.d.mts +290 -0
- package/dist/valibot-Du97X-TS.mjs +326 -0
- package/package.json +8 -2
- package/src/bin/gen-api-client.test.ts +0 -70
- package/src/bin/gen-api-client.ts +0 -986
- package/src/client/headers.ts +0 -31
- package/src/client/index.ts +0 -8
- package/src/client/promise.ts +0 -11
- package/src/client/react/index.test.tsx +0 -266
- package/src/client/react/index.ts +0 -431
- package/src/client/responses.test.ts +0 -151
- package/src/client/responses.ts +0 -278
- package/src/client/transport.ts +0 -74
- package/src/client/transports/body-codec.ts +0 -61
- package/src/client/transports/fetch.ts +0 -113
- package/src/client/tsconfig.json +0 -9
- package/src/client/types.ts +0 -15
- package/src/client/url.ts +0 -31
- package/src/index.ts +0 -63
- package/src/router/fetch-types.ts +0 -13
- package/src/router/handlers/index.ts +0 -2
- package/src/router/handlers/openapi/index.ts +0 -2
- package/src/router/handlers/openapi/openapi.ts +0 -293
- package/src/router/integration/zod-openapi.test.ts +0 -74
- package/src/router/lib/charset.test.ts +0 -22
- package/src/router/lib/charset.ts +0 -133
- package/src/router/lib/collections.ts +0 -3
- package/src/router/lib/format.test.ts +0 -67
- package/src/router/lib/format.ts +0 -35
- package/src/router/lib/host.ts +0 -4
- package/src/router/lib/json-schema.ts +0 -6
- package/src/router/lib/media-type.test.ts +0 -122
- package/src/router/lib/media-type.ts +0 -289
- package/src/router/lib/pathname.test.ts +0 -18
- package/src/router/lib/pathname.ts +0 -19
- package/src/router/lib/route-names.ts +0 -70
- package/src/router/lib/route-normalize.test.ts +0 -36
- package/src/router/lib/route-normalize.ts +0 -67
- package/src/router/lib/schema-merge.ts +0 -56
- package/src/router/middleware/accept-ctx.test.ts +0 -33
- package/src/router/middleware/accept-ctx.ts +0 -12
- package/src/router/middleware/body-limit.test.ts +0 -112
- package/src/router/middleware/body-limit.ts +0 -121
- package/src/router/middleware/content-type-context.ts +0 -0
- package/src/router/middleware/cors.test.ts +0 -269
- package/src/router/middleware/cors.ts +0 -490
- package/src/router/middleware/csrf.test.ts +0 -106
- package/src/router/middleware/csrf.ts +0 -192
- package/src/router/middleware/define.ts +0 -249
- package/src/router/middleware/index.ts +0 -34
- package/src/router/middleware/jsxhtml-response.ts +0 -0
- package/src/router/middleware/oas-swagger.ts +0 -0
- package/src/router/middleware/rate-limit.test.ts +0 -886
- package/src/router/middleware/rate-limit.ts +0 -920
- package/src/router/middleware/request-id-ctx.test.ts +0 -183
- package/src/router/middleware/request-id-ctx.ts +0 -135
- package/src/router/middleware/request-logger-format.test.ts +0 -16
- package/src/router/middleware/request-logger-format.ts +0 -269
- package/src/router/middleware/request-logger.test.ts +0 -267
- package/src/router/middleware/request-logger.ts +0 -131
- package/src/router/middleware/start-time-ctx.ts +0 -5
- package/src/router/request.ts +0 -611
- package/src/router/response/core.ts +0 -181
- package/src/router/response/directives.ts +0 -233
- package/src/router/response/formats/content/bodyless.ts +0 -54
- package/src/router/response/formats/content/content.ts +0 -79
- package/src/router/response/formats/content/index.ts +0 -2
- package/src/router/response/formats/json-rpc/index.ts +0 -2
- package/src/router/response/formats/problem/badRequest.ts +0 -90
- package/src/router/response/formats/problem/conflict.ts +0 -90
- package/src/router/response/formats/problem/created.ts +0 -40
- package/src/router/response/formats/problem/index.ts +0 -27
- package/src/router/response/formats/problem/notFound.ts +0 -90
- package/src/router/response/formats/problem/permissionDenied.ts +0 -90
- package/src/router/response/formats/problem/problem.test.ts +0 -888
- package/src/router/response/formats/problem/rateLimited.ts +0 -90
- package/src/router/response/formats/problem/responses.ts +0 -219
- package/src/router/response/formats/problem/root-errors.ts +0 -48
- package/src/router/response/formats/problem/sessionExpired.ts +0 -90
- package/src/router/response/formats/problem/types.ts +0 -170
- package/src/router/response/formats/problem/unauthenticated.ts +0 -90
- package/src/router/response/formats/problem/valibot.ts +0 -410
- package/src/router/response/formats/status/index.ts +0 -1
- package/src/router/response/formats/status/responses.ts +0 -59
- package/src/router/response/formats/status/status.test.ts +0 -21
- package/src/router/response/framers.ts +0 -85
- package/src/router/response/index.ts +0 -28
- package/src/router/response/openapi.test.ts +0 -96
- package/src/router/response/openapi.ts +0 -1
- package/src/router/response/serializers.ts +0 -66
- package/src/router/response/stream.ts +0 -35
- package/src/router/router.test.ts +0 -1571
- package/src/router/router.ts +0 -1965
- package/src/router/routes/index.ts +0 -46
- package/src/router/routes/valibot/index.ts +0 -18
- package/src/router/routes/valibot/valibot.ts +0 -1393
- package/src/router/routes/valibot.test.ts +0 -286
- package/src/router/routes/zod/index.ts +0 -18
- package/src/router/routes/zod/zod.ts +0 -1318
- package/src/router/routes/zod.test.ts +0 -280
- package/src/router/server-interface.ts +0 -31
- package/src/router/types.ts +0 -657
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { n as RoutekitResponse, r as RoutekitResponseInit } from "../core-CzUCxvGk.mjs";
|
|
2
|
+
import { HttpStatus } from "@mpen/http";
|
|
3
|
+
|
|
4
|
+
//#region src/router/response/formats/content/content.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Create a represented `text/plain` response.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* return text('pong')
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* @param value - Text response body.
|
|
14
|
+
* @param init - Response status and headers.
|
|
15
|
+
* @returns Routekit logical response with `Content-Type` set.
|
|
16
|
+
*/
|
|
17
|
+
declare function text(value: string): RoutekitResponse<string, HttpStatus.OK>;
|
|
18
|
+
declare function text(value: string, init: Omit<RoutekitResponseInit, 'status'>): RoutekitResponse<string, HttpStatus.OK>;
|
|
19
|
+
declare function text<const Status extends number>(value: string, init: RoutekitResponseInit<Status> & {
|
|
20
|
+
status: Status;
|
|
21
|
+
}): RoutekitResponse<string, Status>;
|
|
22
|
+
/**
|
|
23
|
+
* Create a represented `text/html` response.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* return html('<h1>Hello</h1>')
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @param value - HTML response body.
|
|
31
|
+
* @param init - Response status and headers.
|
|
32
|
+
* @returns Routekit logical response with `Content-Type` set.
|
|
33
|
+
*/
|
|
34
|
+
declare function html(value: string): RoutekitResponse<string, HttpStatus.OK>;
|
|
35
|
+
declare function html(value: string, init: Omit<RoutekitResponseInit, 'status'>): RoutekitResponse<string, HttpStatus.OK>;
|
|
36
|
+
declare function html<const Status extends number>(value: string, init: RoutekitResponseInit<Status> & {
|
|
37
|
+
status: Status;
|
|
38
|
+
}): RoutekitResponse<string, Status>;
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/router/response/formats/content/bodyless.d.ts
|
|
41
|
+
/**
|
|
42
|
+
* Create an empty response with the provided status.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* return empty(HttpStatus.ACCEPTED)
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @param statusCode - HTTP status code to use.
|
|
50
|
+
* @param init - Response headers.
|
|
51
|
+
* @returns Routekit logical response with no body.
|
|
52
|
+
*/
|
|
53
|
+
declare function empty<const Status extends number = HttpStatus.NO_CONTENT>(statusCode?: Status, init?: Omit<RoutekitResponseInit, 'status'>): RoutekitResponse<undefined, Status>;
|
|
54
|
+
/**
|
|
55
|
+
* Create a `204 No Content` response.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* return noContent()
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* @returns Routekit logical response with no body.
|
|
63
|
+
*/
|
|
64
|
+
declare function noContent(): RoutekitResponse<undefined, HttpStatus.NO_CONTENT>;
|
|
65
|
+
/**
|
|
66
|
+
* Create a redirect response.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* return redirect('/login')
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* @param url - Redirect target URL.
|
|
74
|
+
* @param statusCode - Redirect status code. Defaults to `302`.
|
|
75
|
+
* @returns Routekit logical response with a `Location` header.
|
|
76
|
+
*/
|
|
77
|
+
declare function redirect<const Status extends number = HttpStatus.FOUND>(url: string, statusCode?: Status): RoutekitResponse<undefined, Status>;
|
|
78
|
+
//#endregion
|
|
79
|
+
export { empty, html, noContent, redirect, text };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { C as MiddlewareInput, f as ContextFromMiddlewareInput } from "../../router-Cwb7ak0J.mjs";
|
|
2
|
+
import { n as RoutekitResponse } from "../../core-CzUCxvGk.mjs";
|
|
3
|
+
import { d as ProblemResponse, i as ValidationProblemInit, l as ProblemIssue } from "../../responses-B379Ep9Y.mjs";
|
|
4
|
+
import { i as ValibotRouteBuilder, l as ValibotValidationError, o as ValibotRouteHelperDefaults } from "../../valibot-D7liFYyB.mjs";
|
|
5
|
+
import * as v from "valibot";
|
|
6
|
+
|
|
7
|
+
//#region src/router/response/formats/problem/valibot.d.ts
|
|
8
|
+
type AnySchema = v.BaseSchema<any, any, any>;
|
|
9
|
+
type StringSchema = v.BaseSchema<any, string, any>;
|
|
10
|
+
type ProblemSchemaResult<CodeSchema extends StringSchema, Schema extends AnySchema> = v.BaseSchema<v.InferInput<Schema>, ProblemResponse<v.InferOutput<CodeSchema> & string>, v.InferIssue<Schema>>;
|
|
11
|
+
declare function createSuccessSchema<const DataSchema extends AnySchema>(dataSchema: DataSchema): v.ObjectSchema<{
|
|
12
|
+
readonly success: v.LiteralSchema<true, undefined>;
|
|
13
|
+
readonly data: DataSchema;
|
|
14
|
+
}, undefined>;
|
|
15
|
+
declare function createSuccessSchemaWithMeta<const DataSchema extends AnySchema, const MetaSchema extends AnySchema>(dataSchema: DataSchema, metaSchema: MetaSchema): v.ObjectSchema<{
|
|
16
|
+
readonly success: v.LiteralSchema<true, undefined>;
|
|
17
|
+
readonly data: DataSchema;
|
|
18
|
+
readonly meta: v.OptionalSchema<MetaSchema, undefined>;
|
|
19
|
+
}, undefined>;
|
|
20
|
+
type SuccessSchemaResult<DataSchema extends AnySchema, MetaSchema extends AnySchema | undefined> = MetaSchema extends AnySchema ? ReturnType<typeof createSuccessSchemaWithMeta<DataSchema, MetaSchema>> : ReturnType<typeof createSuccessSchema<DataSchema>>;
|
|
21
|
+
/**
|
|
22
|
+
* Create a Valibot schema for standard response issues.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const schema = problemIssueSchema(v.picklist(['required', 'invalid_type']))
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @param codeSchema - Optional issue code schema. Defaults to `v.string()`.
|
|
30
|
+
* @returns Valibot object schema for [`ProblemIssue`]{@link ProblemIssue}.
|
|
31
|
+
* @typeParam CodeSchema - Valibot schema used for issue codes.
|
|
32
|
+
*/
|
|
33
|
+
declare function problemIssueSchema<const CodeSchema extends StringSchema = StringSchema>(codeSchema?: CodeSchema): v.ObjectSchema<{
|
|
34
|
+
readonly code: CodeSchema;
|
|
35
|
+
readonly message: v.StringSchema<undefined>;
|
|
36
|
+
readonly path: v.OptionalSchema<v.SchemaWithPipe<readonly [v.ArraySchema<v.UnionSchema<[v.StringSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, v.ReadonlyAction<(string | number)[]>]>, undefined>;
|
|
37
|
+
readonly expected: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
38
|
+
readonly received: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
39
|
+
}, undefined>;
|
|
40
|
+
/**
|
|
41
|
+
* Create a Valibot schema for standard primary error metadata.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* const schema = problemErrorSchema(v.picklist(['not_found', 'validation_failed']))
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @param codeSchema - Optional primary error code schema. Defaults to `v.string()`.
|
|
49
|
+
* @returns Valibot object schema for problem error metadata.
|
|
50
|
+
* @typeParam CodeSchema - Valibot schema used for primary error codes.
|
|
51
|
+
*/
|
|
52
|
+
declare function problemErrorSchema<const CodeSchema extends StringSchema = StringSchema>(codeSchema?: CodeSchema): v.ObjectSchema<{
|
|
53
|
+
readonly code: CodeSchema;
|
|
54
|
+
readonly message: v.StringSchema<undefined>;
|
|
55
|
+
readonly title: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
56
|
+
}, undefined>;
|
|
57
|
+
/**
|
|
58
|
+
* Create a Valibot schema for successful standard response envelopes.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* const schema = okSchema(v.object({ id: v.string() }))
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @param dataSchema - Valibot schema for the response payload.
|
|
66
|
+
* @param metaSchema - Optional Valibot schema for response metadata.
|
|
67
|
+
* @returns Valibot object schema for a successful standard response.
|
|
68
|
+
* @typeParam DataSchema - Valibot schema used for the response payload.
|
|
69
|
+
* @typeParam MetaSchema - Optional Valibot schema used for response metadata.
|
|
70
|
+
*/
|
|
71
|
+
declare function okSchema<const DataSchema extends AnySchema, const MetaSchema extends AnySchema | undefined = undefined>(dataSchema: DataSchema, metaSchema?: MetaSchema): SuccessSchemaResult<DataSchema, MetaSchema>;
|
|
72
|
+
/**
|
|
73
|
+
* Create a Valibot schema for standard problem response envelopes.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```ts
|
|
77
|
+
* const schema = problemSchema({
|
|
78
|
+
* code: v.picklist(['not_found', 'validation_failed']),
|
|
79
|
+
* })
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* @param options - Optional primary error and issue schemas.
|
|
83
|
+
* @returns Valibot object schema for a standard problem response.
|
|
84
|
+
* @typeParam CodeSchema - Valibot schema used for primary error codes.
|
|
85
|
+
* @typeParam IssueSchema - Valibot schema used for response issues.
|
|
86
|
+
*/
|
|
87
|
+
declare function problemSchema<const CodeSchema extends StringSchema = StringSchema, const IssueSchema extends AnySchema = ReturnType<typeof problemIssueSchema>>(options?: {
|
|
88
|
+
code?: CodeSchema;
|
|
89
|
+
issue?: IssueSchema;
|
|
90
|
+
}): ProblemSchemaResult<CodeSchema, v.ObjectSchema<{
|
|
91
|
+
readonly success: v.LiteralSchema<false, undefined>;
|
|
92
|
+
readonly error: v.ObjectSchema<{
|
|
93
|
+
readonly code: CodeSchema;
|
|
94
|
+
readonly message: v.StringSchema<undefined>;
|
|
95
|
+
readonly title: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
96
|
+
}, undefined>;
|
|
97
|
+
readonly issues: v.OptionalSchema<v.SchemaWithPipe<readonly [v.ArraySchema<IssueSchema, undefined>, v.ReadonlyAction<v.InferOutput<IssueSchema>[]>]>, undefined>;
|
|
98
|
+
}, undefined>>;
|
|
99
|
+
/**
|
|
100
|
+
* Create a Valibot schema for the full standard response union.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* const schema = standardResponseSchema(v.object({ id: v.string() }), {
|
|
105
|
+
* code: v.picklist(['not_found']),
|
|
106
|
+
* })
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @param dataSchema - Valibot schema for the successful response payload.
|
|
110
|
+
* @param options - Optional metadata, primary error, and issue schemas.
|
|
111
|
+
* @returns Valibot union schema for successful and problem responses.
|
|
112
|
+
* @typeParam DataSchema - Valibot schema used for the response payload.
|
|
113
|
+
* @typeParam MetaSchema - Optional Valibot schema used for response metadata.
|
|
114
|
+
* @typeParam CodeSchema - Valibot schema used for primary error codes.
|
|
115
|
+
* @typeParam IssueSchema - Valibot schema used for response issues.
|
|
116
|
+
*/
|
|
117
|
+
declare function standardResponseSchema<const DataSchema extends AnySchema, const MetaSchema extends AnySchema | undefined = undefined, const CodeSchema extends StringSchema = StringSchema, const IssueSchema extends AnySchema = ReturnType<typeof problemIssueSchema>>(dataSchema: DataSchema, options?: {
|
|
118
|
+
meta?: MetaSchema;
|
|
119
|
+
code?: CodeSchema;
|
|
120
|
+
issue?: IssueSchema;
|
|
121
|
+
}): v.UnionSchema<[v.ObjectSchema<{
|
|
122
|
+
readonly success: v.LiteralSchema<true, undefined>;
|
|
123
|
+
readonly data: DataSchema;
|
|
124
|
+
}, undefined> | SuccessSchemaResult<DataSchema, MetaSchema & {}>, ProblemSchemaResult<CodeSchema, v.ObjectSchema<{
|
|
125
|
+
readonly success: v.LiteralSchema<false, undefined>;
|
|
126
|
+
readonly error: v.ObjectSchema<{
|
|
127
|
+
readonly code: CodeSchema;
|
|
128
|
+
readonly message: v.StringSchema<undefined>;
|
|
129
|
+
readonly title: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
130
|
+
}, undefined>;
|
|
131
|
+
readonly issues: v.OptionalSchema<v.SchemaWithPipe<readonly [v.ArraySchema<IssueSchema, undefined>, v.ReadonlyAction<v.InferOutput<IssueSchema>[]>]>, undefined>;
|
|
132
|
+
}, undefined>>], undefined>;
|
|
133
|
+
/**
|
|
134
|
+
* Convert a Valibot issue into a standard response issue.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```ts
|
|
138
|
+
* const parsed = v.safeParse(v.object({ id: v.string() }), { id: 123 })
|
|
139
|
+
* if (!parsed.success) {
|
|
140
|
+
* const issue = issueFromValibotIssue(parsed.issues[0])
|
|
141
|
+
* }
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* @param issue - Valibot issue to convert.
|
|
145
|
+
* @returns Standard response issue.
|
|
146
|
+
*/
|
|
147
|
+
declare function issueFromValibotIssue(issue: v.BaseIssue<unknown>): ProblemIssue;
|
|
148
|
+
/**
|
|
149
|
+
* Convert Valibot issues into standard response issues.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```ts
|
|
153
|
+
* const parsed = v.safeParse(v.object({ id: v.string() }), { id: 123 })
|
|
154
|
+
* if (!parsed.success) {
|
|
155
|
+
* const issues = issuesFromValibotIssues(parsed.issues)
|
|
156
|
+
* }
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* @param issues - Valibot issues to convert.
|
|
160
|
+
* @returns Standard response issues.
|
|
161
|
+
*/
|
|
162
|
+
declare function issuesFromValibotIssues(issues: readonly v.BaseIssue<unknown>[]): ProblemIssue[];
|
|
163
|
+
/**
|
|
164
|
+
* Create a validation problem response from Valibot issues.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* const route = createValibotRouteBuilder()
|
|
169
|
+
* route({
|
|
170
|
+
* onRequestValidationError: (_component, issues) => validationProblemFromValibotIssues(issues),
|
|
171
|
+
* handler: () => ok({ saved: true }),
|
|
172
|
+
* })
|
|
173
|
+
* ```
|
|
174
|
+
*
|
|
175
|
+
* @param issues - Valibot issues to convert and include in the response.
|
|
176
|
+
* @param init - Optional problem response overrides and headers.
|
|
177
|
+
* @returns Routekit logical response with a validation [`ProblemResponse`]{@link ProblemResponse}.
|
|
178
|
+
* @typeParam Code - Machine-readable primary error code.
|
|
179
|
+
*/
|
|
180
|
+
declare function validationProblemFromValibotIssues<const Code extends string = 'validation_failed'>(issues: readonly v.BaseIssue<unknown>[], init?: ValidationProblemInit<Code>): RoutekitResponse<ProblemResponse<Code>>;
|
|
181
|
+
/**
|
|
182
|
+
* A Valibot validation error handler that maps request validation errors to problem-compliant responses.
|
|
183
|
+
*
|
|
184
|
+
* This handler returns `422 Unprocessable Content` with error code `validation_failed:body` for request body
|
|
185
|
+
* validation failures, and `400 Bad Request` with `validation_failed:query` or `validation_failed:path` for
|
|
186
|
+
* query and path parameter validation failures respectively.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```ts
|
|
190
|
+
* const route = createValibotRouteBuilder({
|
|
191
|
+
* onRequestValidationError: problemValidationErrorHandler,
|
|
192
|
+
* })
|
|
193
|
+
* ```
|
|
194
|
+
*
|
|
195
|
+
* @param component - The request component that failed validation.
|
|
196
|
+
* @param issues - A non-empty tuple of Valibot validation issues.
|
|
197
|
+
* @returns A Routekit handler result containing the formatted problem response.
|
|
198
|
+
*/
|
|
199
|
+
declare function problemValidationErrorHandler(component: ValibotValidationError, issues: [v.BaseIssue<unknown>, ...v.BaseIssue<unknown>[]]): RoutekitResponse<ProblemResponse<'validation_failed:body' | 'validation_failed:query' | 'validation_failed:path'>>;
|
|
200
|
+
/**
|
|
201
|
+
* Create a Valibot route builder pre-configured with problem-spec-compliant request validation errors.
|
|
202
|
+
*
|
|
203
|
+
* This route builder automatically configures standard error schemas for `400 Bad Request` and
|
|
204
|
+
* `422 Unprocessable Content` statuses. It also uses [`problemValidationErrorHandler`]{@link problemValidationErrorHandler}
|
|
205
|
+
* as its default validation error handler to output structured JSON responses when validation fails.
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```ts
|
|
209
|
+
* const route = createValibotRouteBuilder()
|
|
210
|
+
*
|
|
211
|
+
* router.post('/todos', route({
|
|
212
|
+
* schema: {
|
|
213
|
+
* request: {
|
|
214
|
+
* body: v.object({ title: v.string() })
|
|
215
|
+
* }
|
|
216
|
+
* },
|
|
217
|
+
* handler: ({ body }) => ok({ title: body.title })
|
|
218
|
+
* }))
|
|
219
|
+
* ```
|
|
220
|
+
*
|
|
221
|
+
* @param defaults - Additional defaults to apply to built routes.
|
|
222
|
+
* @returns A problem-spec-compliant Valibot route builder.
|
|
223
|
+
* @typeParam BuilderCtx - Custom context registered by middlewares (e.g. Services, Auth).
|
|
224
|
+
*/
|
|
225
|
+
declare function createValibotRouteBuilder<BuilderMiddleware extends MiddlewareInput<any>, BuilderCtx extends object = ContextFromMiddlewareInput<BuilderMiddleware>>(defaults: ValibotRouteHelperDefaults<BuilderCtx, BuilderMiddleware> & {
|
|
226
|
+
middleware: BuilderMiddleware;
|
|
227
|
+
}): ValibotRouteBuilder<BuilderCtx, BuilderMiddleware>;
|
|
228
|
+
declare function createValibotRouteBuilder<BuilderCtx extends object = object, BuilderMiddleware extends MiddlewareInput<BuilderCtx> = undefined>(defaults?: ValibotRouteHelperDefaults<BuilderCtx, BuilderMiddleware>): ValibotRouteBuilder<BuilderCtx, BuilderMiddleware>;
|
|
229
|
+
//#endregion
|
|
230
|
+
export { createValibotRouteBuilder, issueFromValibotIssue, issuesFromValibotIssues, okSchema, problemErrorSchema, problemIssueSchema, problemSchema, problemValidationErrorHandler, standardResponseSchema, validationProblemFromValibotIssues };
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { i as validationProblem } from "../../responses-BpVrgeYi.mjs";
|
|
2
|
+
import { n as createValibotRouteBuilder$1 } from "../../valibot-Du97X-TS.mjs";
|
|
3
|
+
import { HttpStatus } from "@mpen/http";
|
|
4
|
+
import * as v from "valibot";
|
|
5
|
+
//#region src/router/response/formats/problem/valibot.ts
|
|
6
|
+
function pathSegmentFromValibotKey(key) {
|
|
7
|
+
if (typeof key === "string" || typeof key === "number") return key;
|
|
8
|
+
}
|
|
9
|
+
function pathFromValibotIssue(issue) {
|
|
10
|
+
const path = issue.path?.map((item) => pathSegmentFromValibotKey(item.key)).filter((item) => item !== void 0);
|
|
11
|
+
return path?.length ? path : void 0;
|
|
12
|
+
}
|
|
13
|
+
function collectValibotIssues(issue, target) {
|
|
14
|
+
if (issue.issues?.length) {
|
|
15
|
+
for (const child of issue.issues) collectValibotIssues(child, target);
|
|
16
|
+
return target;
|
|
17
|
+
}
|
|
18
|
+
target.push(issueFromValibotIssue(issue));
|
|
19
|
+
return target;
|
|
20
|
+
}
|
|
21
|
+
function createSuccessSchema(dataSchema) {
|
|
22
|
+
return v.object({
|
|
23
|
+
success: v.literal(true),
|
|
24
|
+
data: dataSchema
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function createSuccessSchemaWithMeta(dataSchema, metaSchema) {
|
|
28
|
+
return v.object({
|
|
29
|
+
success: v.literal(true),
|
|
30
|
+
data: dataSchema,
|
|
31
|
+
meta: v.optional(metaSchema)
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Create a Valibot schema for standard response issues.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* const schema = problemIssueSchema(v.picklist(['required', 'invalid_type']))
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @param codeSchema - Optional issue code schema. Defaults to `v.string()`.
|
|
43
|
+
* @returns Valibot object schema for [`ProblemIssue`]{@link ProblemIssue}.
|
|
44
|
+
* @typeParam CodeSchema - Valibot schema used for issue codes.
|
|
45
|
+
*/
|
|
46
|
+
function problemIssueSchema(codeSchema = v.string()) {
|
|
47
|
+
return v.object({
|
|
48
|
+
code: codeSchema,
|
|
49
|
+
message: v.string(),
|
|
50
|
+
path: v.optional(v.pipe(v.array(v.union([v.string(), v.number()])), v.readonly())),
|
|
51
|
+
expected: v.optional(v.string()),
|
|
52
|
+
received: v.optional(v.string())
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Create a Valibot schema for standard primary error metadata.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* const schema = problemErrorSchema(v.picklist(['not_found', 'validation_failed']))
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @param codeSchema - Optional primary error code schema. Defaults to `v.string()`.
|
|
64
|
+
* @returns Valibot object schema for problem error metadata.
|
|
65
|
+
* @typeParam CodeSchema - Valibot schema used for primary error codes.
|
|
66
|
+
*/
|
|
67
|
+
function problemErrorSchema(codeSchema = v.string()) {
|
|
68
|
+
return v.object({
|
|
69
|
+
code: codeSchema,
|
|
70
|
+
message: v.string(),
|
|
71
|
+
title: v.optional(v.string())
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Create a Valibot schema for successful standard response envelopes.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* const schema = okSchema(v.object({ id: v.string() }))
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* @param dataSchema - Valibot schema for the response payload.
|
|
83
|
+
* @param metaSchema - Optional Valibot schema for response metadata.
|
|
84
|
+
* @returns Valibot object schema for a successful standard response.
|
|
85
|
+
* @typeParam DataSchema - Valibot schema used for the response payload.
|
|
86
|
+
* @typeParam MetaSchema - Optional Valibot schema used for response metadata.
|
|
87
|
+
*/
|
|
88
|
+
function okSchema(dataSchema, metaSchema) {
|
|
89
|
+
if (metaSchema) return createSuccessSchemaWithMeta(dataSchema, metaSchema);
|
|
90
|
+
return createSuccessSchema(dataSchema);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Create a Valibot schema for standard problem response envelopes.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* const schema = problemSchema({
|
|
98
|
+
* code: v.picklist(['not_found', 'validation_failed']),
|
|
99
|
+
* })
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* @param options - Optional primary error and issue schemas.
|
|
103
|
+
* @returns Valibot object schema for a standard problem response.
|
|
104
|
+
* @typeParam CodeSchema - Valibot schema used for primary error codes.
|
|
105
|
+
* @typeParam IssueSchema - Valibot schema used for response issues.
|
|
106
|
+
*/
|
|
107
|
+
function problemSchema(options = {}) {
|
|
108
|
+
const codeSchema = options.code ?? v.string();
|
|
109
|
+
const issueSchema = options.issue ?? problemIssueSchema();
|
|
110
|
+
return v.object({
|
|
111
|
+
success: v.literal(false),
|
|
112
|
+
error: problemErrorSchema(codeSchema),
|
|
113
|
+
issues: v.optional(v.pipe(v.array(issueSchema), v.readonly()))
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Create a Valibot schema for the full standard response union.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* const schema = standardResponseSchema(v.object({ id: v.string() }), {
|
|
122
|
+
* code: v.picklist(['not_found']),
|
|
123
|
+
* })
|
|
124
|
+
* ```
|
|
125
|
+
*
|
|
126
|
+
* @param dataSchema - Valibot schema for the successful response payload.
|
|
127
|
+
* @param options - Optional metadata, primary error, and issue schemas.
|
|
128
|
+
* @returns Valibot union schema for successful and problem responses.
|
|
129
|
+
* @typeParam DataSchema - Valibot schema used for the response payload.
|
|
130
|
+
* @typeParam MetaSchema - Optional Valibot schema used for response metadata.
|
|
131
|
+
* @typeParam CodeSchema - Valibot schema used for primary error codes.
|
|
132
|
+
* @typeParam IssueSchema - Valibot schema used for response issues.
|
|
133
|
+
*/
|
|
134
|
+
function standardResponseSchema(dataSchema, options = {}) {
|
|
135
|
+
const successEnvelopeSchema = options.meta === void 0 ? okSchema(dataSchema) : okSchema(dataSchema, options.meta);
|
|
136
|
+
return v.union([successEnvelopeSchema, problemSchema({
|
|
137
|
+
code: options.code,
|
|
138
|
+
issue: options.issue
|
|
139
|
+
})]);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Convert a Valibot issue into a standard response issue.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* const parsed = v.safeParse(v.object({ id: v.string() }), { id: 123 })
|
|
147
|
+
* if (!parsed.success) {
|
|
148
|
+
* const issue = issueFromValibotIssue(parsed.issues[0])
|
|
149
|
+
* }
|
|
150
|
+
* ```
|
|
151
|
+
*
|
|
152
|
+
* @param issue - Valibot issue to convert.
|
|
153
|
+
* @returns Standard response issue.
|
|
154
|
+
*/
|
|
155
|
+
function issueFromValibotIssue(issue) {
|
|
156
|
+
const path = pathFromValibotIssue(issue);
|
|
157
|
+
return {
|
|
158
|
+
code: issue.type,
|
|
159
|
+
message: issue.message,
|
|
160
|
+
...path ? { path } : {},
|
|
161
|
+
...issue.expected == null ? {} : { expected: issue.expected },
|
|
162
|
+
received: issue.received
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Convert Valibot issues into standard response issues.
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```ts
|
|
170
|
+
* const parsed = v.safeParse(v.object({ id: v.string() }), { id: 123 })
|
|
171
|
+
* if (!parsed.success) {
|
|
172
|
+
* const issues = issuesFromValibotIssues(parsed.issues)
|
|
173
|
+
* }
|
|
174
|
+
* ```
|
|
175
|
+
*
|
|
176
|
+
* @param issues - Valibot issues to convert.
|
|
177
|
+
* @returns Standard response issues.
|
|
178
|
+
*/
|
|
179
|
+
function issuesFromValibotIssues(issues) {
|
|
180
|
+
return issues.flatMap((issue) => collectValibotIssues(issue, []));
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Create a validation problem response from Valibot issues.
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* const route = createValibotRouteBuilder()
|
|
188
|
+
* route({
|
|
189
|
+
* onRequestValidationError: (_component, issues) => validationProblemFromValibotIssues(issues),
|
|
190
|
+
* handler: () => ok({ saved: true }),
|
|
191
|
+
* })
|
|
192
|
+
* ```
|
|
193
|
+
*
|
|
194
|
+
* @param issues - Valibot issues to convert and include in the response.
|
|
195
|
+
* @param init - Optional problem response overrides and headers.
|
|
196
|
+
* @returns Routekit logical response with a validation [`ProblemResponse`]{@link ProblemResponse}.
|
|
197
|
+
* @typeParam Code - Machine-readable primary error code.
|
|
198
|
+
*/
|
|
199
|
+
function validationProblemFromValibotIssues(issues, init = {}) {
|
|
200
|
+
return validationProblem(issuesFromValibotIssues(issues), init);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* A Valibot validation error handler that maps request validation errors to problem-compliant responses.
|
|
204
|
+
*
|
|
205
|
+
* This handler returns `422 Unprocessable Content` with error code `validation_failed:body` for request body
|
|
206
|
+
* validation failures, and `400 Bad Request` with `validation_failed:query` or `validation_failed:path` for
|
|
207
|
+
* query and path parameter validation failures respectively.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```ts
|
|
211
|
+
* const route = createValibotRouteBuilder({
|
|
212
|
+
* onRequestValidationError: problemValidationErrorHandler,
|
|
213
|
+
* })
|
|
214
|
+
* ```
|
|
215
|
+
*
|
|
216
|
+
* @param component - The request component that failed validation.
|
|
217
|
+
* @param issues - A non-empty tuple of Valibot validation issues.
|
|
218
|
+
* @returns A Routekit handler result containing the formatted problem response.
|
|
219
|
+
*/
|
|
220
|
+
function problemValidationErrorHandler(component, issues) {
|
|
221
|
+
let code;
|
|
222
|
+
let status;
|
|
223
|
+
switch (component) {
|
|
224
|
+
case 0:
|
|
225
|
+
code = "validation_failed:body";
|
|
226
|
+
status = HttpStatus.UNPROCESSABLE_ENTITY;
|
|
227
|
+
break;
|
|
228
|
+
case 2:
|
|
229
|
+
code = "validation_failed:query";
|
|
230
|
+
status = HttpStatus.BAD_REQUEST;
|
|
231
|
+
break;
|
|
232
|
+
case 1:
|
|
233
|
+
code = "validation_failed:path";
|
|
234
|
+
status = HttpStatus.BAD_REQUEST;
|
|
235
|
+
break;
|
|
236
|
+
default:
|
|
237
|
+
code = "validation_failed:body";
|
|
238
|
+
status = HttpStatus.UNPROCESSABLE_ENTITY;
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
return validationProblemFromValibotIssues(issues, {
|
|
242
|
+
code,
|
|
243
|
+
status,
|
|
244
|
+
message: `Validation failed: ${component === 0 ? "body" : component === 2 ? "query" : "path"}`
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
function createValibotRouteBuilder(defaults = {}) {
|
|
248
|
+
return createValibotRouteBuilder$1({
|
|
249
|
+
onRequestValidationError: problemValidationErrorHandler,
|
|
250
|
+
validationResponses: { response: { body: {
|
|
251
|
+
400: v.union([problemSchema({ code: v.literal("validation_failed:query") }), problemSchema({ code: v.literal("validation_failed:path") })]),
|
|
252
|
+
422: problemSchema({ code: v.literal("validation_failed:body") })
|
|
253
|
+
} } }.response.body,
|
|
254
|
+
...defaults
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
//#endregion
|
|
258
|
+
export { createValibotRouteBuilder, issueFromValibotIssue, issuesFromValibotIssues, okSchema, problemErrorSchema, problemIssueSchema, problemSchema, problemValidationErrorHandler, standardResponseSchema, validationProblemFromValibotIssues };
|