@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.
Files changed (172) hide show
  1. package/dist/cjs/builder/app.cjs +27 -0
  2. package/dist/cjs/builder/app.cjs.map +1 -0
  3. package/dist/cjs/builder/app.d.cts +11 -0
  4. package/dist/cjs/{constants.cjs → builder/constants.cjs} +1 -1
  5. package/dist/cjs/builder/constants.cjs.map +1 -0
  6. package/dist/cjs/{factories.cjs → builder/factories.cjs} +5 -5
  7. package/dist/cjs/builder/factories.cjs.map +1 -0
  8. package/dist/cjs/builder/factories.d.cts +15 -0
  9. package/dist/cjs/{middleware.cjs → builder/middleware.cjs} +1 -1
  10. package/dist/cjs/builder/middleware.cjs.map +1 -0
  11. package/dist/cjs/{middleware.d.cts → builder/middleware.d.cts} +1 -1
  12. package/dist/cjs/{route.cjs → builder/route.cjs} +41 -34
  13. package/dist/cjs/builder/route.cjs.map +1 -0
  14. package/dist/cjs/builder/route.d.cts +4 -0
  15. package/dist/cjs/{taser-router.cjs → builder/router.cjs} +38 -13
  16. package/dist/cjs/builder/router.cjs.map +1 -0
  17. package/dist/{esm/taser-router.d.ts → cjs/builder/router.d.cts} +16 -11
  18. package/dist/cjs/{create-context.cjs → context/create-context.cjs} +1 -1
  19. package/dist/cjs/context/create-context.cjs.map +1 -0
  20. package/dist/cjs/{create-context.d.cts → context/create-context.d.cts} +2 -2
  21. package/dist/cjs/define/middleware.cjs +2 -2
  22. package/dist/cjs/define/middleware.cjs.map +1 -1
  23. package/dist/cjs/define/middleware.d.cts +10 -8
  24. package/dist/cjs/define/validators.cjs +1 -1
  25. package/dist/cjs/define/validators.cjs.map +1 -1
  26. package/dist/cjs/define/validators.d.cts +1 -1
  27. package/dist/cjs/index.cjs +6 -28
  28. package/dist/cjs/index.d.cts +7 -8
  29. package/dist/cjs/middleware/body-limit.cjs +2 -2
  30. package/dist/cjs/middleware/body-limit.cjs.map +1 -1
  31. package/dist/cjs/middleware/compress.cjs +2 -2
  32. package/dist/cjs/middleware/compress.cjs.map +1 -1
  33. package/dist/cjs/middleware/cors.cjs +2 -2
  34. package/dist/cjs/middleware/cors.cjs.map +1 -1
  35. package/dist/cjs/middleware/csrf.cjs +2 -2
  36. package/dist/cjs/middleware/csrf.cjs.map +1 -1
  37. package/dist/cjs/middleware/etag.cjs +2 -2
  38. package/dist/cjs/middleware/etag.cjs.map +1 -1
  39. package/dist/cjs/middleware/jwk.cjs +2 -8
  40. package/dist/cjs/middleware/jwk.cjs.map +1 -1
  41. package/dist/cjs/middleware/jwt.cjs +2 -8
  42. package/dist/cjs/middleware/jwt.cjs.map +1 -1
  43. package/dist/cjs/middleware/secure-headers.cjs +2 -2
  44. package/dist/cjs/middleware/secure-headers.cjs.map +1 -1
  45. package/dist/cjs/middleware/timing.cjs +2 -2
  46. package/dist/cjs/middleware/timing.cjs.map +1 -1
  47. package/dist/cjs/middleware/wrap-hono.cjs +10 -0
  48. package/dist/cjs/middleware/wrap-hono.cjs.map +1 -1
  49. package/dist/cjs/middleware/wrap-hono.d.cts +4 -0
  50. package/dist/cjs/reply.cjs +8 -19
  51. package/dist/cjs/reply.d.cts +1 -2
  52. package/dist/cjs/stream.cjs +8 -31
  53. package/dist/cjs/stream.d.cts +1 -1
  54. package/dist/cjs/types/app.d.cts +8 -26
  55. package/dist/cjs/types/index.d.cts +60 -19
  56. package/dist/cjs/types/returns.d.cts +8 -11
  57. package/dist/cjs/types/type-utils.d.cts +8 -7
  58. package/dist/cjs/types/units.cjs.map +1 -1
  59. package/dist/cjs/types/units.d.cts +6 -17
  60. package/dist/esm/builder/app.d.ts +11 -0
  61. package/dist/esm/builder/app.js +26 -0
  62. package/dist/esm/builder/app.js.map +1 -0
  63. package/dist/esm/{constants.js → builder/constants.js} +1 -1
  64. package/dist/esm/builder/constants.js.map +1 -0
  65. package/dist/esm/builder/factories.d.ts +15 -0
  66. package/dist/esm/{factories.js → builder/factories.js} +5 -5
  67. package/dist/esm/builder/factories.js.map +1 -0
  68. package/dist/esm/{middleware.d.ts → builder/middleware.d.ts} +1 -1
  69. package/dist/esm/{middleware.js → builder/middleware.js} +1 -1
  70. package/dist/esm/builder/middleware.js.map +1 -0
  71. package/dist/esm/builder/route.d.ts +4 -0
  72. package/dist/esm/{route.js → builder/route.js} +41 -34
  73. package/dist/esm/builder/route.js.map +1 -0
  74. package/dist/{cjs/taser-router.d.cts → esm/builder/router.d.ts} +16 -11
  75. package/dist/esm/{taser-router.js → builder/router.js} +37 -12
  76. package/dist/esm/builder/router.js.map +1 -0
  77. package/dist/esm/{create-context.d.ts → context/create-context.d.ts} +2 -2
  78. package/dist/esm/{create-context.js → context/create-context.js} +1 -1
  79. package/dist/esm/context/create-context.js.map +1 -0
  80. package/dist/esm/define/middleware.d.ts +10 -8
  81. package/dist/esm/define/middleware.js +2 -2
  82. package/dist/esm/define/middleware.js.map +1 -1
  83. package/dist/esm/define/validators.d.ts +1 -1
  84. package/dist/esm/define/validators.js +1 -1
  85. package/dist/esm/define/validators.js.map +1 -1
  86. package/dist/esm/index.d.ts +7 -8
  87. package/dist/esm/index.js +5 -6
  88. package/dist/esm/middleware/body-limit.js +2 -2
  89. package/dist/esm/middleware/body-limit.js.map +1 -1
  90. package/dist/esm/middleware/compress.js +2 -2
  91. package/dist/esm/middleware/compress.js.map +1 -1
  92. package/dist/esm/middleware/cors.js +2 -2
  93. package/dist/esm/middleware/cors.js.map +1 -1
  94. package/dist/esm/middleware/csrf.js +2 -2
  95. package/dist/esm/middleware/csrf.js.map +1 -1
  96. package/dist/esm/middleware/etag.js +2 -2
  97. package/dist/esm/middleware/etag.js.map +1 -1
  98. package/dist/esm/middleware/jwk.js +2 -8
  99. package/dist/esm/middleware/jwk.js.map +1 -1
  100. package/dist/esm/middleware/jwt.js +2 -8
  101. package/dist/esm/middleware/jwt.js.map +1 -1
  102. package/dist/esm/middleware/secure-headers.js +2 -2
  103. package/dist/esm/middleware/secure-headers.js.map +1 -1
  104. package/dist/esm/middleware/timing.js +2 -2
  105. package/dist/esm/middleware/timing.js.map +1 -1
  106. package/dist/esm/middleware/wrap-hono.d.ts +4 -0
  107. package/dist/esm/middleware/wrap-hono.js +10 -1
  108. package/dist/esm/middleware/wrap-hono.js.map +1 -1
  109. package/dist/esm/reply.d.ts +1 -2
  110. package/dist/esm/reply.js +1 -2
  111. package/dist/esm/stream.d.ts +1 -1
  112. package/dist/esm/stream.js +1 -2
  113. package/dist/esm/types/app.d.ts +8 -26
  114. package/dist/esm/types/index.d.ts +60 -19
  115. package/dist/esm/types/returns.d.ts +8 -11
  116. package/dist/esm/types/type-utils.d.ts +8 -7
  117. package/dist/esm/types/units.d.ts +6 -17
  118. package/dist/esm/types/units.js.map +1 -1
  119. package/package.json +3 -3
  120. package/src/builder/app.ts +39 -0
  121. package/src/builder/factories.ts +58 -0
  122. package/src/{middleware.ts → builder/middleware.ts} +2 -2
  123. package/src/{route.ts → builder/route.ts} +55 -35
  124. package/src/{taser-router.ts → builder/router.ts} +77 -28
  125. package/src/{create-context.ts → context/create-context.ts} +2 -2
  126. package/src/define/middleware.ts +115 -123
  127. package/src/define/validators.ts +1 -1
  128. package/src/index.ts +13 -20
  129. package/src/middleware/body-limit.ts +2 -2
  130. package/src/middleware/compress.ts +2 -2
  131. package/src/middleware/cors.ts +2 -2
  132. package/src/middleware/csrf.ts +2 -2
  133. package/src/middleware/etag.ts +2 -2
  134. package/src/middleware/jwk.ts +2 -7
  135. package/src/middleware/jwt.ts +2 -7
  136. package/src/middleware/secure-headers.ts +2 -2
  137. package/src/middleware/timing.ts +2 -2
  138. package/src/middleware/wrap-hono.ts +13 -0
  139. package/src/reply.ts +1 -11
  140. package/src/stream.ts +1 -1
  141. package/src/types/app.ts +13 -28
  142. package/src/types/index.ts +126 -22
  143. package/src/types/returns.ts +9 -78
  144. package/src/types/type-utils.ts +10 -6
  145. package/src/types/units.ts +36 -16
  146. package/dist/cjs/constants.cjs.map +0 -1
  147. package/dist/cjs/create-context.cjs.map +0 -1
  148. package/dist/cjs/factories.cjs.map +0 -1
  149. package/dist/cjs/factories.d.cts +0 -61
  150. package/dist/cjs/middleware.cjs.map +0 -1
  151. package/dist/cjs/route.cjs.map +0 -1
  152. package/dist/cjs/route.d.cts +0 -5
  153. package/dist/cjs/taser-app.cjs +0 -36
  154. package/dist/cjs/taser-app.cjs.map +0 -1
  155. package/dist/cjs/taser-app.d.cts +0 -18
  156. package/dist/cjs/taser-router.cjs.map +0 -1
  157. package/dist/esm/constants.js.map +0 -1
  158. package/dist/esm/create-context.js.map +0 -1
  159. package/dist/esm/factories.d.ts +0 -61
  160. package/dist/esm/factories.js.map +0 -1
  161. package/dist/esm/middleware.js.map +0 -1
  162. package/dist/esm/route.d.ts +0 -5
  163. package/dist/esm/route.js.map +0 -1
  164. package/dist/esm/taser-app.d.ts +0 -18
  165. package/dist/esm/taser-app.js +0 -35
  166. package/dist/esm/taser-app.js.map +0 -1
  167. package/dist/esm/taser-router.js.map +0 -1
  168. package/src/factories.ts +0 -185
  169. package/src/taser-app.ts +0 -38
  170. /package/dist/cjs/{constants.d.cts → builder/constants.d.cts} +0 -0
  171. /package/dist/esm/{constants.d.ts → builder/constants.d.ts} +0 -0
  172. /package/src/{constants.ts → builder/constants.ts} +0 -0
