@taserjs/router 0.0.4 → 0.1.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/dist/cjs/builder/app.cjs +27 -0
- package/dist/cjs/builder/app.cjs.map +1 -0
- package/dist/cjs/builder/app.d.cts +11 -0
- package/dist/cjs/{constants.cjs → builder/constants.cjs} +1 -1
- package/dist/cjs/builder/constants.cjs.map +1 -0
- package/dist/cjs/{factories.cjs → builder/factories.cjs} +5 -5
- package/dist/cjs/builder/factories.cjs.map +1 -0
- package/dist/cjs/builder/factories.d.cts +15 -0
- package/dist/cjs/{middleware.cjs → builder/middleware.cjs} +1 -1
- package/dist/cjs/builder/middleware.cjs.map +1 -0
- package/dist/cjs/{middleware.d.cts → builder/middleware.d.cts} +1 -1
- package/dist/cjs/{route.cjs → builder/route.cjs} +41 -34
- package/dist/cjs/builder/route.cjs.map +1 -0
- package/dist/cjs/builder/route.d.cts +4 -0
- package/dist/cjs/{taser-router.cjs → builder/router.cjs} +38 -13
- package/dist/cjs/builder/router.cjs.map +1 -0
- package/dist/{esm/taser-router.d.ts → cjs/builder/router.d.cts} +16 -11
- package/dist/cjs/{create-context.cjs → context/create-context.cjs} +1 -1
- package/dist/cjs/context/create-context.cjs.map +1 -0
- package/dist/cjs/{create-context.d.cts → context/create-context.d.cts} +2 -2
- package/dist/cjs/define/middleware.cjs +2 -2
- package/dist/cjs/define/middleware.cjs.map +1 -1
- package/dist/cjs/define/middleware.d.cts +10 -8
- package/dist/cjs/define/validators.cjs +1 -1
- package/dist/cjs/define/validators.cjs.map +1 -1
- package/dist/cjs/define/validators.d.cts +1 -1
- package/dist/cjs/index.cjs +6 -28
- package/dist/cjs/index.d.cts +7 -8
- package/dist/cjs/middleware/body-limit.cjs +2 -2
- package/dist/cjs/middleware/body-limit.cjs.map +1 -1
- package/dist/cjs/middleware/compress.cjs +2 -2
- package/dist/cjs/middleware/compress.cjs.map +1 -1
- package/dist/cjs/middleware/cors.cjs +2 -2
- package/dist/cjs/middleware/cors.cjs.map +1 -1
- package/dist/cjs/middleware/csrf.cjs +2 -2
- package/dist/cjs/middleware/csrf.cjs.map +1 -1
- package/dist/cjs/middleware/etag.cjs +2 -2
- package/dist/cjs/middleware/etag.cjs.map +1 -1
- package/dist/cjs/middleware/jwk.cjs +2 -8
- package/dist/cjs/middleware/jwk.cjs.map +1 -1
- package/dist/cjs/middleware/jwt.cjs +2 -8
- package/dist/cjs/middleware/jwt.cjs.map +1 -1
- package/dist/cjs/middleware/secure-headers.cjs +2 -2
- package/dist/cjs/middleware/secure-headers.cjs.map +1 -1
- package/dist/cjs/middleware/timing.cjs +2 -2
- package/dist/cjs/middleware/timing.cjs.map +1 -1
- package/dist/cjs/middleware/wrap-hono.cjs +10 -0
- package/dist/cjs/middleware/wrap-hono.cjs.map +1 -1
- package/dist/cjs/middleware/wrap-hono.d.cts +4 -0
- package/dist/cjs/reply.cjs +8 -19
- package/dist/cjs/reply.d.cts +1 -2
- package/dist/cjs/stream.cjs +8 -31
- package/dist/cjs/stream.d.cts +1 -1
- package/dist/cjs/types/app.d.cts +8 -26
- package/dist/cjs/types/index.d.cts +60 -19
- package/dist/cjs/types/returns.d.cts +8 -11
- package/dist/cjs/types/type-utils.d.cts +8 -7
- package/dist/cjs/types/units.cjs.map +1 -1
- package/dist/cjs/types/units.d.cts +6 -17
- package/dist/esm/builder/app.d.ts +11 -0
- package/dist/esm/builder/app.js +26 -0
- package/dist/esm/builder/app.js.map +1 -0
- package/dist/esm/{constants.js → builder/constants.js} +1 -1
- package/dist/esm/builder/constants.js.map +1 -0
- package/dist/esm/builder/factories.d.ts +15 -0
- package/dist/esm/{factories.js → builder/factories.js} +5 -5
- package/dist/esm/builder/factories.js.map +1 -0
- package/dist/esm/{middleware.d.ts → builder/middleware.d.ts} +1 -1
- package/dist/esm/{middleware.js → builder/middleware.js} +1 -1
- package/dist/esm/builder/middleware.js.map +1 -0
- package/dist/esm/builder/route.d.ts +4 -0
- package/dist/esm/{route.js → builder/route.js} +41 -34
- package/dist/esm/builder/route.js.map +1 -0
- package/dist/{cjs/taser-router.d.cts → esm/builder/router.d.ts} +16 -11
- package/dist/esm/{taser-router.js → builder/router.js} +37 -12
- package/dist/esm/builder/router.js.map +1 -0
- package/dist/esm/{create-context.d.ts → context/create-context.d.ts} +2 -2
- package/dist/esm/{create-context.js → context/create-context.js} +1 -1
- package/dist/esm/context/create-context.js.map +1 -0
- package/dist/esm/define/middleware.d.ts +10 -8
- package/dist/esm/define/middleware.js +2 -2
- package/dist/esm/define/middleware.js.map +1 -1
- package/dist/esm/define/validators.d.ts +1 -1
- package/dist/esm/define/validators.js +1 -1
- package/dist/esm/define/validators.js.map +1 -1
- package/dist/esm/index.d.ts +7 -8
- package/dist/esm/index.js +5 -6
- package/dist/esm/middleware/body-limit.js +2 -2
- package/dist/esm/middleware/body-limit.js.map +1 -1
- package/dist/esm/middleware/compress.js +2 -2
- package/dist/esm/middleware/compress.js.map +1 -1
- package/dist/esm/middleware/cors.js +2 -2
- package/dist/esm/middleware/cors.js.map +1 -1
- package/dist/esm/middleware/csrf.js +2 -2
- package/dist/esm/middleware/csrf.js.map +1 -1
- package/dist/esm/middleware/etag.js +2 -2
- package/dist/esm/middleware/etag.js.map +1 -1
- package/dist/esm/middleware/jwk.js +2 -8
- package/dist/esm/middleware/jwk.js.map +1 -1
- package/dist/esm/middleware/jwt.js +2 -8
- package/dist/esm/middleware/jwt.js.map +1 -1
- package/dist/esm/middleware/secure-headers.js +2 -2
- package/dist/esm/middleware/secure-headers.js.map +1 -1
- package/dist/esm/middleware/timing.js +2 -2
- package/dist/esm/middleware/timing.js.map +1 -1
- package/dist/esm/middleware/wrap-hono.d.ts +4 -0
- package/dist/esm/middleware/wrap-hono.js +10 -1
- package/dist/esm/middleware/wrap-hono.js.map +1 -1
- package/dist/esm/reply.d.ts +1 -2
- package/dist/esm/reply.js +1 -2
- package/dist/esm/stream.d.ts +1 -1
- package/dist/esm/stream.js +1 -2
- package/dist/esm/types/app.d.ts +8 -26
- package/dist/esm/types/index.d.ts +60 -19
- package/dist/esm/types/returns.d.ts +8 -11
- package/dist/esm/types/type-utils.d.ts +8 -7
- package/dist/esm/types/units.d.ts +6 -17
- package/dist/esm/types/units.js.map +1 -1
- package/package.json +3 -3
- package/src/builder/app.ts +39 -0
- package/src/builder/factories.ts +58 -0
- package/src/{middleware.ts → builder/middleware.ts} +2 -2
- package/src/{route.ts → builder/route.ts} +55 -35
- package/src/{taser-router.ts → builder/router.ts} +77 -28
- package/src/{create-context.ts → context/create-context.ts} +2 -2
- package/src/define/middleware.ts +115 -123
- package/src/define/validators.ts +1 -1
- package/src/index.ts +13 -20
- package/src/middleware/body-limit.ts +2 -2
- package/src/middleware/compress.ts +2 -2
- package/src/middleware/cors.ts +2 -2
- package/src/middleware/csrf.ts +2 -2
- package/src/middleware/etag.ts +2 -2
- package/src/middleware/jwk.ts +2 -7
- package/src/middleware/jwt.ts +2 -7
- package/src/middleware/secure-headers.ts +2 -2
- package/src/middleware/timing.ts +2 -2
- package/src/middleware/wrap-hono.ts +13 -0
- package/src/reply.ts +1 -11
- package/src/stream.ts +1 -1
- package/src/types/app.ts +13 -28
- package/src/types/index.ts +126 -22
- package/src/types/returns.ts +9 -78
- package/src/types/type-utils.ts +10 -6
- package/src/types/units.ts +36 -16
- package/dist/cjs/constants.cjs.map +0 -1
- package/dist/cjs/create-context.cjs.map +0 -1
- package/dist/cjs/factories.cjs.map +0 -1
- package/dist/cjs/factories.d.cts +0 -61
- package/dist/cjs/middleware.cjs.map +0 -1
- package/dist/cjs/route.cjs.map +0 -1
- package/dist/cjs/route.d.cts +0 -5
- package/dist/cjs/taser-app.cjs +0 -36
- package/dist/cjs/taser-app.cjs.map +0 -1
- package/dist/cjs/taser-app.d.cts +0 -18
- package/dist/cjs/taser-router.cjs.map +0 -1
- package/dist/esm/constants.js.map +0 -1
- package/dist/esm/create-context.js.map +0 -1
- package/dist/esm/factories.d.ts +0 -61
- package/dist/esm/factories.js.map +0 -1
- package/dist/esm/middleware.js.map +0 -1
- package/dist/esm/route.d.ts +0 -5
- package/dist/esm/route.js.map +0 -1
- package/dist/esm/taser-app.d.ts +0 -18
- package/dist/esm/taser-app.js +0 -35
- package/dist/esm/taser-app.js.map +0 -1
- package/dist/esm/taser-router.js.map +0 -1
- package/src/factories.ts +0 -185
- package/src/taser-app.ts +0 -38
- /package/dist/cjs/{constants.d.cts → builder/constants.d.cts} +0 -0
- /package/dist/esm/{constants.d.ts → builder/constants.d.ts} +0 -0
- /package/src/{constants.ts → builder/constants.ts} +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { Awaitable, TaserCookieJar, TaserHeaders } from '@taserjs/router-core';
|
|
2
2
|
import { RouterRegister } from '../register.js';
|
|
3
|
-
import { MergeMiddlewareField, MergeMiddlewareInputField, MergePart, RequestShape,
|
|
3
|
+
import { MergeMiddlewareField, MergeMiddlewareInputField, MergePart, RequestShape, Simplify, UnionToIntersection, UnitRuntimeContext } from './type-utils.js';
|
|
4
4
|
import { ReturnsMap, ValidHandlerReply } from './returns.js';
|
|
5
5
|
import { Schema } from './schema.js';
|
|
6
|
-
import { AppContext, ExtractState, HandlerContext, HandlerUnit, InlineMiddlewareOptions, Method, MiddlewareDefinition, MiddlewareReturnFromParts, MiddlewareUnit,
|
|
6
|
+
import { AppContext, ExtractState, HandlerContext, HandlerUnit, InlineMiddlewareOptions, Method, MiddlewareDefinition, MiddlewareReturnFromParts, MiddlewareUnit, ValidatorParts } from './units.js';
|
|
7
7
|
export type { Awaitable } from '@taserjs/router-core';
|
|
8
8
|
export type { SchemaRequestShape, InferInput, InferOutput, Schema, StandardSchemaV1, } from './schema.js';
|
|
9
9
|
export type { RouterRegister } from '../register.js';
|
|
10
|
-
export type { MergeMiddlewareField, MergeMiddlewareInputField, MergePart, RequestShape, Simplify, UnwrapPart, } from './type-utils.js';
|
|
11
|
-
export type { EmptyReturns, EnforceHandlerReply, HandlerReply, HasReturns, MergeReturns,
|
|
12
|
-
export type { AppContext, ExtractState, HandlerContext, HandlerUnit, HttpMethod, InlineMiddlewareOptions, IsUnknown, Method, MiddlewareDefinition, MiddlewareNext, MiddlewareReturnFromParts, MiddlewareUnit,
|
|
10
|
+
export type { MergeMiddlewareField, MergeMiddlewareInputField, MergePart, RequestShape, Simplify, UnitRuntimeContext, UnwrapPart, } from './type-utils.js';
|
|
11
|
+
export type { EmptyReturns, EnforceHandlerReply, HandlerReply, HasReturns, MergeReturns, ReplyFor, ReturnsMap, StatusCode, ValidHandlerReply, } from './returns.js';
|
|
12
|
+
export type { AppContext, ExtractState, HandlerContext, HandlerUnit, HttpMethod, InlineMiddlewareOptions, IsUnknown, Method, MiddlewareDefinition, MiddlewareNext, MiddlewareReturnFromParts, MiddlewareUnit, NextFn, NextResult, StandaloneMiddlewareContext, StateBrand, ValidatorParts, } from './units.js';
|
|
13
13
|
export type RoutePath = RouterRegister extends {
|
|
14
14
|
RoutePath: infer P;
|
|
15
15
|
} ? P : never;
|
|
@@ -29,6 +29,7 @@ type ParseParam<Segment extends string> = Segment extends "*" ? {
|
|
|
29
29
|
} : {};
|
|
30
30
|
type ParseParamsFromSegments<S extends string> = S extends `${infer Segment}/${infer Rest}` ? ParseParam<Segment> & ParseParamsFromSegments<Rest> : ParseParam<S>;
|
|
31
31
|
export type PathParams<Path extends string> = Path extends `/${infer Rest}` ? ParseParamsFromSegments<Rest> : {};
|
|
32
|
+
export type ResolveParams<TPathParams, TSchemaParams> = TSchemaParams extends Record<string, unknown> ? [keyof TSchemaParams] extends [never] ? TPathParams : Simplify<Omit<TPathParams, keyof TSchemaParams> & TSchemaParams> : TPathParams;
|
|
32
33
|
type LayoutParent<Layout extends LayoutId> = LayoutTree[Layout] extends {
|
|
33
34
|
parent: infer Parent extends LayoutId | null;
|
|
34
35
|
} ? Parent : null;
|
|
@@ -56,12 +57,14 @@ type RouteParent<Path extends RoutePath, TMethod extends Method> = RouteEntry<Pa
|
|
|
56
57
|
type RouteLayoutChain<Path extends RoutePath, TMethod extends Method> = RouteEntry<Path, TMethod> extends {
|
|
57
58
|
layoutChain: infer Chain extends readonly LayoutId[];
|
|
58
59
|
} ? Chain : RouteParent<Path, TMethod> extends LayoutId ? readonly [RouteParent<Path, TMethod>] : readonly [];
|
|
59
|
-
type
|
|
60
|
+
export type RouteLayoutMiddlewares<Path extends RoutePath, TMethod extends Method> = ResolveLayoutChainMiddlewares<RouteLayoutChain<Path, TMethod>>;
|
|
61
|
+
export type RouteLayoutField<Path extends RoutePath, TMethod extends Method, Field extends "query" | "params" | "body" | "state"> = MergeMiddlewareField<RouteLayoutMiddlewares<Path, TMethod>, Field>;
|
|
62
|
+
export type RouteLayoutInputField<Path extends RoutePath, TMethod extends Method, Field extends "query" | "params" | "body"> = MergeMiddlewareInputField<RouteLayoutMiddlewares<Path, TMethod>, Field>;
|
|
63
|
+
type RouteResolvedField<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], Field extends "query" | "params" | "body" | "state"> = RouteLayoutField<Path, TMethod, Field> & MergeMiddlewareField<Acc, Field>;
|
|
60
64
|
type RouteChainField<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], Field extends "query" | "params" | "body" | "state"> = RouteResolvedField<Path, TMethod, Acc, Field>;
|
|
61
|
-
type UnitRuntimeContext = Omit<RuntimeContextFields<NativeContext>, "var">;
|
|
62
65
|
export type RouteChainContext<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], TQuery, TParams, TBody, TAppContext extends Record<string, unknown> = AppContext> = Simplify<TAppContext & UnitRuntimeContext & {
|
|
63
66
|
query: Simplify<MergePart<TQuery, RouteChainField<Path, TMethod, Acc, "query">>>;
|
|
64
|
-
params: Simplify<PathParams<Path
|
|
67
|
+
params: Simplify<ResolveParams<PathParams<Path>, MergePart<TParams, RouteChainField<Path, TMethod, Acc, "params">>>>;
|
|
65
68
|
body: Simplify<MergePart<TBody, RouteChainField<Path, TMethod, Acc, "body">>>;
|
|
66
69
|
state: Simplify<RouteChainField<Path, TMethod, Acc, "state">>;
|
|
67
70
|
headers: TaserHeaders;
|
|
@@ -77,9 +80,9 @@ export type RouteHandleContext<Path extends RoutePath, TMethod extends Method, A
|
|
|
77
80
|
query: Simplify<MergePart<Validators extends {
|
|
78
81
|
query?: infer Q;
|
|
79
82
|
} ? Q : unknown, RouteResolvedField<Path, TMethod, Acc, "query">>>;
|
|
80
|
-
params: Simplify<PathParams<Path
|
|
83
|
+
params: Simplify<ResolveParams<PathParams<Path>, MergePart<Validators extends {
|
|
81
84
|
params?: infer P;
|
|
82
|
-
} ? P : unknown, RouteResolvedField<Path, TMethod, Acc, "params"
|
|
85
|
+
} ? P : unknown, RouteResolvedField<Path, TMethod, Acc, "params">>>>;
|
|
83
86
|
body: Simplify<MergePart<Validators extends {
|
|
84
87
|
body?: infer B;
|
|
85
88
|
} ? B : unknown, RouteResolvedField<Path, TMethod, Acc, "body">>>;
|
|
@@ -96,15 +99,15 @@ export type RouteHandleContextWithoutBody<Path extends RoutePath, TMethod extend
|
|
|
96
99
|
query: Simplify<MergePart<Validators extends {
|
|
97
100
|
query?: infer Q;
|
|
98
101
|
} ? Q : unknown, RouteResolvedField<Path, TMethod, Acc, "query">>>;
|
|
99
|
-
params: Simplify<PathParams<Path
|
|
102
|
+
params: Simplify<ResolveParams<PathParams<Path>, MergePart<Validators extends {
|
|
100
103
|
params?: infer P;
|
|
101
|
-
} ? P : unknown, RouteResolvedField<Path, TMethod, Acc, "params"
|
|
104
|
+
} ? P : unknown, RouteResolvedField<Path, TMethod, Acc, "params">>>>;
|
|
102
105
|
body: never;
|
|
103
106
|
state: Simplify<RouteResolvedField<Path, TMethod, Acc, "state">>;
|
|
104
107
|
headers: TaserHeaders;
|
|
105
108
|
cookies: TaserCookieJar;
|
|
106
109
|
}>;
|
|
107
|
-
type RouteResolvedInputField<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], Field extends "query" | "params" | "body"> =
|
|
110
|
+
type RouteResolvedInputField<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], Field extends "query" | "params" | "body"> = RouteLayoutInputField<Path, TMethod, Field> & MergeMiddlewareInputField<Acc, Field>;
|
|
108
111
|
type IsNever<T> = [T] extends [never] ? true : false;
|
|
109
112
|
type IsEmptyObject<T> = [keyof T] extends [never] ? true : false;
|
|
110
113
|
export type IsLayoutAllowed<TRequiredLayouts, TChain extends readonly LayoutId[]> = [
|
|
@@ -119,11 +122,11 @@ type RouteQueryInput<Path extends RoutePath, TMethod extends Method, Acc extends
|
|
|
119
122
|
} ? QI : unknown, Validators extends {
|
|
120
123
|
query?: infer Q;
|
|
121
124
|
} ? Q : unknown>, RouteResolvedInputField<Path, TMethod, Acc, "query">>>;
|
|
122
|
-
type RouteParamsInput<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], Validators extends ValidatorParts> = Simplify<PathParams<Path
|
|
125
|
+
type RouteParamsInput<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], Validators extends ValidatorParts> = Simplify<ResolveParams<PathParams<Path>, MergePart<RequestShape<Validators extends {
|
|
123
126
|
paramsIn?: infer PI;
|
|
124
127
|
} ? PI : unknown, Validators extends {
|
|
125
128
|
params?: infer P;
|
|
126
|
-
} ? P : unknown>, RouteResolvedInputField<Path, TMethod, Acc, "params"
|
|
129
|
+
} ? P : unknown>, RouteResolvedInputField<Path, TMethod, Acc, "params">>>>;
|
|
127
130
|
type RouteBodyInput<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], Validators extends ValidatorParts> = Simplify<MergePart<RequestShape<Validators extends {
|
|
128
131
|
bodyIn?: infer BI;
|
|
129
132
|
} ? BI : unknown, Validators extends {
|
|
@@ -131,14 +134,15 @@ type RouteBodyInput<Path extends RoutePath, TMethod extends Method, Acc extends
|
|
|
131
134
|
} ? B : unknown>, RouteResolvedInputField<Path, TMethod, Acc, "body">>>;
|
|
132
135
|
export type RouteHandleInputWithoutBody<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], Validators extends ValidatorParts = {}> = Simplify<InputFacet<RouteQueryInput<Path, TMethod, Acc, Validators>, "query"> & InputFacet<RouteParamsInput<Path, TMethod, Acc, Validators>, "params">>;
|
|
133
136
|
export type RouteHandleInput<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], Validators extends ValidatorParts = {}> = Simplify<RouteHandleInputWithoutBody<Path, TMethod, Acc, Validators> & InputFacet<RouteBodyInput<Path, TMethod, Acc, Validators>, "body">>;
|
|
134
|
-
export type
|
|
137
|
+
export type InferRouteInputFromPath<Path extends RoutePath, TMethod extends Method> = RouteEntry<Path, TMethod> extends {
|
|
135
138
|
route: infer Route;
|
|
136
139
|
} ? Route extends {
|
|
137
140
|
$Infer: {
|
|
138
141
|
Input: infer I;
|
|
139
142
|
};
|
|
140
143
|
} ? I : never : never;
|
|
141
|
-
type
|
|
144
|
+
export type MiddlewareLayoutField<Layout extends LayoutId, Field extends "query" | "params" | "body" | "state"> = MergeMiddlewareField<ResolveLayoutMiddlewares<LayoutParent<Layout>>, Field>;
|
|
145
|
+
type MiddlewareChainField<Layout extends LayoutId, Acc extends readonly unknown[], Field extends "query" | "params" | "body" | "state"> = MiddlewareLayoutField<Layout, Field> & MergeMiddlewareField<Acc, Field>;
|
|
142
146
|
export type MiddlewareChainContext<Layout extends LayoutId, Acc extends readonly unknown[], TQuery, TParams, TBody, TAppContext extends Record<string, unknown> = AppContext> = Simplify<TAppContext & UnitRuntimeContext & {
|
|
143
147
|
query: Simplify<MergePart<TQuery, MiddlewareChainField<Layout, Acc, "query">>>;
|
|
144
148
|
params: Simplify<MergePart<TParams, MiddlewareChainField<Layout, Acc, "params">>>;
|
|
@@ -177,10 +181,11 @@ export type RouteExport<Path extends RoutePath, TMethod extends Method, Acc exte
|
|
|
177
181
|
readonly middlewares: readonly MiddlewareDefinition[];
|
|
178
182
|
readonly handlerMiddlewares: readonly MiddlewareDefinition[];
|
|
179
183
|
readonly returns?: TReturns;
|
|
184
|
+
readonly bodyMode?: "json" | "form" | "urlencoded";
|
|
180
185
|
handler: (ctx: unknown) => Awaitable<Response>;
|
|
181
186
|
readonly $Infer: {
|
|
182
187
|
Context: TMethod extends "GET" | "DELETE" | "HEAD" | "OPTIONS" ? RouteHandleContextWithoutBody<Path, TMethod, Acc, {}> : RouteHandleContext<Path, TMethod, Acc, {}>;
|
|
183
|
-
|
|
188
|
+
Input: TMethod extends "GET" | "DELETE" | "HEAD" | "OPTIONS" ? RouteHandleInputWithoutBody<Path, TMethod, Acc, {}> : RouteHandleInput<Path, TMethod, Acc, {}>;
|
|
184
189
|
Output: TOutput;
|
|
185
190
|
};
|
|
186
191
|
query?: Schema<unknown>;
|
|
@@ -197,12 +202,22 @@ type RouteHandleResult<Path extends RoutePath, TMethod extends Method, Acc exten
|
|
|
197
202
|
Output: TOutput;
|
|
198
203
|
};
|
|
199
204
|
};
|
|
200
|
-
export type
|
|
205
|
+
export type RouteBuilderBase<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[] = readonly [], Validators extends ValidatorParts = {}, TReturns extends ReturnsMap = {}, TAppContext extends Record<string, unknown> = AppContext> = {
|
|
201
206
|
readonly path: Path;
|
|
202
207
|
readonly method: TMethod;
|
|
203
208
|
readonly $Infer: {
|
|
204
209
|
Context: TMethod extends "GET" | "DELETE" | "HEAD" | "OPTIONS" ? RouteHandleContextWithoutBody<Path, TMethod, Acc, Validators, TAppContext> : RouteHandleContext<Path, TMethod, Acc, Validators, TAppContext>;
|
|
210
|
+
Input: TMethod extends "GET" | "DELETE" | "HEAD" | "OPTIONS" ? RouteHandleInputWithoutBody<Path, TMethod, Acc, Validators> : RouteHandleInput<Path, TMethod, Acc, Validators>;
|
|
211
|
+
Output: TReturns;
|
|
205
212
|
};
|
|
213
|
+
query<TQuery, TQueryIn = unknown>(schema: Schema<TQuery, TQueryIn>): RouteBuilder<Path, TMethod, Acc, Omit<Validators, "query" | "queryIn"> & {
|
|
214
|
+
query: TQuery;
|
|
215
|
+
queryIn: TQueryIn;
|
|
216
|
+
}, TReturns, TAppContext>;
|
|
217
|
+
params<TParams, TParamsIn = unknown>(schema: Schema<TParams, TParamsIn>): RouteBuilder<Path, TMethod, Acc, Omit<Validators, "params" | "paramsIn"> & {
|
|
218
|
+
params: TParams;
|
|
219
|
+
paramsIn: TParamsIn;
|
|
220
|
+
}, TReturns, TAppContext>;
|
|
206
221
|
returns<const M extends ReturnsMap>(map: M): RouteBuilder<Path, TMethod, Acc, Validators, Omit<TReturns, keyof M> & M, TAppContext>;
|
|
207
222
|
use<TAcc, UReturns extends ReturnsMap = {}, TRequiredLayouts = unknown, TRequiredState = unknown>(unit: MiddlewareUnit<TAcc, UReturns, TRequiredLayouts, TRequiredState>, ..._assert: [
|
|
208
223
|
IsLayoutAllowed<TRequiredLayouts, RouteLayoutChain<Path, TMethod>>,
|
|
@@ -228,6 +243,16 @@ export type RouteBuilder<Path extends RoutePath, TMethod extends Method, Acc ext
|
|
|
228
243
|
]): RouteHandleResult<Path, TMethod, Acc, Validators, TReturns, R, TAppContext>;
|
|
229
244
|
handler<HandlerAcc extends readonly unknown[] = readonly [], HandlerValidators extends ValidatorParts = ValidatorParts, HReturns extends ReturnsMap = {}, HOutput = Response>(unit: HandlerUnit<HandlerAcc, HandlerValidators, HReturns, HOutput>): RouteHandleResult<Path, TMethod, readonly [...Acc, ...HandlerAcc], Validators, Omit<TReturns, keyof HReturns> & HReturns, HOutput, TAppContext>;
|
|
230
245
|
};
|
|
246
|
+
export type RouteBuilder<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[] = readonly [], Validators extends ValidatorParts = {}, TReturns extends ReturnsMap = {}, TAppContext extends Record<string, unknown> = AppContext> = RouteBuilderBase<Path, TMethod, Acc, Validators, TReturns, TAppContext> & (TMethod extends "GET" | "DELETE" | "HEAD" | "OPTIONS" ? {} : {
|
|
247
|
+
body<TBody, TBodyIn = unknown>(schema: Schema<TBody, TBodyIn>): RouteBuilder<Path, TMethod, Acc, Omit<Validators, "body" | "bodyIn"> & {
|
|
248
|
+
body: TBody;
|
|
249
|
+
bodyIn: TBodyIn;
|
|
250
|
+
}, TReturns, TAppContext>;
|
|
251
|
+
body<Mode extends "json" | "form" | "urlencoded", TBody, TBodyIn = unknown>(mode: Mode, schema: Schema<TBody, TBodyIn>): RouteBuilder<Path, TMethod, Acc, Omit<Validators, "body" | "bodyIn"> & {
|
|
252
|
+
body: TBody;
|
|
253
|
+
bodyIn: TBodyIn;
|
|
254
|
+
}, TReturns, TAppContext>;
|
|
255
|
+
});
|
|
231
256
|
export type HandlerBuilder<Acc extends readonly unknown[] = readonly [], Validators extends ValidatorParts = {}, TReturns extends ReturnsMap = {}, TAppContext extends Record<string, unknown> = AppContext> = {
|
|
232
257
|
returns<const M extends ReturnsMap>(map: M): HandlerBuilder<Acc, Validators, Omit<TReturns, keyof M> & M, TAppContext>;
|
|
233
258
|
use<TAcc, UReturns extends ReturnsMap = {}, TRequiredLayouts = unknown, TRequiredState = unknown>(unit: MiddlewareUnit<TAcc, UReturns, TRequiredLayouts, TRequiredState>, ..._assert: [IsStateSatisfied<MergeMiddlewareField<Acc, "state">, TRequiredState>] extends [
|
|
@@ -254,3 +279,19 @@ export type HandlerBuilder<Acc extends readonly unknown[] = readonly [], Validat
|
|
|
254
279
|
}
|
|
255
280
|
]): HandlerUnit<Acc, Validators, TReturns, R>;
|
|
256
281
|
};
|
|
282
|
+
export type RouteDefinition<Path extends RoutePath = RoutePath, TMethod extends Method = Method, Acc extends readonly unknown[] = readonly unknown[], Validators extends ValidatorParts = ValidatorParts, TReturns extends ReturnsMap = ReturnsMap, TOutput = Response, TAppContext extends Record<string, unknown> = AppContext> = RouteHandleResult<Path, TMethod, Acc, Validators, TReturns, TOutput, TAppContext>;
|
|
283
|
+
export type InferRouteContext<R> = R extends {
|
|
284
|
+
$Infer: {
|
|
285
|
+
Context: infer C;
|
|
286
|
+
};
|
|
287
|
+
} ? C : never;
|
|
288
|
+
export type InferRouteInput<R> = R extends {
|
|
289
|
+
$Infer: {
|
|
290
|
+
Input: infer I;
|
|
291
|
+
};
|
|
292
|
+
} ? I : never;
|
|
293
|
+
export type InferRouteOutput<R> = R extends {
|
|
294
|
+
$Infer: {
|
|
295
|
+
Output: infer O;
|
|
296
|
+
};
|
|
297
|
+
} ? O : never;
|
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
import { ReplyOf } from '@taserjs/router-utils';
|
|
1
|
+
import { ReplyOf } from '@taserjs/router-utils/reply';
|
|
2
|
+
import { StatusCode } from '@taserjs/router-utils';
|
|
2
3
|
import { Simplify } from './type-utils.js';
|
|
3
4
|
import { Schema, InferOutput } from './schema.js';
|
|
4
|
-
|
|
5
|
-
* Known HTTP status codes. `number & {}` allows custom codes while keeping
|
|
6
|
-
* literal autocomplete / inference for well-known values.
|
|
7
|
-
*/
|
|
8
|
-
export type StatusCode = 100 | 101 | 102 | 103 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 226 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 | (number & {});
|
|
5
|
+
export type { StatusCode };
|
|
9
6
|
/** Status-code → Standard Schema map for route/middleware/handler outputs. */
|
|
10
7
|
export type ReturnsMap = {
|
|
11
|
-
readonly [
|
|
8
|
+
readonly [status: number]: Schema<unknown> | undefined;
|
|
12
9
|
};
|
|
13
10
|
/** Later map wins on overlapping status keys. */
|
|
14
11
|
export type MergeReturns<A extends ReturnsMap, B extends ReturnsMap> = Omit<A, keyof B> & B;
|
|
15
12
|
/** Typed reply union for statuses declared in a returns map. */
|
|
16
|
-
export type
|
|
17
|
-
[S in keyof M
|
|
18
|
-
}[keyof M];
|
|
13
|
+
export type ReplyFor<M extends ReturnsMap> = {
|
|
14
|
+
[S in keyof M & number]: M[S] extends Schema<unknown> ? ReplyOf<S, Simplify<InferOutput<M[S]>>> : never;
|
|
15
|
+
}[keyof M & number];
|
|
19
16
|
export type EmptyReturns = {};
|
|
20
17
|
/** True when no status schemas have been declared yet. */
|
|
21
18
|
export type HasReturns<M extends ReturnsMap> = [keyof M] extends [never] ? false : true;
|
|
@@ -34,4 +31,4 @@ export type EnforceHandlerReply<R, M extends ReturnsMap> = [R] extends [ValidHan
|
|
|
34
31
|
* Expected `.handler` return type for a returns map.
|
|
35
32
|
* Prefer constraining handler generics with {@link EnforceHandlerReply}.
|
|
36
33
|
*/
|
|
37
|
-
export type HandlerReply<M extends ReturnsMap> = HasReturns<M> extends true ?
|
|
34
|
+
export type HandlerReply<M extends ReturnsMap> = HasReturns<M> extends true ? ReplyFor<M> | Response : Response;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { TaserCookieJar, TaserHeaders } from '@taserjs/router-core';
|
|
2
|
+
import { HttpMethod, HttpVerb } from '@taserjs/router-utils/http';
|
|
3
|
+
export type Method = HttpMethod;
|
|
4
|
+
export type { HttpMethod, HttpVerb };
|
|
3
5
|
export type MiddlewareFieldName = "query" | "params" | "body" | "state";
|
|
4
6
|
export type MiddlewareInputFieldName = "query" | "params" | "body";
|
|
5
7
|
export type UnwrapPart<T> = unknown extends T ? {} : T;
|
|
@@ -37,13 +39,12 @@ export type MiddlewareInputField<Middleware, Field extends MiddlewareInputFieldN
|
|
|
37
39
|
} ? V : {};
|
|
38
40
|
export type MergeMiddlewareField<Middlewares extends readonly unknown[], Field extends MiddlewareFieldName> = [Middlewares] extends [readonly []] ? {} : UnionToIntersection<MiddlewareField<Middlewares[number], Field>>;
|
|
39
41
|
export type MergeMiddlewareInputField<Middlewares extends readonly unknown[], Field extends MiddlewareInputFieldName> = [Middlewares] extends [readonly []] ? {} : UnionToIntersection<MiddlewareInputField<Middlewares[number], Field>>;
|
|
40
|
-
export type RuntimeContextFields
|
|
42
|
+
export type RuntimeContextFields = {
|
|
41
43
|
request: Request;
|
|
42
44
|
method: Method;
|
|
43
45
|
url: URL;
|
|
44
|
-
headers:
|
|
45
|
-
cookies:
|
|
46
|
+
headers: TaserHeaders;
|
|
47
|
+
cookies: TaserCookieJar;
|
|
46
48
|
var: Record<string, unknown>;
|
|
47
|
-
native?: TNative;
|
|
48
49
|
};
|
|
49
|
-
export
|
|
50
|
+
export type UnitRuntimeContext = Omit<RuntimeContextFields, "var">;
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import { Awaitable, TaserCookieJar, TaserHeaders } from '@taserjs/router-core';
|
|
2
|
-
import {
|
|
3
|
-
import { RouterRegister } from '../register.js';
|
|
4
|
-
import { MergeMiddlewareField, MergePart, RequestShape, RuntimeContextFields, Simplify, UnwrapPart } from './type-utils.js';
|
|
1
|
+
import { Awaitable, MiddlewareDefinition as CoreMiddlewareDefinition, TaserCookieJar, TaserHeaders } from '@taserjs/router-core';
|
|
2
|
+
import { MergeMiddlewareField, MergePart, RequestShape, Simplify, UnitRuntimeContext, UnwrapPart } from './type-utils.js';
|
|
5
3
|
import { ReturnsMap } from './returns.js';
|
|
6
4
|
import { Schema } from './schema.js';
|
|
7
5
|
export type { HttpMethod, Method } from './type-utils.js';
|
|
8
6
|
export type { EmptyReturns, MergeReturns, ReturnsMap, HandlerReply, HasReturns, StatusCode, ValidHandlerReply, EnforceHandlerReply, } from './returns.js';
|
|
9
7
|
/** Default empty app context for standalone units without a bound router instance. */
|
|
10
8
|
export type AppContext = Record<never, never>;
|
|
11
|
-
export type NativeContext = RouterRegister extends {
|
|
12
|
-
NativeContext: infer N;
|
|
13
|
-
} ? N : unknown;
|
|
14
9
|
export type ValidatorParts = {
|
|
15
10
|
query?: unknown;
|
|
16
11
|
params?: unknown;
|
|
@@ -20,7 +15,7 @@ export type ValidatorParts = {
|
|
|
20
15
|
bodyIn?: unknown;
|
|
21
16
|
};
|
|
22
17
|
export declare const StateBrand: unique symbol;
|
|
23
|
-
export type NextResult<TState = unknown> =
|
|
18
|
+
export type NextResult<TState = unknown> = Response & {
|
|
24
19
|
readonly [StateBrand]?: TState;
|
|
25
20
|
};
|
|
26
21
|
export type ExtractState<T> = [Extract<Awaited<T>, {
|
|
@@ -33,13 +28,7 @@ export type ExtractState<T> = [Extract<Awaited<T>, {
|
|
|
33
28
|
export type IsUnknown<T> = [unknown] extends [T] ? true : false;
|
|
34
29
|
export type NextFn<TExpectedState = unknown> = IsUnknown<TExpectedState> extends true ? <S extends Record<string, unknown> = {}>(state?: S) => Promise<NextResult<S>> : (state: TExpectedState) => Promise<NextResult<TExpectedState>>;
|
|
35
30
|
export type MiddlewareNext = NextFn;
|
|
36
|
-
export type MiddlewareDefinition =
|
|
37
|
-
query?: unknown;
|
|
38
|
-
params?: unknown;
|
|
39
|
-
body?: unknown;
|
|
40
|
-
returns?: ReturnsMap;
|
|
41
|
-
handler: (ctx: unknown, next: MiddlewareNext) => Awaitable<ReplyResult | Response | unknown>;
|
|
42
|
-
};
|
|
31
|
+
export type MiddlewareDefinition = CoreMiddlewareDefinition<ReturnsMap>;
|
|
43
32
|
export type MiddlewareReturnFromParts<TQuery, TParams, TBody, TState, TQueryIn = TQuery, TParamsIn = TParams, TBodyIn = TBody> = {
|
|
44
33
|
query: Simplify<UnwrapPart<TQuery>>;
|
|
45
34
|
params: Simplify<UnwrapPart<TParams>>;
|
|
@@ -52,7 +41,7 @@ export type MiddlewareReturnFromParts<TQuery, TParams, TBody, TState, TQueryIn =
|
|
|
52
41
|
body: RequestShape<TBodyIn, TBody>;
|
|
53
42
|
};
|
|
54
43
|
};
|
|
55
|
-
type
|
|
44
|
+
export type DefineMiddlewareResult<TQuery, TParams, TBody, TState, R, TQueryIn = TQuery, TParamsIn = TParams, TBodyIn = TBody, TReturns extends ReturnsMap = {}, TLayout = null, TRequires = {}> = MiddlewareUnit<MiddlewareReturnFromParts<TQuery, TParams, TBody, IsUnknown<TState> extends true ? ExtractState<R> : TState, TQueryIn, TParamsIn, TBodyIn>, TReturns, TLayout, TRequires>;
|
|
56
45
|
export type StandaloneMiddlewareContext<TQuery = unknown, TParams = unknown, TBody = unknown, TAppContext extends Record<string, unknown> = AppContext, TState = {}> = Simplify<TAppContext & UnitRuntimeContext & {
|
|
57
46
|
query: Simplify<UnwrapPart<TQuery>>;
|
|
58
47
|
params: Simplify<UnwrapPart<TParams>>;
|
|
@@ -87,7 +76,7 @@ export type HandlerUnit<_Acc extends readonly unknown[], _Validators extends Val
|
|
|
87
76
|
Output: TOutput;
|
|
88
77
|
};
|
|
89
78
|
middlewares: readonly MiddlewareDefinition[];
|
|
90
|
-
handler: (ctx: unknown) => Awaitable<
|
|
79
|
+
handler: (ctx: unknown) => Awaitable<Response>;
|
|
91
80
|
returns?: ReturnsMap;
|
|
92
81
|
query?: Schema<unknown>;
|
|
93
82
|
params?: Schema<unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"units.js","names":[],"sources":["../../../src/types/units.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"units.js","names":[],"sources":["../../../src/types/units.ts"],"sourcesContent":["import type {\n Awaitable,\n MiddlewareDefinition as CoreMiddlewareDefinition,\n TaserCookieJar,\n TaserHeaders,\n} from \"@taserjs/router-core\";\n\nimport type {\n MergeMiddlewareField,\n MergePart,\n RequestShape,\n Simplify,\n UnitRuntimeContext,\n UnwrapPart,\n} from \"./type-utils.js\";\nimport type { ReturnsMap } from \"./returns.js\";\nimport type { Schema } from \"./schema.js\";\n\nexport type { HttpMethod, Method } from \"./type-utils.js\";\nexport type {\n EmptyReturns,\n MergeReturns,\n ReturnsMap,\n HandlerReply,\n HasReturns,\n StatusCode,\n ValidHandlerReply,\n EnforceHandlerReply,\n} from \"./returns.js\";\n\n/** Default empty app context for standalone units without a bound router instance. */\nexport type AppContext = Record<never, never>;\n\nexport type ValidatorParts = {\n query?: unknown;\n params?: unknown;\n body?: unknown;\n queryIn?: unknown;\n paramsIn?: unknown;\n bodyIn?: unknown;\n};\n\nexport declare const StateBrand: unique symbol;\n\nexport type NextResult<TState = unknown> = Response & {\n readonly [StateBrand]?: TState;\n};\n\nexport type ExtractState<T> = [Extract<Awaited<T>, { [StateBrand]?: unknown }>] extends [never]\n ? {}\n : Extract<Awaited<T>, { [StateBrand]?: unknown }> extends { [StateBrand]?: infer S }\n ? [S] extends [never]\n ? {}\n : S\n : {};\n\nexport type IsUnknown<T> = [unknown] extends [T] ? true : false;\n\nexport type NextFn<TExpectedState = unknown> =\n IsUnknown<TExpectedState> extends true\n ? <S extends Record<string, unknown> = {}>(state?: S) => Promise<NextResult<S>>\n : (state: TExpectedState) => Promise<NextResult<TExpectedState>>;\n\nexport type MiddlewareNext = NextFn;\n\nexport type MiddlewareDefinition = CoreMiddlewareDefinition<ReturnsMap>;\n\nexport type MiddlewareReturnFromParts<\n TQuery,\n TParams,\n TBody,\n TState,\n TQueryIn = TQuery,\n TParamsIn = TParams,\n TBodyIn = TBody,\n> = {\n query: Simplify<UnwrapPart<TQuery>>;\n params: Simplify<UnwrapPart<TParams>>;\n body: Simplify<UnwrapPart<TBody>>;\n state: Simplify<UnwrapPart<TState>>;\n /** Pre-parse shapes merged into route `$Infer.Input`. */\n input: {\n query: RequestShape<TQueryIn, TQuery>;\n params: RequestShape<TParamsIn, TParams>;\n body: RequestShape<TBodyIn, TBody>;\n };\n};\n\nexport type DefineMiddlewareResult<\n TQuery,\n TParams,\n TBody,\n TState,\n R,\n TQueryIn = TQuery,\n TParamsIn = TParams,\n TBodyIn = TBody,\n TReturns extends ReturnsMap = {},\n TLayout = null,\n TRequires = {},\n> = MiddlewareUnit<\n MiddlewareReturnFromParts<\n TQuery,\n TParams,\n TBody,\n IsUnknown<TState> extends true ? ExtractState<R> : TState,\n TQueryIn,\n TParamsIn,\n TBodyIn\n >,\n TReturns,\n TLayout,\n TRequires\n>;\n\nexport type StandaloneMiddlewareContext<\n TQuery = unknown,\n TParams = unknown,\n TBody = unknown,\n TAppContext extends Record<string, unknown> = AppContext,\n TState = {},\n> = Simplify<\n TAppContext &\n UnitRuntimeContext & {\n query: Simplify<UnwrapPart<TQuery>>;\n params: Simplify<UnwrapPart<TParams>>;\n body: Simplify<UnwrapPart<TBody>>;\n state: Simplify<UnwrapPart<TState>>;\n headers: TaserHeaders;\n cookies: TaserCookieJar;\n }\n>;\n\nexport type HandlerContext<\n Acc extends readonly unknown[],\n Validators extends ValidatorParts,\n TAppContext extends Record<string, unknown> = AppContext,\n> = Simplify<\n TAppContext &\n UnitRuntimeContext & {\n query: Simplify<\n MergePart<\n Validators extends { query?: infer Q } ? Q : unknown,\n MergeMiddlewareField<Acc, \"query\">\n >\n >;\n params: Simplify<\n MergePart<\n Validators extends { params?: infer P } ? P : unknown,\n MergeMiddlewareField<Acc, \"params\">\n >\n >;\n body: Simplify<\n MergePart<\n Validators extends { body?: infer B } ? B : unknown,\n MergeMiddlewareField<Acc, \"body\">\n >\n >;\n state: Simplify<MergeMiddlewareField<Acc, \"state\">>;\n headers: TaserHeaders;\n cookies: TaserCookieJar;\n }\n>;\n\nexport type MiddlewareUnit<\n TAcc = unknown,\n TReturns extends ReturnsMap = {},\n TRequiredLayouts = unknown,\n TRequiredState = unknown,\n> = MiddlewareDefinition & {\n readonly __middlewareAcc: TAcc;\n readonly __returns?: TReturns;\n readonly __requiredLayouts?: TRequiredLayouts;\n readonly __requiredState?: TRequiredState;\n};\n\nexport type HandlerUnit<\n _Acc extends readonly unknown[],\n _Validators extends ValidatorParts,\n TReturns extends ReturnsMap = {},\n TOutput = Response,\n> = {\n readonly __returns?: TReturns;\n readonly $Infer: {\n Output: TOutput;\n };\n middlewares: readonly MiddlewareDefinition[];\n handler: (ctx: unknown) => Awaitable<Response>;\n returns?: ReturnsMap;\n query?: Schema<unknown>;\n params?: Schema<unknown>;\n body?: Schema<unknown>;\n};\n\nexport type InlineMiddlewareOptions<\n Ctx = unknown,\n TQuery = unknown,\n TParams = unknown,\n TBody = unknown,\n TReturns extends ReturnsMap = {},\n TQueryIn = unknown,\n TParamsIn = unknown,\n TBodyIn = unknown,\n R = unknown,\n> = {\n query?: Schema<TQuery, TQueryIn>;\n params?: Schema<TParams, TParamsIn>;\n body?: Schema<TBody, TBodyIn>;\n returns?: TReturns;\n handler: (ctx: Ctx, next: NextFn) => Awaitable<R>;\n};\n\nexport function isHandlerUnit(\n value: unknown,\n): value is HandlerUnit<readonly unknown[], ValidatorParts> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"handler\" in value &&\n \"middlewares\" in value &&\n Array.isArray((value as HandlerUnit<readonly unknown[], ValidatorParts>).middlewares)\n );\n}\n"],"mappings":";AAoNA,SAAgB,cACd,OAC0D;CAC1D,OACE,OAAO,UAAU,YACjB,UAAU,QACV,aAAa,SACb,iBAAiB,SACjB,MAAM,QAAS,MAA0D,WAAW;AAExF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taserjs/router",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Type-safe Node.js router with runtime validation and middleware",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"repository": {
|
|
@@ -147,8 +147,8 @@
|
|
|
147
147
|
"dependencies": {
|
|
148
148
|
"@standard-schema/spec": "^1.1.0",
|
|
149
149
|
"hono": "^4.10.3",
|
|
150
|
-
"@taserjs/router-core": "0.0
|
|
151
|
-
"@taserjs/router-utils": "0.0
|
|
150
|
+
"@taserjs/router-core": "0.1.0",
|
|
151
|
+
"@taserjs/router-utils": "0.1.0"
|
|
152
152
|
},
|
|
153
153
|
"devDependencies": {
|
|
154
154
|
"@tanstack/vite-config": "^0.6.0",
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { RouteManifestShape, TaserRuntime } from "@taserjs/router-core";
|
|
2
|
+
|
|
3
|
+
export class TaserServeView<THasNotFound extends boolean = boolean> {
|
|
4
|
+
readonly fetch: (
|
|
5
|
+
request: Request,
|
|
6
|
+
env?: unknown,
|
|
7
|
+
executionCtx?: unknown,
|
|
8
|
+
) => THasNotFound extends true
|
|
9
|
+
? Promise<Response> | Response
|
|
10
|
+
: Promise<Response | undefined> | Response | undefined;
|
|
11
|
+
|
|
12
|
+
readonly request: (
|
|
13
|
+
path: string,
|
|
14
|
+
init?: RequestInit,
|
|
15
|
+
) => THasNotFound extends true ? Promise<Response> : Promise<Response | undefined>;
|
|
16
|
+
|
|
17
|
+
constructor(protected readonly runtime: TaserRuntime<THasNotFound>) {
|
|
18
|
+
this.fetch = (request: Request, env?: unknown, executionCtx?: unknown) => {
|
|
19
|
+
return this.runtime.fetch(request, env, executionCtx as never);
|
|
20
|
+
};
|
|
21
|
+
this.request = (path: string, init?: RequestInit) => {
|
|
22
|
+
return this.runtime.request(path, init);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class TaserApp<
|
|
28
|
+
TManifest extends RouteManifestShape = RouteManifestShape,
|
|
29
|
+
THasNotFound extends boolean = boolean,
|
|
30
|
+
> extends TaserServeView<THasNotFound> {
|
|
31
|
+
readonly __manifest?: TManifest;
|
|
32
|
+
|
|
33
|
+
constructor(runtime: TaserRuntime<THasNotFound>, manifest?: TManifest) {
|
|
34
|
+
super(runtime);
|
|
35
|
+
if (manifest !== undefined) {
|
|
36
|
+
this.__manifest = manifest;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { createRouteBuilder } from "./route.js";
|
|
2
|
+
import type { RouteBuilder, RoutePath } from "../types/index.js";
|
|
3
|
+
import type { AppContext, HttpMethod } from "../types/units.js";
|
|
4
|
+
|
|
5
|
+
export type CreateWithoutBodyRoute<
|
|
6
|
+
M extends "GET" | "DELETE" | "OPTIONS" | "HEAD",
|
|
7
|
+
TAppContext extends Record<string, unknown> = AppContext,
|
|
8
|
+
> = <const Path extends RoutePath>(
|
|
9
|
+
path: Path,
|
|
10
|
+
) => RouteBuilder<Path, M, readonly [], {}, {}, TAppContext>;
|
|
11
|
+
|
|
12
|
+
export type CreateWithBodyRoute<
|
|
13
|
+
M extends "POST" | "PUT" | "PATCH",
|
|
14
|
+
TAppContext extends Record<string, unknown> = AppContext,
|
|
15
|
+
> = <const Path extends RoutePath>(
|
|
16
|
+
path: Path,
|
|
17
|
+
) => RouteBuilder<Path, M, readonly [], {}, {}, TAppContext>;
|
|
18
|
+
|
|
19
|
+
export type CreateAnyRoute<TAppContext extends Record<string, unknown> = AppContext> = <
|
|
20
|
+
const Path extends RoutePath,
|
|
21
|
+
const Methods extends readonly HttpMethod[],
|
|
22
|
+
>(
|
|
23
|
+
path: Path,
|
|
24
|
+
methods: Methods,
|
|
25
|
+
) => RouteBuilder<Path, Methods[number], readonly [], {}, {}, TAppContext>;
|
|
26
|
+
|
|
27
|
+
export type CreateAllRoute<TAppContext extends Record<string, unknown> = AppContext> = <
|
|
28
|
+
const Path extends RoutePath,
|
|
29
|
+
>(
|
|
30
|
+
path: Path,
|
|
31
|
+
) => RouteBuilder<Path, HttpMethod, readonly [], {}, {}, TAppContext>;
|
|
32
|
+
|
|
33
|
+
function createWithoutBodyRoute<M extends "GET" | "DELETE" | "OPTIONS" | "HEAD">(
|
|
34
|
+
method: M,
|
|
35
|
+
): CreateWithoutBodyRoute<M> {
|
|
36
|
+
return ((path: string) =>
|
|
37
|
+
createRouteBuilder(path, method)) as unknown as CreateWithoutBodyRoute<M>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function createWithBodyRoute<M extends "POST" | "PUT" | "PATCH">(
|
|
41
|
+
method: M,
|
|
42
|
+
): CreateWithBodyRoute<M> {
|
|
43
|
+
return ((path: string) => createRouteBuilder(path, method)) as unknown as CreateWithBodyRoute<M>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const createGetRoute = createWithoutBodyRoute("GET");
|
|
47
|
+
export const createDeleteRoute = createWithoutBodyRoute("DELETE");
|
|
48
|
+
export const createOptionsRoute = createWithoutBodyRoute("OPTIONS");
|
|
49
|
+
export const createHeadRoute = createWithoutBodyRoute("HEAD");
|
|
50
|
+
export const createPostRoute = createWithBodyRoute("POST");
|
|
51
|
+
export const createPutRoute = createWithBodyRoute("PUT");
|
|
52
|
+
export const createPatchRoute = createWithBodyRoute("PATCH");
|
|
53
|
+
|
|
54
|
+
export const createAnyRoute: CreateAnyRoute = ((path: string, methods: readonly HttpMethod[]) =>
|
|
55
|
+
createRouteBuilder(path, "ANY", methods)) as unknown as CreateAnyRoute;
|
|
56
|
+
|
|
57
|
+
export const createAllRoute: CreateAllRoute = ((path: string) =>
|
|
58
|
+
createRouteBuilder(path, "ALL")) as unknown as CreateAllRoute;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { LayoutId, MiddlewareBuilder } from "
|
|
2
|
-
import type { MiddlewareDefinition } from "
|
|
1
|
+
import type { LayoutId, MiddlewareBuilder } from "../types/index.js";
|
|
2
|
+
import type { MiddlewareDefinition } from "../types/units.js";
|
|
3
3
|
|
|
4
4
|
export function createMiddleware<const Layout extends LayoutId>(
|
|
5
5
|
layout: Layout,
|
|
@@ -5,12 +5,20 @@ import {
|
|
|
5
5
|
mergeReturnsMaps,
|
|
6
6
|
withAuto422,
|
|
7
7
|
} from "@taserjs/router-utils";
|
|
8
|
+
import type { BodyMode } from "@taserjs/router-core";
|
|
8
9
|
|
|
9
|
-
import type {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
import type {
|
|
11
|
+
Method,
|
|
12
|
+
RouteBuilder,
|
|
13
|
+
RoutePath,
|
|
14
|
+
ReturnsMap,
|
|
15
|
+
ValidatorParts,
|
|
16
|
+
Schema,
|
|
17
|
+
} from "../types/index.js";
|
|
18
|
+
import type { HttpMethod, MiddlewareDefinition } from "../types/units.js";
|
|
19
|
+
import { isHandlerUnit } from "../types/units.js";
|
|
12
20
|
import { HANDLER_SCHEMA_KEY_MAP } from "./constants.js";
|
|
13
|
-
import { pickDefinedSchemas, type SchemaValidators } from "
|
|
21
|
+
import { pickDefinedSchemas, type SchemaValidators } from "../define/validators.js";
|
|
14
22
|
|
|
15
23
|
function toUtilsMap(map: ReturnsMap | undefined): Record<number, StandardSchemaV1> {
|
|
16
24
|
if (!map) {
|
|
@@ -69,15 +77,36 @@ function buildRouteBase(
|
|
|
69
77
|
export function createRouteBuilder(
|
|
70
78
|
path: string,
|
|
71
79
|
method: HttpMethod | "ANY" | "ALL",
|
|
72
|
-
validators: SchemaValidators = {},
|
|
73
80
|
methods?: readonly HttpMethod[],
|
|
74
81
|
): RouteBuilder<RoutePath, Method, readonly [], ValidatorParts> {
|
|
75
82
|
const middlewares: MiddlewareDefinition[] = [];
|
|
76
83
|
let routeReturns: Record<number, StandardSchemaV1> = {};
|
|
84
|
+
const validators: SchemaValidators = {};
|
|
85
|
+
let bodyMode: BodyMode | undefined;
|
|
77
86
|
|
|
78
87
|
const builder = {
|
|
79
88
|
path,
|
|
80
89
|
method,
|
|
90
|
+
query(schema: Schema<unknown>) {
|
|
91
|
+
validators.query = schema;
|
|
92
|
+
return builder;
|
|
93
|
+
},
|
|
94
|
+
params(schema: Schema<unknown>) {
|
|
95
|
+
validators.params = schema;
|
|
96
|
+
return builder;
|
|
97
|
+
},
|
|
98
|
+
body(modeOrSchema: BodyMode | Schema<unknown>, schema?: Schema<unknown>) {
|
|
99
|
+
if (typeof modeOrSchema === "string") {
|
|
100
|
+
bodyMode = modeOrSchema as BodyMode;
|
|
101
|
+
if (schema !== undefined) {
|
|
102
|
+
validators.body = schema;
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
bodyMode = "json";
|
|
106
|
+
validators.body = modeOrSchema;
|
|
107
|
+
}
|
|
108
|
+
return builder;
|
|
109
|
+
},
|
|
81
110
|
returns(map: ReturnsMap) {
|
|
82
111
|
routeReturns = { ...routeReturns, ...toUtilsMap(map) };
|
|
83
112
|
return builder;
|
|
@@ -90,49 +119,40 @@ export function createRouteBuilder(
|
|
|
90
119
|
const routeSchemas = pickDefinedSchemas(validators);
|
|
91
120
|
const base = buildRouteBase(path, method, methods, middlewares);
|
|
92
121
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
schemas: {
|
|
101
|
-
...validators,
|
|
102
|
-
handlerQuery: fnOrUnit.query,
|
|
103
|
-
handlerParams: fnOrUnit.params,
|
|
104
|
-
handlerBody: fnOrUnit.body,
|
|
105
|
-
middlewares,
|
|
106
|
-
handlerMiddlewares: fnOrUnit.middlewares,
|
|
107
|
-
},
|
|
108
|
-
});
|
|
122
|
+
const unit = isHandlerUnit(fnOrUnit)
|
|
123
|
+
? fnOrUnit
|
|
124
|
+
: {
|
|
125
|
+
handler: fnOrUnit as (ctx: unknown) => Response | Promise<Response>,
|
|
126
|
+
middlewares: [] as MiddlewareDefinition[],
|
|
127
|
+
returns: undefined as ReturnsMap | undefined,
|
|
128
|
+
};
|
|
109
129
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
handler: fnOrUnit.handler,
|
|
114
|
-
...routeSchemas,
|
|
115
|
-
...handlerSchemas,
|
|
116
|
-
...(returns ? { returns } : {}),
|
|
117
|
-
};
|
|
118
|
-
}
|
|
130
|
+
const handlerSchemas = isHandlerUnit(fnOrUnit)
|
|
131
|
+
? pickDefinedSchemas(fnOrUnit, HANDLER_SCHEMA_KEY_MAP)
|
|
132
|
+
: {};
|
|
119
133
|
|
|
120
134
|
const returns = buildEffectiveReturns({
|
|
121
135
|
middlewareReturns: collectReturnsFromDefinitions(middlewares),
|
|
122
|
-
routeReturns
|
|
123
|
-
handlerMiddlewareReturns:
|
|
124
|
-
handlerReturns:
|
|
136
|
+
routeReturns,
|
|
137
|
+
handlerMiddlewareReturns: collectReturnsFromDefinitions(unit.middlewares),
|
|
138
|
+
handlerReturns: unit.returns,
|
|
125
139
|
schemas: {
|
|
126
140
|
...validators,
|
|
141
|
+
handlerQuery: (unit as any).query,
|
|
142
|
+
handlerParams: (unit as any).params,
|
|
143
|
+
handlerBody: (unit as any).body,
|
|
127
144
|
middlewares,
|
|
145
|
+
handlerMiddlewares: unit.middlewares,
|
|
128
146
|
},
|
|
129
147
|
});
|
|
130
148
|
|
|
131
149
|
return {
|
|
132
150
|
...base,
|
|
133
|
-
handlerMiddlewares: [],
|
|
134
|
-
handler:
|
|
151
|
+
handlerMiddlewares: [...unit.middlewares],
|
|
152
|
+
handler: unit.handler,
|
|
135
153
|
...routeSchemas,
|
|
154
|
+
...handlerSchemas,
|
|
155
|
+
...(bodyMode ? { bodyMode } : {}),
|
|
136
156
|
...(returns ? { returns } : {}),
|
|
137
157
|
};
|
|
138
158
|
},
|