@@ -2,10 +2,10 @@ import { timing as honoTiming } from "hono/timing";
2
2
 
3
3
  import { wrapHonoMiddleware } from "./wrap-hono.js";
4
4
 
5
- const honoTimingMiddleware = wrapHonoMiddleware(honoTiming);
5
+ const wrapped = wrapHonoMiddleware(honoTiming);
6
6
 
7
7
  export function timing(...args: Parameters<typeof honoTiming>) {
8
- return honoTimingMiddleware(...args);
8
+ return wrapped(...args);
9
9
  }
10
10
 
11
11
  export type TimingOptions = NonNullable<Parameters<typeof honoTiming>[0]>;
@@ -1,3 +1,4 @@
1
+ import { createTaserCompatHandler } from "@taserjs/router-core";
1
2
  import type { MiddlewareHandler } from "hono";
2
3
 
3
4
  import { defineMiddleware } from "../define/middleware.js";
@@ -10,3 +11,15 @@ export function wrapHonoMiddleware<F extends (...args: never[]) => MiddlewareHan
10
11
  ) => MiddlewareUnit<MiddlewareReturnFromParts<unknown, unknown, unknown, {}>> {
11
12
  return (...args) => defineMiddleware(honoFactory(...args));
12
13
  }
14
+
15
+ /** Extracts the jwtPayload from Hono's variable bag and forwards it into Taser's state via next(). */
16
+ export function extractJwtPayload<TPayload>(
17
+ honoMw: MiddlewareHandler,
18
+ ): (ctx: unknown, next: (state: { jwtPayload: TPayload }) => unknown) => unknown {
19
+ const taserHandler = createTaserCompatHandler(honoMw);
20
+ return (ctx, next) =>
21
+ taserHandler(ctx, async () => {
22
+ const payload = (ctx as unknown as { var: { jwtPayload?: unknown } }).var.jwtPayload;
23
+ return next({ jwtPayload: payload as TPayload });
24
+ });
25
+ }
package/src/reply.ts CHANGED
@@ -1,11 +1 @@
1
- export { errorReply, reply, successReply } from "@taserjs/router-utils/reply";
2
- export type {
3
- BinaryBody,
4
- BodyKind,
5
- FileReplyInit,
6
- RedirectInit,
7
- ReplyBodyKind,
8
- ReplyInit,
9
- ReplyOf,
10
- SuccessReplyData,
11
- } from "@taserjs/router-utils/reply";
1
+ export * from "@taserjs/router-utils/reply";
package/src/stream.ts CHANGED
@@ -1 +1 @@
1
- export { blob, buffer, file, pipe, stream } from "@taserjs/router-utils";
1
+ export * from "@taserjs/router-utils/stream";
package/src/types/app.ts CHANGED
@@ -1,31 +1,18 @@
1
+ import type { CookieRuntimeConfig, RouteManifestShape } from "@taserjs/router-core";
1
2
  import type { ResponseValidationFailureHandler } from "@taserjs/router-utils";
2
3
 
3
- import type { TaserApp } from "../taser-app.js";
4
+ import type { TaserApp } from "../builder/app.js";
4
5
  import type { ReturnsMap } from "./returns.js";
5
6
  import type { Schema } from "./schema.js";
6
7
 
7
8
  export type CreateTaserAppOptions = {
8
- basePath?: string;
9
9
  response?: {
10
10
  /** Validate handler replies against returns maps. Default true. */
11
11
  validate?: boolean;
12
12
  onValidationFailure?: ResponseValidationFailureHandler;
13
13
  };
14
14
  /** Global cookie defaults and signing secret. Per-call `ctx.cookies.set` options override defaults. */
15
- cookies?: {
16
- secret?: string | BufferSource;
17
- path?: string;
18
- httpOnly?: boolean;
19
- sameSite?: "Strict" | "Lax" | "None" | "strict" | "lax" | "none";
20
- secure?: boolean;
21
- domain?: string;
22
- maxAge?: number;
23
- expires?: Date;
24
- };
25
- };
26
-
27
- export type CreateContextArgs = {
28
- native?: import("./units.js").NativeContext;
15
+ cookies?: CookieRuntimeConfig;
29
16
  };
30
17
 
31
18
  export type ContextDefinition<
@@ -33,7 +20,7 @@ export type ContextDefinition<
33
20
  TReq extends Record<string, unknown> = Record<string, never>,
34
21
  > = {
35
22
  boot?: () => TBoot | Promise<TBoot>;
36
- request?: (args: CreateContextArgs) => TReq | Promise<TReq>;
23
+ request?: (req: Request) => TReq | Promise<TReq>;
37
24
  };
38
25
 
39
26
  export type InferAppContext<
@@ -45,19 +32,17 @@ export type OnErrorOptions<TResponses extends ReturnsMap = ReturnsMap> = {
45
32
  handle: (error: unknown, ctx?: unknown) => Response | Promise<Response>;
46
33
  };
47
34
 
48
- export type InferAppManifest<TApp> = TApp extends TaserApp<infer TManifest> ? TManifest : never;
49
-
50
- export type TaserHandler<TFrameworkApp> = {
51
- /**
52
- * Mount the Taser handler on a framework app.
53
- * Use universal wildcard patterns (`/*`, `/prefix/*`) for Hono/Fastify.
54
- * Use framework-native splat patterns for Express (e.g. `/{*splat}`, `/*splat`).
55
- */
56
- mount(pattern: string, frameworkApp: TFrameworkApp): void;
57
- };
35
+ export type InferAppManifest<TApp> =
36
+ TApp extends TaserApp<infer TManifest, any>
37
+ ? TManifest
38
+ : TApp extends { manifest: infer TManifest }
39
+ ? TManifest
40
+ : TApp extends RouteManifestShape
41
+ ? TApp
42
+ : never;
58
43
 
59
44
  export type { RouteManifestShape } from "@taserjs/router-core";
60
45
 
61
46
  export type { Schema };
62
47
 
63
- export type { TaserApp, TaserNativeBound } from "../taser-app.js";
48
+ export type { TaserApp } from "../builder/app.js";
@@ -5,9 +5,9 @@ import type {
5
5
  MergeMiddlewareInputField,
6
6
  MergePart,
7
7
  RequestShape,
8
- RuntimeContextFields,
9
8
  Simplify,
10
9
  UnionToIntersection,
10
+ UnitRuntimeContext,
11
11
  } from "./type-utils.js";
12
12
  import type { ReturnsMap, ValidHandlerReply } from "./returns.js";
13
13
  import type { Schema } from "./schema.js";
@@ -21,7 +21,6 @@ import type {
21
21
  MiddlewareDefinition,
22
22
  MiddlewareReturnFromParts,
23
23
  MiddlewareUnit,
24
- NativeContext,
25
24
  ValidatorParts,
26
25
  } from "./units.js";
27
26
 
@@ -40,6 +39,7 @@ export type {
40
39
  MergePart,
41
40
  RequestShape,
42
41
  Simplify,
42
+ UnitRuntimeContext,
43
43
  UnwrapPart,
44
44
  } from "./type-utils.js";
45
45
  export type {
@@ -48,7 +48,7 @@ export type {
48
48
  HandlerReply,
49
49
  HasReturns,
50
50
  MergeReturns,
51
- ReplyResultFor,
51
+ ReplyFor,
52
52
  ReturnsMap,
53
53
  StatusCode,
54
54
  ValidHandlerReply,
@@ -66,7 +66,6 @@ export type {
66
66
  MiddlewareNext,
67
67
  MiddlewareReturnFromParts,
68
68
  MiddlewareUnit,
69
- NativeContext,
70
69
  NextFn,
71
70
  NextResult,
72
71
  StandaloneMiddlewareContext,
@@ -97,6 +96,13 @@ export type PathParams<Path extends string> = Path extends `/${infer Rest}`
97
96
  ? ParseParamsFromSegments<Rest>
98
97
  : {};
99
98
 
99
+ export type ResolveParams<TPathParams, TSchemaParams> =
100
+ TSchemaParams extends Record<string, unknown>
101
+ ? [keyof TSchemaParams] extends [never]
102
+ ? TPathParams
103
+ : Simplify<Omit<TPathParams, keyof TSchemaParams> & TSchemaParams>
104
+ : TPathParams;
105
+
100
106
  type LayoutParent<Layout extends LayoutId> = LayoutTree[Layout] extends {
101
107
  parent: infer Parent extends LayoutId | null;
102
108
  }
@@ -162,13 +168,29 @@ type RouteLayoutChain<Path extends RoutePath, TMethod extends Method> =
162
168
  ? readonly [RouteParent<Path, TMethod>]
163
169
  : readonly [];
164
170
 
171
+ export type RouteLayoutMiddlewares<
172
+ Path extends RoutePath,
173
+ TMethod extends Method,
174
+ > = ResolveLayoutChainMiddlewares<RouteLayoutChain<Path, TMethod>>;
175
+
176
+ export type RouteLayoutField<
177
+ Path extends RoutePath,
178
+ TMethod extends Method,
179
+ Field extends "query" | "params" | "body" | "state",
180
+ > = MergeMiddlewareField<RouteLayoutMiddlewares<Path, TMethod>, Field>;
181
+
182
+ export type RouteLayoutInputField<
183
+ Path extends RoutePath,
184
+ TMethod extends Method,
185
+ Field extends "query" | "params" | "body",
186
+ > = MergeMiddlewareInputField<RouteLayoutMiddlewares<Path, TMethod>, Field>;
187
+
165
188
  type RouteResolvedField<
166
189
  Path extends RoutePath,
167
190
  TMethod extends Method,
168
191
  Acc extends readonly unknown[],
169
192
  Field extends "query" | "params" | "body" | "state",
170
- > = MergeMiddlewareField<ResolveLayoutChainMiddlewares<RouteLayoutChain<Path, TMethod>>, Field> &
171
- MergeMiddlewareField<Acc, Field>;
193
+ > = RouteLayoutField<Path, TMethod, Field> & MergeMiddlewareField<Acc, Field>;
172
194
 
173
195
  type RouteChainField<
174
196
  Path extends RoutePath,
@@ -177,8 +199,6 @@ type RouteChainField<
177
199
  Field extends "query" | "params" | "body" | "state",
178
200
  > = RouteResolvedField<Path, TMethod, Acc, Field>;
179
201
 
180
- type UnitRuntimeContext = Omit<RuntimeContextFields<NativeContext>, "var">;
181
-
182
202
  export type RouteChainContext<
183
203
  Path extends RoutePath,
184
204
  TMethod extends Method,
@@ -192,7 +212,10 @@ export type RouteChainContext<
192
212
  UnitRuntimeContext & {
193
213
  query: Simplify<MergePart<TQuery, RouteChainField<Path, TMethod, Acc, "query">>>;
194
214
  params: Simplify<
195
- PathParams<Path> & MergePart<TParams, RouteChainField<Path, TMethod, Acc, "params">>
215
+ ResolveParams<
216
+ PathParams<Path>,
217
+ MergePart<TParams, RouteChainField<Path, TMethod, Acc, "params">>
218
+ >
196
219
  >;
197
220
  body: Simplify<MergePart<TBody, RouteChainField<Path, TMethod, Acc, "body">>>;
198
221
  state: Simplify<RouteChainField<Path, TMethod, Acc, "state">>;
@@ -223,11 +246,13 @@ export type RouteHandleContext<
223
246
  >
224
247
  >;
225
248
  params: Simplify<
226
- PathParams<Path> &
249
+ ResolveParams<
250
+ PathParams<Path>,
227
251
  MergePart<
228
252
  Validators extends { params?: infer P } ? P : unknown,
229
253
  RouteResolvedField<Path, TMethod, Acc, "params">
230
254
  >
255
+ >
231
256
  >;
232
257
  body: Simplify<
233
258
  MergePart<
@@ -262,11 +287,13 @@ export type RouteHandleContextWithoutBody<
262
287
  >
263
288
  >;
264
289
  params: Simplify<
265
- PathParams<Path> &
290
+ ResolveParams<
291
+ PathParams<Path>,
266
292
  MergePart<
267
293
  Validators extends { params?: infer P } ? P : unknown,
268
294
  RouteResolvedField<Path, TMethod, Acc, "params">
269
295
  >
296
+ >
270
297
  >;
271
298
  body: never;
272
299
  state: Simplify<RouteResolvedField<Path, TMethod, Acc, "state">>;
@@ -280,11 +307,7 @@ type RouteResolvedInputField<
280
307
  TMethod extends Method,
281
308
  Acc extends readonly unknown[],
282
309
  Field extends "query" | "params" | "body",
283
- > = MergeMiddlewareInputField<
284
- ResolveLayoutChainMiddlewares<RouteLayoutChain<Path, TMethod>>,
285
- Field
286
- > &
287
- MergeMiddlewareInputField<Acc, Field>;
310
+ > = RouteLayoutInputField<Path, TMethod, Field> & MergeMiddlewareInputField<Acc, Field>;
288
311
 
289
312
  type IsNever<T> = [T] extends [never] ? true : false;
290
313
 
@@ -348,7 +371,8 @@ type RouteParamsInput<
348
371
  Acc extends readonly unknown[],
349
372
  Validators extends ValidatorParts,
350
373
  > = Simplify<
351
- PathParams<Path> &
374
+ ResolveParams<
375
+ PathParams<Path>,
352
376
  MergePart<
353
377
  RequestShape<
354
378
  Validators extends { paramsIn?: infer PI } ? PI : unknown,
@@ -356,6 +380,7 @@ type RouteParamsInput<
356
380
  >,
357
381
  RouteResolvedInputField<Path, TMethod, Acc, "params">
358
382
  >
383
+ >
359
384
  >;
360
385
 
361
386
  type RouteBodyInput<
@@ -393,19 +418,23 @@ export type RouteHandleInput<
393
418
  InputFacet<RouteBodyInput<Path, TMethod, Acc, Validators>, "body">
394
419
  >;
395
420
 
396
- export type InferRouteInput<Path extends RoutePath, TMethod extends Method> =
421
+ export type InferRouteInputFromPath<Path extends RoutePath, TMethod extends Method> =
397
422
  RouteEntry<Path, TMethod> extends { route: infer Route }
398
423
  ? Route extends { $Infer: { Input: infer I } }
399
424
  ? I
400
425
  : never
401
426
  : never;
402
427
 
428
+ export type MiddlewareLayoutField<
429
+ Layout extends LayoutId,
430
+ Field extends "query" | "params" | "body" | "state",
431
+ > = MergeMiddlewareField<ResolveLayoutMiddlewares<LayoutParent<Layout>>, Field>;
432
+
403
433
  type MiddlewareChainField<
404
434
  Layout extends LayoutId,
405
435
  Acc extends readonly unknown[],
406
436
  Field extends "query" | "params" | "body" | "state",
407
- > = MergeMiddlewareField<ResolveLayoutMiddlewares<LayoutParent<Layout>>, Field> &
408
- MergeMiddlewareField<Acc, Field>;
437
+ > = MiddlewareLayoutField<Layout, Field> & MergeMiddlewareField<Acc, Field>;
409
438
 
410
439
  export type MiddlewareChainContext<
411
440
  Layout extends LayoutId,
@@ -505,12 +534,15 @@ export type RouteExport<
505
534
  readonly middlewares: readonly MiddlewareDefinition[];
506
535
  readonly handlerMiddlewares: readonly MiddlewareDefinition[];
507
536
  readonly returns?: TReturns;
537
+ readonly bodyMode?: "json" | "form" | "urlencoded";
508
538
  handler: (ctx: unknown) => Awaitable<Response>;
509
539
  readonly $Infer: {
510
540
  Context: TMethod extends "GET" | "DELETE" | "HEAD" | "OPTIONS"
511
541
  ? RouteHandleContextWithoutBody<Path, TMethod, Acc, {}>
512
542
  : RouteHandleContext<Path, TMethod, Acc, {}>;
513
- /** Concrete handler reply (`ReplyOf` union) for client inference. */
543
+ Input: TMethod extends "GET" | "DELETE" | "HEAD" | "OPTIONS"
544
+ ? RouteHandleInputWithoutBody<Path, TMethod, Acc, {}>
545
+ : RouteHandleInput<Path, TMethod, Acc, {}>;
514
546
  Output: TOutput;
515
547
  };
516
548
  query?: Schema<unknown>;
@@ -541,7 +573,7 @@ type RouteHandleResult<
541
573
  };
542
574
  };
543
575
 
544
- export type RouteBuilder<
576
+ export type RouteBuilderBase<
545
577
  Path extends RoutePath,
546
578
  TMethod extends Method,
547
579
  Acc extends readonly unknown[] = readonly [],
@@ -555,7 +587,31 @@ export type RouteBuilder<
555
587
  Context: TMethod extends "GET" | "DELETE" | "HEAD" | "OPTIONS"
556
588
  ? RouteHandleContextWithoutBody<Path, TMethod, Acc, Validators, TAppContext>
557
589
  : RouteHandleContext<Path, TMethod, Acc, Validators, TAppContext>;
590
+ Input: TMethod extends "GET" | "DELETE" | "HEAD" | "OPTIONS"
591
+ ? RouteHandleInputWithoutBody<Path, TMethod, Acc, Validators>
592
+ : RouteHandleInput<Path, TMethod, Acc, Validators>;
593
+ Output: TReturns;
558
594
  };
595
+ query<TQuery, TQueryIn = unknown>(
596
+ schema: Schema<TQuery, TQueryIn>,
597
+ ): RouteBuilder<
598
+ Path,
599
+ TMethod,
600
+ Acc,
601
+ Omit<Validators, "query" | "queryIn"> & { query: TQuery; queryIn: TQueryIn },
602
+ TReturns,
603
+ TAppContext
604
+ >;
605
+ params<TParams, TParamsIn = unknown>(
606
+ schema: Schema<TParams, TParamsIn>,
607
+ ): RouteBuilder<
608
+ Path,
609
+ TMethod,
610
+ Acc,
611
+ Omit<Validators, "params" | "paramsIn"> & { params: TParams; paramsIn: TParamsIn },
612
+ TReturns,
613
+ TAppContext
614
+ >;
559
615
  returns<const M extends ReturnsMap>(
560
616
  map: M,
561
617
  ): RouteBuilder<Path, TMethod, Acc, Validators, Omit<TReturns, keyof M> & M, TAppContext>;
@@ -656,6 +712,40 @@ export type RouteBuilder<
656
712
  >;
657
713
  };
658
714
 
715
+ export type RouteBuilder<
716
+ Path extends RoutePath,
717
+ TMethod extends Method,
718
+ Acc extends readonly unknown[] = readonly [],
719
+ Validators extends ValidatorParts = {},
720
+ TReturns extends ReturnsMap = {},
721
+ TAppContext extends Record<string, unknown> = AppContext,
722
+ > = RouteBuilderBase<Path, TMethod, Acc, Validators, TReturns, TAppContext> &
723
+ (TMethod extends "GET" | "DELETE" | "HEAD" | "OPTIONS"
724
+ ? {}
725
+ : {
726
+ body<TBody, TBodyIn = unknown>(
727
+ schema: Schema<TBody, TBodyIn>,
728
+ ): RouteBuilder<
729
+ Path,
730
+ TMethod,
731
+ Acc,
732
+ Omit<Validators, "body" | "bodyIn"> & { body: TBody; bodyIn: TBodyIn },
733
+ TReturns,
734
+ TAppContext
735
+ >;
736
+ body<Mode extends "json" | "form" | "urlencoded", TBody, TBodyIn = unknown>(
737
+ mode: Mode,
738
+ schema: Schema<TBody, TBodyIn>,
739
+ ): RouteBuilder<
740
+ Path,
741
+ TMethod,
742
+ Acc,
743
+ Omit<Validators, "body" | "bodyIn"> & { body: TBody; bodyIn: TBodyIn },
744
+ TReturns,
745
+ TAppContext
746
+ >;
747
+ });
748
+
659
749
  export type HandlerBuilder<
660
750
  Acc extends readonly unknown[] = readonly [],
661
751
  Validators extends ValidatorParts = {},
@@ -734,3 +824,17 @@ export type HandlerBuilder<
734
824
  ]
735
825
  ): HandlerUnit<Acc, Validators, TReturns, R>;
736
826
  };
827
+
828
+ export type RouteDefinition<
829
+ Path extends RoutePath = RoutePath,
830
+ TMethod extends Method = Method,
831
+ Acc extends readonly unknown[] = readonly unknown[],
832
+ Validators extends ValidatorParts = ValidatorParts,
833
+ TReturns extends ReturnsMap = ReturnsMap,
834
+ TOutput = Response,
835
+ TAppContext extends Record<string, unknown> = AppContext,
836
+ > = RouteHandleResult<Path, TMethod, Acc, Validators, TReturns, TOutput, TAppContext>;
837
+
838
+ export type InferRouteContext<R> = R extends { $Infer: { Context: infer C } } ? C : never;
839
+ export type InferRouteInput<R> = R extends { $Infer: { Input: infer I } } ? I : never;
840
+ export type InferRouteOutput<R> = R extends { $Infer: { Output: infer O } } ? O : never;
@@ -1,95 +1,26 @@
1
- import type { ReplyOf } from "@taserjs/router-utils";
1
+ import type { ReplyOf } from "@taserjs/router-utils/reply";
2
+ import type { StatusCode } from "@taserjs/router-utils";
2
3
 
3
4
  import type { Simplify } from "./type-utils.js";
4
5
  import type { Schema } from "./schema.js";
5
6
  import type { InferOutput } from "./schema.js";
6
7
 
7
- /**
8
- * Known HTTP status codes. `number & {}` allows custom codes while keeping
9
- * literal autocomplete / inference for well-known values.
10
- */
11
- export type StatusCode =
12
- | 100
13
- | 101
14
- | 102
15
- | 103
16
- | 200
17
- | 201
18
- | 202
19
- | 203
20
- | 204
21
- | 205
22
- | 206
23
- | 207
24
- | 208
25
- | 226
26
- | 300
27
- | 301
28
- | 302
29
- | 303
30
- | 304
31
- | 305
32
- | 306
33
- | 307
34
- | 308
35
- | 400
36
- | 401
37
- | 402
38
- | 403
39
- | 404
40
- | 405
41
- | 406
42
- | 407
43
- | 408
44
- | 409
45
- | 410
46
- | 411
47
- | 412
48
- | 413
49
- | 414
50
- | 415
51
- | 416
52
- | 417
53
- | 418
54
- | 421
55
- | 422
56
- | 423
57
- | 424
58
- | 425
59
- | 426
60
- | 428
61
- | 429
62
- | 431
63
- | 451
64
- | 500
65
- | 501
66
- | 502
67
- | 503
68
- | 504
69
- | 505
70
- | 506
71
- | 507
72
- | 508
73
- | 510
74
- | 511
75
- | (number & {});
8
+ export type { StatusCode };
76
9
 
77
10
  /** Status-code → Standard Schema map for route/middleware/handler outputs. */
78
11
  export type ReturnsMap = {
79
- readonly [K in StatusCode]?: Schema<unknown>;
12
+ readonly [status: number]: Schema<unknown> | undefined;
80
13
  };
81
14
 
82
15
  /** Later map wins on overlapping status keys. */
83
16
  export type MergeReturns<A extends ReturnsMap, B extends ReturnsMap> = Omit<A, keyof B> & B;
84
17
 
85
18
  /** Typed reply union for statuses declared in a returns map. */
86
- export type ReplyResultFor<M extends ReturnsMap> = {
87
- [S in keyof M]-?: S extends StatusCode
88
- ? M[S] extends Schema<unknown>
89
- ? ReplyOf<S, Simplify<InferOutput<M[S]>>>
90
- : never
19
+ export type ReplyFor<M extends ReturnsMap> = {
20
+ [S in keyof M & number]: M[S] extends Schema<unknown>
21
+ ? ReplyOf<S, Simplify<InferOutput<M[S]>>>
91
22
  : never;
92
- }[keyof M];
23
+ }[keyof M & number];
93
24
 
94
25
  export type EmptyReturns = {};
95
26
 
@@ -127,4 +58,4 @@ export type EnforceHandlerReply<R, M extends ReturnsMap> = [R] extends [ValidHan
127
58
  * Prefer constraining handler generics with {@link EnforceHandlerReply}.
128
59
  */
129
60
  export type HandlerReply<M extends ReturnsMap> =
130
- HasReturns<M> extends true ? ReplyResultFor<M> | Response : Response;
61
+ HasReturns<M> extends true ? ReplyFor<M> | Response : Response;
@@ -1,5 +1,8 @@
1
- export type Method = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD";
2
- export type HttpMethod = Method;
1
+ import type { TaserCookieJar, TaserHeaders } from "@taserjs/router-core";
2
+ import type { HttpMethod, HttpVerb } from "@taserjs/router-utils/http";
3
+
4
+ export type Method = HttpMethod;
5
+ export type { HttpMethod, HttpVerb };
3
6
 
4
7
  export type MiddlewareFieldName = "query" | "params" | "body" | "state";
5
8
 
@@ -71,12 +74,13 @@ export type MergeMiddlewareInputField<
71
74
  ? {}
72
75
  : UnionToIntersection<MiddlewareInputField<Middlewares[number], Field>>;
73
76
 
74
- export type RuntimeContextFields<TNative = unknown> = {
77
+ export type RuntimeContextFields = {
75
78
  request: Request;
76
79
  method: Method;
77
80
  url: URL;
78
- headers: import("@taserjs/router-core").TaserHeaders;
79
- cookies: import("@taserjs/router-core").TaserCookieJar;
81
+ headers: TaserHeaders;
82
+ cookies: TaserCookieJar;
80
83
  var: Record<string, unknown>;
81
- native?: TNative;
82
84
  };
85
+
86
+ export type UnitRuntimeContext = Omit<RuntimeContextFields, "var">;
@@ -1,13 +1,16 @@
1
- import type { Awaitable, TaserCookieJar, TaserHeaders } from "@taserjs/router-core";
2
- import type { ReplyResult } from "@taserjs/router-utils";
1
+ import type {
2
+ Awaitable,
3
+ MiddlewareDefinition as CoreMiddlewareDefinition,
4
+ TaserCookieJar,
5
+ TaserHeaders,
6
+ } from "@taserjs/router-core";
3
7
 
4
- import type { RouterRegister } from "../register.js";
5
8
  import type {
6
9
  MergeMiddlewareField,
7
10
  MergePart,
8
11
  RequestShape,
9
- RuntimeContextFields,
10
12
  Simplify,
13
+ UnitRuntimeContext,
11
14
  UnwrapPart,
12
15
  } from "./type-utils.js";
13
16
  import type { ReturnsMap } from "./returns.js";
@@ -28,8 +31,6 @@ export type {
28
31
  /** Default empty app context for standalone units without a bound router instance. */
29
32
  export type AppContext = Record<never, never>;
30
33
 
31
- export type NativeContext = RouterRegister extends { NativeContext: infer N } ? N : unknown;
32
-
33
34
  export type ValidatorParts = {
34
35
  query?: unknown;
35
36
  params?: unknown;
@@ -41,7 +42,7 @@ export type ValidatorParts = {
41
42
 
42
43
  export declare const StateBrand: unique symbol;
43
44
 
44
- export type NextResult<TState = unknown> = ReplyResult & {
45
+ export type NextResult<TState = unknown> = Response & {
45
46
  readonly [StateBrand]?: TState;
46
47
  };
47
48
 
@@ -62,13 +63,7 @@ export type NextFn<TExpectedState = unknown> =
62
63
 
63
64
  export type MiddlewareNext = NextFn;
64
65
 
65
- export type MiddlewareDefinition = {
66
- query?: unknown;
67
- params?: unknown;
68
- body?: unknown;
69
- returns?: ReturnsMap;
70
- handler: (ctx: unknown, next: MiddlewareNext) => Awaitable<ReplyResult | Response | unknown>;
71
- };
66
+ export type MiddlewareDefinition = CoreMiddlewareDefinition<ReturnsMap>;
72
67
 
73
68
  export type MiddlewareReturnFromParts<
74
69
  TQuery,
@@ -91,7 +86,32 @@ export type MiddlewareReturnFromParts<
91
86
  };
92
87
  };
93
88
 
94
- type UnitRuntimeContext = Omit<RuntimeContextFields<NativeContext>, "var">;
89
+ export type DefineMiddlewareResult<
90
+ TQuery,
91
+ TParams,
92
+ TBody,
93
+ TState,
94
+ R,
95
+ TQueryIn = TQuery,
96
+ TParamsIn = TParams,
97
+ TBodyIn = TBody,
98
+ TReturns extends ReturnsMap = {},
99
+ TLayout = null,
100
+ TRequires = {},
101
+ > = MiddlewareUnit<
102
+ MiddlewareReturnFromParts<
103
+ TQuery,
104
+ TParams,
105
+ TBody,
106
+ IsUnknown<TState> extends true ? ExtractState<R> : TState,
107
+ TQueryIn,
108
+ TParamsIn,
109
+ TBodyIn
110
+ >,
111
+ TReturns,
112
+ TLayout,
113
+ TRequires
114
+ >;
95
115
 
96
116
  export type StandaloneMiddlewareContext<
97
117
  TQuery = unknown,
@@ -165,7 +185,7 @@ export type HandlerUnit<
165
185
  Output: TOutput;
166
186
  };
167
187
  middlewares: readonly MiddlewareDefinition[];
168
- handler: (ctx: unknown) => Awaitable<ReplyResult | Response>;
188
+ handler: (ctx: unknown) => Awaitable<Response>;
169
189
  returns?: ReturnsMap;
170
190
  query?: Schema<unknown>;
171
191
  params?: Schema<unknown>;
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.cjs","names":[],"sources":["../../src/constants.ts"],"sourcesContent":["/** Input schema keys validated by middleware and route handlers. Headers/cookies are parsed only. */\nexport const SCHEMA_KEYS = [\"query\", \"params\", \"body\"] as const;\n\nexport type SchemaKey = (typeof SCHEMA_KEYS)[number];\n\nexport const HANDLER_SCHEMA_KEY_MAP = {\n query: \"handlerQuery\",\n params: \"handlerParams\",\n body: \"handlerBody\",\n} as const satisfies Record<SchemaKey, string>;\n"],"mappings":";;AACA,IAAa,cAAc;CAAC;CAAS;CAAU;AAAM;AAIrD,IAAa,yBAAyB;CACpC,OAAO;CACP,QAAQ;CACR,MAAM;AACR"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-context.cjs","names":[],"sources":["../../src/create-context.ts"],"sourcesContent":["import type { ReservedContextKey } from \"@taserjs/router-core\";\n\nimport type { ContextDefinition } from \"./types/app.js\";\n\ntype NoReservedKeysConstraint<\n TBoot extends Record<string, unknown>,\n TReq extends Record<string, unknown>,\n> = Extract<keyof TBoot | keyof TReq, ReservedContextKey> extends never ? unknown : never;\n\nexport function createContext<\n TBoot extends Record<string, unknown> = Record<string, never>,\n TReq extends Record<string, unknown> = Record<string, never>,\n>(\n definition: ContextDefinition<TBoot, TReq> & NoReservedKeysConstraint<TBoot, TReq>,\n): ContextDefinition<TBoot, TReq> {\n return definition;\n}\n\nexport type { ContextDefinition, InferAppContext } from \"./types/app.js\";\n"],"mappings":";AASA,SAAgB,cAId,YACgC;CAChC,OAAO;AACT"}