@taserjs/router 0.1.7 → 0.1.8

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.
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.cjs","names":[],"sources":["../../../src/define/middleware.ts"],"sourcesContent":["import { createMiddlewareUnitBuilder } from \"../builder/middleware-unit.js\";\nimport type {\n DefineMiddlewareResult,\n ExtractState,\n IsUnknown,\n MiddlewareRequirements,\n MiddlewareUnitBuilder,\n NextFn,\n StandaloneMiddlewareContext,\n} from \"../types/units.js\";\nimport type {\n AppContext,\n LayoutId,\n ResolveLayoutMiddlewaresState,\n ResolveLayoutsState,\n} from \"../types/index.js\";\n\nexport interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppContext> {\n /**\n * Constructs a fluent unscoped middleware builder, with optional explicit State generic.\n *\n * @example\n * ```ts\n * const auth = middleware<{ user: string }>()\n * .query(z.object({ token: z.string() }))\n * .body(\"form\", z.object({ file: z.instanceof(File) }))\n * .returns({ 401: z.string() })\n * .handler(async (ctx, next) => next({ user: \"alice\" }));\n * ```\n */\n <TState = unknown>(): MiddlewareUnitBuilder<\n unknown,\n unknown,\n unknown,\n {},\n null,\n {},\n TAppContext,\n {},\n unknown,\n unknown,\n unknown,\n TState\n >;\n\n /**\n * Constructs a fluent middleware builder scoped to a single layout branch, with optional explicit State generic.\n */\n <const Layout extends LayoutId, TState = unknown>(\n layout: Layout,\n ): MiddlewareUnitBuilder<\n unknown,\n unknown,\n unknown,\n {},\n Layout,\n {},\n TAppContext,\n ResolveLayoutMiddlewaresState<Layout>,\n unknown,\n unknown,\n unknown,\n TState\n >;\n\n /**\n * Constructs a fluent middleware builder scoped to multiple layout branches (branch union), with optional explicit State generic.\n */\n <const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown>(\n layouts: Layouts,\n ): MiddlewareUnitBuilder<\n unknown,\n unknown,\n unknown,\n {},\n Layouts,\n {},\n TAppContext,\n ResolveLayoutsState<Layouts>,\n unknown,\n unknown,\n unknown,\n TState\n >;\n\n /**\n * Defines a standalone middleware scoped to a single layout branch using a short function signature.\n */\n <\n const Layout extends LayoutId,\n TState = unknown,\n TRequires extends MiddlewareRequirements = {},\n R = unknown,\n >(\n layout: Layout,\n fn: (\n ctx: StandaloneMiddlewareContext<\n unknown,\n unknown,\n unknown,\n TAppContext,\n ResolveLayoutMiddlewaresState<Layout>,\n TRequires\n >,\n next: NextFn<NoInfer<TState>>,\n ) => R,\n ): DefineMiddlewareResult<\n unknown,\n unknown,\n unknown,\n IsUnknown<TState> extends true ? ExtractState<R> : TState,\n R,\n unknown,\n unknown,\n unknown,\n {},\n Layout,\n TRequires\n >;\n\n /**\n * Defines a standalone middleware scoped to multiple layout branches using a short function signature.\n */\n <\n const Layouts extends readonly [LayoutId, ...LayoutId[]],\n TState = unknown,\n TRequires extends MiddlewareRequirements = {},\n R = unknown,\n >(\n layouts: Layouts,\n fn: (\n ctx: StandaloneMiddlewareContext<\n unknown,\n unknown,\n unknown,\n TAppContext,\n ResolveLayoutsState<Layouts>,\n TRequires\n >,\n next: NextFn<NoInfer<TState>>,\n ) => R,\n ): DefineMiddlewareResult<\n unknown,\n unknown,\n unknown,\n IsUnknown<TState> extends true ? ExtractState<R> : TState,\n R,\n unknown,\n unknown,\n unknown,\n {},\n Layouts,\n TRequires\n >;\n\n /**\n * Defines a standalone, unscoped middleware using a short function signature.\n *\n * @example\n * ```ts\n * const auth = middleware((ctx, next) => {\n * return next({ user: \"alice\" });\n * });\n * ```\n */\n <TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(\n fn: (\n ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, {}, TRequires>,\n next: NextFn<NoInfer<TState>>,\n ) => R,\n ): DefineMiddlewareResult<\n unknown,\n unknown,\n unknown,\n IsUnknown<TState> extends true ? ExtractState<R> : TState,\n R,\n unknown,\n unknown,\n unknown,\n {},\n null,\n TRequires\n >;\n}\n\nexport const middleware: MiddlewareFn<AppContext> = function middleware(\n first?: any,\n second?: any,\n): any {\n if (first === undefined) {\n return createMiddlewareUnitBuilder();\n }\n\n if (typeof first === \"string\" || Array.isArray(first)) {\n if (typeof second === \"function\") {\n return {\n handler: second,\n __middlewareAcc: undefined as unknown,\n __requiredLayouts: first,\n };\n }\n return createMiddlewareUnitBuilder(first);\n }\n\n if (typeof first === \"function\") {\n return {\n handler: first,\n __middlewareAcc: undefined as unknown,\n };\n }\n\n return createMiddlewareUnitBuilder();\n};\n"],"mappings":";;AAyLA,IAAa,aAAuC,SAAS,WAC3D,OACA,QACK;CACL,IAAI,UAAU,KAAA,GACZ,OAAO,wBAAA,4BAA4B;CAGrC,IAAI,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;EACrD,IAAI,OAAO,WAAW,YACpB,OAAO;GACL,SAAS;GACT,iBAAiB,KAAA;GACjB,mBAAmB;EACrB;EAEF,OAAO,wBAAA,4BAA4B,KAAK;CAC1C;CAEA,IAAI,OAAO,UAAU,YACnB,OAAO;EACL,SAAS;EACT,iBAAiB,KAAA;CACnB;CAGF,OAAO,wBAAA,4BAA4B;AACrC"}
1
+ {"version":3,"file":"middleware.cjs","names":[],"sources":["../../../src/define/middleware.ts"],"sourcesContent":["import { createMiddlewareUnitBuilder } from \"../builder/middleware-unit.js\";\nimport type {\n DefineMiddlewareResult,\n ExtractState,\n IsUnknown,\n MiddlewareRequirements,\n MiddlewareUnitBuilder,\n NextFn,\n StandaloneMiddlewareContext,\n} from \"../types/units.js\";\nimport type {\n AppContext,\n LayoutId,\n ResolveLayoutMiddlewaresState,\n ResolveLayoutsState,\n} from \"../types/index.js\";\n\nexport interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppContext> {\n /**\n * Defines a standalone, unscoped middleware using a short function signature.\n *\n * @example\n * ```ts\n * const auth = middleware((ctx, next) => {\n * return next({ user: \"alice\" });\n * });\n * ```\n */\n <TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(\n fn: (\n ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, {}, TRequires>,\n next: NextFn<NoInfer<TState>>,\n ) => R,\n ): DefineMiddlewareResult<\n unknown,\n unknown,\n unknown,\n IsUnknown<TState> extends true ? ExtractState<R> : TState,\n R,\n unknown,\n unknown,\n unknown,\n {},\n null,\n TRequires\n >;\n\n /**\n * Constructs a fluent unscoped middleware builder, with optional explicit State generic.\n *\n * @example\n * ```ts\n * const auth = middleware<{ user: string }>()\n * .query(z.object({ token: z.string() }))\n * .body(\"form\", z.object({ file: z.instanceof(File) }))\n * .returns({ 401: z.string() })\n * .handler(async (ctx, next) => next({ user: \"alice\" }));\n * ```\n */\n <TState = unknown>(): MiddlewareUnitBuilder<\n unknown,\n unknown,\n unknown,\n {},\n null,\n {},\n TAppContext,\n {},\n unknown,\n unknown,\n unknown,\n TState\n >;\n\n /**\n * Defines a standalone middleware scoped to a single layout branch using a short function signature.\n */\n <\n const Layout extends LayoutId,\n TState = unknown,\n TRequires extends MiddlewareRequirements = {},\n R = unknown,\n >(\n layout: Layout,\n fn: (\n ctx: StandaloneMiddlewareContext<\n unknown,\n unknown,\n unknown,\n TAppContext,\n ResolveLayoutMiddlewaresState<Layout>,\n TRequires\n >,\n next: NextFn<NoInfer<TState>>,\n ) => R,\n ): DefineMiddlewareResult<\n unknown,\n unknown,\n unknown,\n IsUnknown<TState> extends true ? ExtractState<R> : TState,\n R,\n unknown,\n unknown,\n unknown,\n {},\n Layout,\n TRequires\n >;\n\n /**\n * Defines a standalone middleware scoped to multiple layout branches using a short function signature.\n */\n <\n const Layouts extends readonly [LayoutId, ...LayoutId[]],\n TState = unknown,\n TRequires extends MiddlewareRequirements = {},\n R = unknown,\n >(\n layouts: Layouts,\n fn: (\n ctx: StandaloneMiddlewareContext<\n unknown,\n unknown,\n unknown,\n TAppContext,\n ResolveLayoutsState<Layouts>,\n TRequires\n >,\n next: NextFn<NoInfer<TState>>,\n ) => R,\n ): DefineMiddlewareResult<\n unknown,\n unknown,\n unknown,\n IsUnknown<TState> extends true ? ExtractState<R> : TState,\n R,\n unknown,\n unknown,\n unknown,\n {},\n Layouts,\n TRequires\n >;\n\n /**\n * Constructs a fluent middleware builder scoped to a single layout branch, with optional explicit State generic.\n */\n <const Layout extends LayoutId, TState = unknown>(\n layout: Layout,\n ): MiddlewareUnitBuilder<\n unknown,\n unknown,\n unknown,\n {},\n Layout,\n {},\n TAppContext,\n ResolveLayoutMiddlewaresState<Layout>,\n unknown,\n unknown,\n unknown,\n TState\n >;\n\n /**\n * Constructs a fluent middleware builder scoped to multiple layout branches (branch union), with optional explicit State generic.\n */\n <const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown>(\n layouts: Layouts,\n ): MiddlewareUnitBuilder<\n unknown,\n unknown,\n unknown,\n {},\n Layouts,\n {},\n TAppContext,\n ResolveLayoutsState<Layouts>,\n unknown,\n unknown,\n unknown,\n TState\n >;\n}\n\nexport const middleware: MiddlewareFn<AppContext> = function middleware(\n first?: any,\n second?: any,\n): any {\n if (first === undefined) {\n return createMiddlewareUnitBuilder();\n }\n\n if (typeof first === \"string\" || Array.isArray(first)) {\n if (typeof second === \"function\") {\n return {\n handler: second,\n __middlewareAcc: undefined as unknown,\n __requiredLayouts: first,\n };\n }\n return createMiddlewareUnitBuilder(first);\n }\n\n if (typeof first === \"function\") {\n return {\n handler: first,\n __middlewareAcc: undefined as unknown,\n };\n }\n\n return createMiddlewareUnitBuilder();\n};\n"],"mappings":";;AAyLA,IAAa,aAAuC,SAAS,WAC3D,OACA,QACK;CACL,IAAI,UAAU,KAAA,GACZ,OAAO,wBAAA,4BAA4B;CAGrC,IAAI,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;EACrD,IAAI,OAAO,WAAW,YACpB,OAAO;GACL,SAAS;GACT,iBAAiB,KAAA;GACjB,mBAAmB;EACrB;EAEF,OAAO,wBAAA,4BAA4B,KAAK;CAC1C;CAEA,IAAI,OAAO,UAAU,YACnB,OAAO;EACL,SAAS;EACT,iBAAiB,KAAA;CACnB;CAGF,OAAO,wBAAA,4BAA4B;AACrC"}
@@ -1,6 +1,17 @@
1
1
  import { DefineMiddlewareResult, ExtractState, IsUnknown, MiddlewareRequirements, MiddlewareUnitBuilder, NextFn, StandaloneMiddlewareContext } from '../types/units.js';
2
2
  import { AppContext, LayoutId, ResolveLayoutMiddlewaresState, ResolveLayoutsState } from '../types/index.js';
3
3
  export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppContext> {
4
+ /**
5
+ * Defines a standalone, unscoped middleware using a short function signature.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const auth = middleware((ctx, next) => {
10
+ * return next({ user: "alice" });
11
+ * });
12
+ * ```
13
+ */
14
+ <TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(fn: (ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, {}, TRequires>, next: NextFn<NoInfer<TState>>) => R): DefineMiddlewareResult<unknown, unknown, unknown, IsUnknown<TState> extends true ? ExtractState<R> : TState, R, unknown, unknown, unknown, {}, null, TRequires>;
4
15
  /**
5
16
  * Constructs a fluent unscoped middleware builder, with optional explicit State generic.
6
17
  *
@@ -14,14 +25,6 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
14
25
  * ```
15
26
  */
16
27
  <TState = unknown>(): MiddlewareUnitBuilder<unknown, unknown, unknown, {}, null, {}, TAppContext, {}, unknown, unknown, unknown, TState>;
17
- /**
18
- * Constructs a fluent middleware builder scoped to a single layout branch, with optional explicit State generic.
19
- */
20
- <const Layout extends LayoutId, TState = unknown>(layout: Layout): MiddlewareUnitBuilder<unknown, unknown, unknown, {}, Layout, {}, TAppContext, ResolveLayoutMiddlewaresState<Layout>, unknown, unknown, unknown, TState>;
21
- /**
22
- * Constructs a fluent middleware builder scoped to multiple layout branches (branch union), with optional explicit State generic.
23
- */
24
- <const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown>(layouts: Layouts): MiddlewareUnitBuilder<unknown, unknown, unknown, {}, Layouts, {}, TAppContext, ResolveLayoutsState<Layouts>, unknown, unknown, unknown, TState>;
25
28
  /**
26
29
  * Defines a standalone middleware scoped to a single layout branch using a short function signature.
27
30
  */
@@ -31,15 +34,12 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
31
34
  */
32
35
  <const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(layouts: Layouts, fn: (ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, ResolveLayoutsState<Layouts>, TRequires>, next: NextFn<NoInfer<TState>>) => R): DefineMiddlewareResult<unknown, unknown, unknown, IsUnknown<TState> extends true ? ExtractState<R> : TState, R, unknown, unknown, unknown, {}, Layouts, TRequires>;
33
36
  /**
34
- * Defines a standalone, unscoped middleware using a short function signature.
35
- *
36
- * @example
37
- * ```ts
38
- * const auth = middleware((ctx, next) => {
39
- * return next({ user: "alice" });
40
- * });
41
- * ```
37
+ * Constructs a fluent middleware builder scoped to a single layout branch, with optional explicit State generic.
42
38
  */
43
- <TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(fn: (ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, {}, TRequires>, next: NextFn<NoInfer<TState>>) => R): DefineMiddlewareResult<unknown, unknown, unknown, IsUnknown<TState> extends true ? ExtractState<R> : TState, R, unknown, unknown, unknown, {}, null, TRequires>;
39
+ <const Layout extends LayoutId, TState = unknown>(layout: Layout): MiddlewareUnitBuilder<unknown, unknown, unknown, {}, Layout, {}, TAppContext, ResolveLayoutMiddlewaresState<Layout>, unknown, unknown, unknown, TState>;
40
+ /**
41
+ * Constructs a fluent middleware builder scoped to multiple layout branches (branch union), with optional explicit State generic.
42
+ */
43
+ <const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown>(layouts: Layouts): MiddlewareUnitBuilder<unknown, unknown, unknown, {}, Layouts, {}, TAppContext, ResolveLayoutsState<Layouts>, unknown, unknown, unknown, TState>;
44
44
  }
45
45
  export declare const middleware: MiddlewareFn<AppContext>;
@@ -1,6 +1,10 @@
1
1
  export interface RouterRegister {
2
2
  }
3
- export type { AppContext, EmptyAppContext, HttpMethod, InferInput, InferOutput, InferRouteContext, InferRouteInput, InferRouteInputFromPath, InferRouteOutput, LayoutBuilder, LayoutId, LayoutTree, Method, MiddlewareBuilder, MiddlewareDefinition, MiddlewareUnit, MiddlewareUnitBuilder, PathParams, ReturnsMap, RouteByPathMethod, RouteDefinition, RouteExport, RoutePath, Schema, Simplify, StatusCode, } from './types/index.js';
3
+ export interface RouterMiddlewaresRegister {
4
+ }
5
+ export interface RouterRoutesRegister {
6
+ }
7
+ export type { AppContext, EmptyAppContext, HttpMethod, InferInput, InferOutput, InferRouteContext, InferRouteInput, InferRouteInputFromPath, InferRouteOutput, LayoutBuilder, LayoutId, LayoutMiddlewaresMap, LayoutTree, Method, MiddlewareBuilder, MiddlewareDefinition, MiddlewareUnit, MiddlewareUnitBuilder, PathParams, ReturnsMap, RouteByPathMethod, RouteDefinition, RouteExport, RoutePath, Schema, Simplify, StatusCode, } from './types/index.js';
4
8
  export type { ContextDefinition, CreateTaserAppOptions, InferAppContext, InferAppManifest, OnErrorOptions, RouteManifestShape, } from './types/app.js';
5
9
  export { ValidationError, validationErrorSchema } from '@taserjs/router-utils';
6
10
  export type { ResponseValidationFailureHandler, SuccessStatusCode } from '@taserjs/router-utils';
@@ -1 +1 @@
1
- {"version":3,"file":"hono-mw.cjs","names":[],"sources":["../../../src/middleware/hono-mw.ts"],"sourcesContent":["import { createTaserCompatHandler } from \"@taserjs/router-core\";\nimport type { MiddlewareHandler } from \"hono\";\n\n/**\n * Adapts a standard Web / Hono-compatible middleware function `(c, next) => ...`\n * into a Taser-compatible middleware handler function `(ctx, next) => Promise<Response>`.\n *\n * @example\n * ```ts\n * import { honoMw } from \"@taserjs/router\";\n * import { cors } from \"hono/cors\";\n *\n * const app = t.get(\"/hello\").use(honoMw(cors()));\n * // or\n * const customCors = middleware(honoMw(cors()));\n * ```\n */\nexport function honoMw(\n middleware: MiddlewareHandler,\n): (ctx: unknown, next: any) => Promise<Response> {\n return createTaserCompatHandler(middleware) as (ctx: unknown, next: any) => Promise<Response>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAiBA,SAAgB,OACd,YACgD;CAChD,QAAA,GAAA,qBAAA,yBAAA,CAAgC,UAAU;AAC5C"}
1
+ {"version":3,"file":"hono-mw.cjs","names":[],"sources":["../../../src/middleware/hono-mw.ts"],"sourcesContent":["import { createTaserCompatHandler } from \"@taserjs/router-core\";\nimport type { MiddlewareHandler } from \"hono\";\n\nimport type { NextFn } from \"../types/units.js\";\n\n/**\n * Adapts a standard Web / Hono-compatible middleware function `(c, next) => ...`\n * into a Taser-compatible middleware handler function `(ctx, next) => Promise<Response>`.\n *\n * @example\n * ```ts\n * import { honoMw } from \"@taserjs/router\";\n * import { cors } from \"hono/cors\";\n *\n * const app = t.get(\"/hello\").use(honoMw(cors()));\n * // or\n * const customCors = middleware(honoMw(cors()));\n * ```\n */\nexport function honoMw<TState extends Record<string, unknown> = {}>(\n middleware: MiddlewareHandler,\n): (ctx: unknown, next: NextFn<TState>) => Promise<Response> {\n return createTaserCompatHandler(middleware) as (ctx: unknown, next: NextFn<TState>) => Promise<Response>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,SAAgB,OACd,YAC2D;CAC3D,QAAA,GAAA,qBAAA,yBAAA,CAAgC,UAAU;AAC5C"}
@@ -1,4 +1,5 @@
1
1
  import { MiddlewareHandler } from 'hono';
2
+ import { NextFn } from '../types/units.js';
2
3
  /**
3
4
  * Adapts a standard Web / Hono-compatible middleware function `(c, next) => ...`
4
5
  * into a Taser-compatible middleware handler function `(ctx, next) => Promise<Response>`.
@@ -13,4 +14,4 @@ import { MiddlewareHandler } from 'hono';
13
14
  * const customCors = middleware(honoMw(cors()));
14
15
  * ```
15
16
  */
16
- export declare function honoMw(middleware: MiddlewareHandler): (ctx: unknown, next: any) => Promise<Response>;
17
+ export declare function honoMw<TState extends Record<string, unknown> = {}>(middleware: MiddlewareHandler): (ctx: unknown, next: NextFn<TState>) => Promise<Response>;
@@ -1,5 +1,5 @@
1
1
  import { Awaitable, TaserCookieJar, TaserHeaders } from '@taserjs/router-core';
2
- import { RouterRegister } from '../index.js';
2
+ import { RouterMiddlewaresRegister, RouterRegister, RouterRoutesRegister } from '../index.js';
3
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';
@@ -21,7 +21,14 @@ export type LayoutId = RouterRegister extends {
21
21
  export type LayoutTree = RouterRegister extends {
22
22
  LayoutTree: infer T;
23
23
  } ? T : Record<never, never>;
24
- export type RouteByPathMethod = RouterRegister extends {
24
+ export type LayoutMiddlewaresMap = RouterMiddlewaresRegister extends {
25
+ LayoutMiddlewares: infer M;
26
+ } ? M : RouterRegister extends {
27
+ LayoutMiddlewares: infer M;
28
+ } ? M : Record<never, never>;
29
+ export type RouteByPathMethod = RouterRoutesRegister extends {
30
+ RouteByPathMethod: infer R;
31
+ } ? R : RouterRegister extends {
25
32
  RouteByPathMethod: infer R;
26
33
  } ? R : Record<never, never>;
27
34
  export type LayoutBuilder<TAppContext extends Record<string, unknown> = AppContext> = <const Layout extends LayoutId>(layout: Layout) => MiddlewareBuilder<Layout, readonly [], TAppContext>;
@@ -33,19 +40,16 @@ type ParseParam<Segment extends string> = Segment extends "*" ? {
33
40
  type ParseParamsFromSegments<S extends string> = S extends `${infer Segment}/${infer Rest}` ? ParseParam<Segment> & ParseParamsFromSegments<Rest> : ParseParam<S>;
34
41
  export type PathParams<Path extends string> = Path extends `/${infer Rest}` ? ParseParamsFromSegments<Rest> : {};
35
42
  export type ResolveParams<TPathParams, TSchemaParams> = TSchemaParams extends Record<string, unknown> ? [keyof TSchemaParams] extends [never] ? TPathParams : Simplify<Omit<TPathParams, keyof TSchemaParams> & TSchemaParams> : TPathParams;
36
- type LayoutParentsMap = RouterRegister extends {
37
- LayoutParents: infer LP extends Record<string, unknown>;
38
- } ? LP : {};
39
- type LayoutParent<Layout extends LayoutId> = Layout extends keyof LayoutParentsMap ? LayoutParentsMap[Layout] extends LayoutId ? LayoutParentsMap[Layout] : null : LayoutTree[Layout] extends {
40
- parent: infer Parent extends LayoutId | null;
41
- } ? Parent : null;
42
- type LayoutMiddlewares<Layout extends LayoutId> = LayoutTree[Layout]["middlewares"] extends {
43
+ type LayoutParent<Layout extends LayoutId> = Layout extends keyof LayoutTree ? LayoutTree[Layout] extends {
44
+ parent: infer P extends LayoutId;
45
+ } ? P : null : null;
46
+ type LayoutMiddlewares<Layout extends LayoutId> = [Layout] extends [keyof LayoutMiddlewaresMap] ? LayoutMiddlewaresMap[Layout] extends {
43
47
  readonly __acc?: infer Acc extends readonly unknown[];
44
- } ? Acc : LayoutTree[Layout]["middlewares"] extends infer Acc extends readonly unknown[] ? Acc : readonly [];
45
- type ResolveLayoutMiddlewares<Layout extends LayoutId | null, Depth extends readonly unknown[] = []> = Depth["length"] extends 10 ? readonly [] : Layout extends LayoutId ? readonly [
46
- ...ResolveLayoutMiddlewares<LayoutParent<Layout>, [...Depth, unknown]>,
48
+ } ? Acc : LayoutMiddlewaresMap[Layout] extends readonly unknown[] ? LayoutMiddlewaresMap[Layout] : readonly [] : readonly [];
49
+ type ResolveLayoutMiddlewares<Layout extends LayoutId | null, Depth extends readonly unknown[] = []> = Depth["length"] extends 10 ? readonly [] : [Layout] extends [LayoutId] ? LayoutParent<Layout> extends infer Parent extends LayoutId ? readonly [
50
+ ...ResolveLayoutMiddlewares<Parent, [...Depth, unknown]>,
47
51
  ...LayoutMiddlewares<Layout>
48
- ] : readonly [];
52
+ ] : readonly [...LayoutMiddlewares<Layout>] : readonly [];
49
53
  export type ResolveLayoutIdChain<L extends LayoutId | null, Depth extends readonly unknown[] = []> = Depth["length"] extends 10 ? readonly [] : L extends LayoutId ? readonly [...ResolveLayoutIdChain<LayoutParent<L>, [...Depth, unknown]>, L] : readonly [];
50
54
  export type ResolveLayoutMiddlewaresState<Layout extends LayoutId | null> = Layout extends LayoutId ? MergeMiddlewareField<ResolveLayoutMiddlewares<Layout>, "state"> : {};
51
55
  export type ResolveLayoutsState<Layouts extends LayoutId | readonly LayoutId[]> = Layouts extends LayoutId ? ResolveLayoutMiddlewaresState<Layouts> : Layouts extends readonly LayoutId[] ? UnionToIntersection<Layouts[number] extends infer L extends LayoutId ? ResolveLayoutMiddlewaresState<L> : never> : {};
@@ -60,21 +64,18 @@ type ResolveLayoutChainMiddlewares<Chain extends readonly LayoutId[]> = Chain ex
60
64
  type RouteEntry<Path extends RoutePath, TMethod extends Method> = RouteByPathMethod[Path] extends {
61
65
  [K in TMethod]: infer Entry;
62
66
  } ? Entry : never;
63
- type RouteParent<Path extends RoutePath, TMethod extends Method> = RouteEntry<Path, TMethod> extends {
64
- parent: infer Parent extends LayoutId | null;
65
- } ? Parent : null;
66
67
  type RouteLayoutChain<Path extends RoutePath, TMethod extends Method> = RouteEntry<Path, TMethod> extends {
67
- layoutChain: infer Chain extends readonly LayoutId[];
68
- } ? Chain : RouteParent<Path, TMethod> extends LayoutId ? readonly [RouteParent<Path, TMethod>] : readonly [];
68
+ layouts: infer Chain extends readonly LayoutId[];
69
+ } ? Chain : readonly [];
69
70
  export type RouteLayoutMiddlewares<Path extends RoutePath, TMethod extends Method> = ResolveLayoutChainMiddlewares<RouteLayoutChain<Path, TMethod>>;
70
71
  export type RouteLayoutField<Path extends RoutePath, TMethod extends Method, Field extends "query" | "params" | "body" | "state"> = MergeMiddlewareField<RouteLayoutMiddlewares<Path, TMethod>, Field>;
71
72
  export type RouteLayoutInputField<Path extends RoutePath, TMethod extends Method, Field extends "query" | "params" | "body"> = MergeMiddlewareInputField<RouteLayoutMiddlewares<Path, TMethod>, Field>;
72
73
  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>;
73
74
  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 & {
74
- query: Simplify<MergePart<TQuery, RouteResolvedField<Path, TMethod, Acc, "query">>>;
75
- params: Simplify<ResolveParams<PathParams<Path>, MergePart<TParams, RouteResolvedField<Path, TMethod, Acc, "params">>>>;
76
- body: Simplify<MergePart<TBody, RouteResolvedField<Path, TMethod, Acc, "body">>>;
77
- state: Simplify<RouteResolvedField<Path, TMethod, Acc, "state">>;
75
+ query: MergePart<TQuery, RouteResolvedField<Path, TMethod, Acc, "query">>;
76
+ params: ResolveParams<PathParams<Path>, MergePart<TParams, RouteResolvedField<Path, TMethod, Acc, "params">>>;
77
+ body: MergePart<TBody, RouteResolvedField<Path, TMethod, Acc, "body">>;
78
+ state: RouteResolvedField<Path, TMethod, Acc, "state">;
78
79
  headers: TaserHeaders;
79
80
  cookies: TaserCookieJar;
80
81
  }>;
@@ -167,23 +168,23 @@ export type InferRouteInputFromPath<Path extends RoutePath, TMethod extends Meth
167
168
  Input: infer I;
168
169
  };
169
170
  } ? I : never : never;
170
- export type MiddlewareLayoutField<Layout extends LayoutId, Field extends "query" | "params" | "body" | "state"> = MergeMiddlewareField<ResolveLayoutMiddlewares<LayoutParent<Layout>>, Field>;
171
+ export type MiddlewareLayoutField<Layout extends LayoutId, Field extends "query" | "params" | "body" | "state"> = [LayoutParent<Layout>] extends [infer Parent extends LayoutId] ? MergeMiddlewareField<ResolveLayoutMiddlewares<Parent>, Field> : {};
171
172
  type MiddlewareChainField<Layout extends LayoutId, Acc extends readonly unknown[], Field extends "query" | "params" | "body" | "state"> = MiddlewareLayoutField<Layout, Field> & MergeMiddlewareField<Acc, Field>;
172
- export type MiddlewareChainContext<Layout extends LayoutId, Acc extends readonly unknown[], TQuery, TParams, TBody, TAppContext extends Record<string, unknown> = AppContext> = Simplify<TAppContext & UnitRuntimeContext & {
173
+ export type MiddlewareChainContext<Layout extends LayoutId, Acc extends readonly unknown[], TQuery = unknown, TParams = unknown, TBody = unknown, TAppContext extends Record<string, unknown> = AppContext> = Simplify<TAppContext & {
174
+ readonly request: Request;
175
+ readonly method: Method;
176
+ readonly url: URL;
177
+ readonly headers: TaserHeaders;
178
+ readonly cookies: TaserCookieJar;
173
179
  query: Simplify<MergePart<TQuery, MiddlewareChainField<Layout, Acc, "query">>>;
174
180
  params: Simplify<MergePart<TParams, MiddlewareChainField<Layout, Acc, "params">>>;
175
181
  body: Simplify<MergePart<TBody, MiddlewareChainField<Layout, Acc, "body">>>;
176
182
  state: Simplify<MiddlewareChainField<Layout, Acc, "state">>;
177
- headers: TaserHeaders;
178
- cookies: TaserCookieJar;
179
183
  }>;
180
184
  export type MiddlewareBuilder<Layout extends LayoutId, Acc extends readonly unknown[] = readonly [], TAppContext extends Record<string, unknown> = AppContext> = {
181
185
  readonly layout: Layout;
182
186
  readonly middlewares: readonly MiddlewareDefinition[];
183
187
  readonly __acc?: Acc;
184
- readonly $Infer: {
185
- Context: MiddlewareChainContext<Layout, Acc, unknown, unknown, unknown, TAppContext>;
186
- };
187
188
  use<TAcc, TReturns extends ReturnsMap = {}, TRequiredLayouts = unknown, TRequires extends MiddlewareRequirements = {}>(unit: [
188
189
  IsLayoutAllowed<TRequiredLayouts, ResolveLayoutIdChain<Layout>>,
189
190
  IsRequirementsSatisfied<{
@@ -192,19 +193,18 @@ export type MiddlewareBuilder<Layout extends LayoutId, Acc extends readonly unkn
192
193
  body: MiddlewareChainField<Layout, Acc, "body">;
193
194
  state: MiddlewareChainField<Layout, Acc, "state">;
194
195
  }, TRequires>
195
- ] extends [true, true] ? MiddlewareUnit<TAcc, TReturns, TRequiredLayouts, TRequires> : {
196
- error: "Middleware cannot be attached to this layout";
197
- requiredLayouts: TRequiredLayouts;
198
- layoutChain: ResolveLayoutIdChain<Layout>;
199
- requirements: TRequires;
200
- actual: {
201
- query: MiddlewareChainField<Layout, Acc, "query">;
202
- params: MiddlewareChainField<Layout, Acc, "params">;
203
- body: MiddlewareChainField<Layout, Acc, "body">;
204
- state: MiddlewareChainField<Layout, Acc, "state">;
205
- };
206
- }): MiddlewareBuilder<Layout, readonly [...Acc, TAcc], TAppContext>;
207
- use<R = unknown>(fn: (ctx: MiddlewareChainContext<Layout, Acc, unknown, unknown, unknown, TAppContext>, next: NextFn) => Awaitable<R>): MiddlewareBuilder<Layout, readonly [...Acc, MiddlewareReturnFromParts<unknown, unknown, unknown, ExtractState<R>>], TAppContext>;
196
+ ] extends [true, true] ? MiddlewareUnit<TAcc, TReturns, TRequiredLayouts, TRequires> : never): MiddlewareBuilder<Layout, readonly [...Acc, TAcc], TAppContext>;
197
+ use<R = unknown>(fn: (ctx: Simplify<TAppContext & {
198
+ readonly request: Request;
199
+ readonly method: Method;
200
+ readonly url: URL;
201
+ readonly headers: TaserHeaders;
202
+ readonly cookies: TaserCookieJar;
203
+ query: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "query">>>;
204
+ params: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "params">>>;
205
+ body: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "body">>>;
206
+ state: Simplify<MiddlewareChainField<Layout, Acc, "state">>;
207
+ }>, next: NextFn) => Awaitable<R>): MiddlewareBuilder<Layout, readonly [...Acc, MiddlewareReturnFromParts<unknown, unknown, unknown, ExtractState<R>>], TAppContext>;
208
208
  };
209
209
  export type RouteExport<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], TReturns extends ReturnsMap = {}, TOutput = Response> = {
210
210
  readonly path: Path;
@@ -274,18 +274,7 @@ export type RouteMiddlewareBuilder<Path extends RoutePath, TMethod extends Metho
274
274
  body: RouteResolvedField<Path, TMethod, Acc, "body">;
275
275
  state: RouteResolvedField<Path, TMethod, Acc, "state">;
276
276
  }, TRequires>
277
- ] extends [true, true] ? MiddlewareUnit<TAcc, UReturns, TRequiredLayouts, TRequires> : {
278
- error: "Middleware cannot be attached to this route";
279
- requiredLayouts: TRequiredLayouts;
280
- routeLayoutChain: RouteLayoutChain<Path, TMethod>;
281
- requirements: TRequires;
282
- actual: {
283
- query: RouteResolvedField<Path, TMethod, Acc, "query">;
284
- params: ResolveParams<PathParams<Path>, RouteResolvedField<Path, TMethod, Acc, "params">>;
285
- body: RouteResolvedField<Path, TMethod, Acc, "body">;
286
- state: RouteResolvedField<Path, TMethod, Acc, "state">;
287
- };
288
- }): RouteMiddlewareBuilder<Path, TMethod, readonly [...Acc, TAcc], Validators, Omit<TReturns, keyof UReturns> & UReturns, TAppContext>;
277
+ ] extends [true, true] ? MiddlewareUnit<TAcc, UReturns, TRequiredLayouts, TRequires> : never): RouteMiddlewareBuilder<Path, TMethod, readonly [...Acc, TAcc], Validators, Omit<TReturns, keyof UReturns> & UReturns, TAppContext>;
289
278
  use<R = unknown>(fn: (ctx: RouteChainContext<Path, TMethod, Acc, unknown, unknown, unknown, TAppContext>, next: NextFn) => Awaitable<R>): RouteMiddlewareBuilder<Path, TMethod, readonly [...Acc, MiddlewareReturnFromParts<unknown, unknown, unknown, ExtractState<R>>], Validators, TReturns, TAppContext>;
290
279
  };
291
280
  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> = RouteMiddlewareBuilder<Path, TMethod, Acc, Validators, TReturns, TAppContext>;
@@ -7,9 +7,9 @@ export type MiddlewareInputFieldName = "query" | "params" | "body";
7
7
  export type UnwrapPart<T> = unknown extends T ? {} : T;
8
8
  export type MergePart<T, Base> = unknown extends T ? Base : Base & T;
9
9
  /** Collapse intersections so `Omit`/`keyof` treat the result as one object type. */
10
- export type Simplify<T> = {
11
- [K in keyof T]: T[K];
12
- } & {};
10
+ export type Simplify<T> = [T] extends [infer U] ? {
11
+ [K in keyof U]: U[K];
12
+ } : never;
13
13
  /**
14
14
  * Request prop: when schema input is `unknown` (e.g. zod coerce),
15
15
  * fall back to the validated output type.
@@ -26,10 +26,10 @@ export type IsUnknown<T> = [unknown] extends [T] ? true : false;
26
26
  export type NextFn<TExpectedState = unknown> = IsUnknown<TExpectedState> extends true ? <S extends Record<string, unknown> = {}>(state?: S) => Promise<NextResult<S>> : (state: TExpectedState) => Promise<NextResult<TExpectedState>>;
27
27
  export type MiddlewareDefinition = CoreMiddlewareDefinition<ReturnsMap>;
28
28
  export type MiddlewareReturnFromParts<TQuery, TParams, TBody, TState, TQueryIn = TQuery, TParamsIn = TParams, TBodyIn = TBody> = {
29
- query: Simplify<UnwrapPart<TQuery>>;
30
- params: Simplify<UnwrapPart<TParams>>;
31
- body: Simplify<UnwrapPart<TBody>>;
32
- state: Simplify<UnwrapPart<TState>>;
29
+ query: UnwrapPart<TQuery>;
30
+ params: UnwrapPart<TParams>;
31
+ body: UnwrapPart<TBody>;
32
+ state: UnwrapPart<TState>;
33
33
  /** Pre-parse shapes merged into route `$Infer.Input`. */
34
34
  input: {
35
35
  query: RequestShape<TQueryIn, TQuery>;
@@ -1,6 +1,17 @@
1
1
  import { DefineMiddlewareResult, ExtractState, IsUnknown, MiddlewareRequirements, MiddlewareUnitBuilder, NextFn, StandaloneMiddlewareContext } from '../types/units.js';
2
2
  import { AppContext, LayoutId, ResolveLayoutMiddlewaresState, ResolveLayoutsState } from '../types/index.js';
3
3
  export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppContext> {
4
+ /**
5
+ * Defines a standalone, unscoped middleware using a short function signature.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const auth = middleware((ctx, next) => {
10
+ * return next({ user: "alice" });
11
+ * });
12
+ * ```
13
+ */
14
+ <TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(fn: (ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, {}, TRequires>, next: NextFn<NoInfer<TState>>) => R): DefineMiddlewareResult<unknown, unknown, unknown, IsUnknown<TState> extends true ? ExtractState<R> : TState, R, unknown, unknown, unknown, {}, null, TRequires>;
4
15
  /**
5
16
  * Constructs a fluent unscoped middleware builder, with optional explicit State generic.
6
17
  *
@@ -14,14 +25,6 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
14
25
  * ```
15
26
  */
16
27
  <TState = unknown>(): MiddlewareUnitBuilder<unknown, unknown, unknown, {}, null, {}, TAppContext, {}, unknown, unknown, unknown, TState>;
17
- /**
18
- * Constructs a fluent middleware builder scoped to a single layout branch, with optional explicit State generic.
19
- */
20
- <const Layout extends LayoutId, TState = unknown>(layout: Layout): MiddlewareUnitBuilder<unknown, unknown, unknown, {}, Layout, {}, TAppContext, ResolveLayoutMiddlewaresState<Layout>, unknown, unknown, unknown, TState>;
21
- /**
22
- * Constructs a fluent middleware builder scoped to multiple layout branches (branch union), with optional explicit State generic.
23
- */
24
- <const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown>(layouts: Layouts): MiddlewareUnitBuilder<unknown, unknown, unknown, {}, Layouts, {}, TAppContext, ResolveLayoutsState<Layouts>, unknown, unknown, unknown, TState>;
25
28
  /**
26
29
  * Defines a standalone middleware scoped to a single layout branch using a short function signature.
27
30
  */
@@ -31,15 +34,12 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
31
34
  */
32
35
  <const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(layouts: Layouts, fn: (ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, ResolveLayoutsState<Layouts>, TRequires>, next: NextFn<NoInfer<TState>>) => R): DefineMiddlewareResult<unknown, unknown, unknown, IsUnknown<TState> extends true ? ExtractState<R> : TState, R, unknown, unknown, unknown, {}, Layouts, TRequires>;
33
36
  /**
34
- * Defines a standalone, unscoped middleware using a short function signature.
35
- *
36
- * @example
37
- * ```ts
38
- * const auth = middleware((ctx, next) => {
39
- * return next({ user: "alice" });
40
- * });
41
- * ```
37
+ * Constructs a fluent middleware builder scoped to a single layout branch, with optional explicit State generic.
42
38
  */
43
- <TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(fn: (ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, {}, TRequires>, next: NextFn<NoInfer<TState>>) => R): DefineMiddlewareResult<unknown, unknown, unknown, IsUnknown<TState> extends true ? ExtractState<R> : TState, R, unknown, unknown, unknown, {}, null, TRequires>;
39
+ <const Layout extends LayoutId, TState = unknown>(layout: Layout): MiddlewareUnitBuilder<unknown, unknown, unknown, {}, Layout, {}, TAppContext, ResolveLayoutMiddlewaresState<Layout>, unknown, unknown, unknown, TState>;
40
+ /**
41
+ * Constructs a fluent middleware builder scoped to multiple layout branches (branch union), with optional explicit State generic.
42
+ */
43
+ <const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown>(layouts: Layouts): MiddlewareUnitBuilder<unknown, unknown, unknown, {}, Layouts, {}, TAppContext, ResolveLayoutsState<Layouts>, unknown, unknown, unknown, TState>;
44
44
  }
45
45
  export declare const middleware: MiddlewareFn<AppContext>;
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","names":[],"sources":["../../../src/define/middleware.ts"],"sourcesContent":["import { createMiddlewareUnitBuilder } from \"../builder/middleware-unit.js\";\nimport type {\n DefineMiddlewareResult,\n ExtractState,\n IsUnknown,\n MiddlewareRequirements,\n MiddlewareUnitBuilder,\n NextFn,\n StandaloneMiddlewareContext,\n} from \"../types/units.js\";\nimport type {\n AppContext,\n LayoutId,\n ResolveLayoutMiddlewaresState,\n ResolveLayoutsState,\n} from \"../types/index.js\";\n\nexport interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppContext> {\n /**\n * Constructs a fluent unscoped middleware builder, with optional explicit State generic.\n *\n * @example\n * ```ts\n * const auth = middleware<{ user: string }>()\n * .query(z.object({ token: z.string() }))\n * .body(\"form\", z.object({ file: z.instanceof(File) }))\n * .returns({ 401: z.string() })\n * .handler(async (ctx, next) => next({ user: \"alice\" }));\n * ```\n */\n <TState = unknown>(): MiddlewareUnitBuilder<\n unknown,\n unknown,\n unknown,\n {},\n null,\n {},\n TAppContext,\n {},\n unknown,\n unknown,\n unknown,\n TState\n >;\n\n /**\n * Constructs a fluent middleware builder scoped to a single layout branch, with optional explicit State generic.\n */\n <const Layout extends LayoutId, TState = unknown>(\n layout: Layout,\n ): MiddlewareUnitBuilder<\n unknown,\n unknown,\n unknown,\n {},\n Layout,\n {},\n TAppContext,\n ResolveLayoutMiddlewaresState<Layout>,\n unknown,\n unknown,\n unknown,\n TState\n >;\n\n /**\n * Constructs a fluent middleware builder scoped to multiple layout branches (branch union), with optional explicit State generic.\n */\n <const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown>(\n layouts: Layouts,\n ): MiddlewareUnitBuilder<\n unknown,\n unknown,\n unknown,\n {},\n Layouts,\n {},\n TAppContext,\n ResolveLayoutsState<Layouts>,\n unknown,\n unknown,\n unknown,\n TState\n >;\n\n /**\n * Defines a standalone middleware scoped to a single layout branch using a short function signature.\n */\n <\n const Layout extends LayoutId,\n TState = unknown,\n TRequires extends MiddlewareRequirements = {},\n R = unknown,\n >(\n layout: Layout,\n fn: (\n ctx: StandaloneMiddlewareContext<\n unknown,\n unknown,\n unknown,\n TAppContext,\n ResolveLayoutMiddlewaresState<Layout>,\n TRequires\n >,\n next: NextFn<NoInfer<TState>>,\n ) => R,\n ): DefineMiddlewareResult<\n unknown,\n unknown,\n unknown,\n IsUnknown<TState> extends true ? ExtractState<R> : TState,\n R,\n unknown,\n unknown,\n unknown,\n {},\n Layout,\n TRequires\n >;\n\n /**\n * Defines a standalone middleware scoped to multiple layout branches using a short function signature.\n */\n <\n const Layouts extends readonly [LayoutId, ...LayoutId[]],\n TState = unknown,\n TRequires extends MiddlewareRequirements = {},\n R = unknown,\n >(\n layouts: Layouts,\n fn: (\n ctx: StandaloneMiddlewareContext<\n unknown,\n unknown,\n unknown,\n TAppContext,\n ResolveLayoutsState<Layouts>,\n TRequires\n >,\n next: NextFn<NoInfer<TState>>,\n ) => R,\n ): DefineMiddlewareResult<\n unknown,\n unknown,\n unknown,\n IsUnknown<TState> extends true ? ExtractState<R> : TState,\n R,\n unknown,\n unknown,\n unknown,\n {},\n Layouts,\n TRequires\n >;\n\n /**\n * Defines a standalone, unscoped middleware using a short function signature.\n *\n * @example\n * ```ts\n * const auth = middleware((ctx, next) => {\n * return next({ user: \"alice\" });\n * });\n * ```\n */\n <TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(\n fn: (\n ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, {}, TRequires>,\n next: NextFn<NoInfer<TState>>,\n ) => R,\n ): DefineMiddlewareResult<\n unknown,\n unknown,\n unknown,\n IsUnknown<TState> extends true ? ExtractState<R> : TState,\n R,\n unknown,\n unknown,\n unknown,\n {},\n null,\n TRequires\n >;\n}\n\nexport const middleware: MiddlewareFn<AppContext> = function middleware(\n first?: any,\n second?: any,\n): any {\n if (first === undefined) {\n return createMiddlewareUnitBuilder();\n }\n\n if (typeof first === \"string\" || Array.isArray(first)) {\n if (typeof second === \"function\") {\n return {\n handler: second,\n __middlewareAcc: undefined as unknown,\n __requiredLayouts: first,\n };\n }\n return createMiddlewareUnitBuilder(first);\n }\n\n if (typeof first === \"function\") {\n return {\n handler: first,\n __middlewareAcc: undefined as unknown,\n };\n }\n\n return createMiddlewareUnitBuilder();\n};\n"],"mappings":";;AAyLA,IAAa,aAAuC,SAAS,WAC3D,OACA,QACK;CACL,IAAI,UAAU,KAAA,GACZ,OAAO,4BAA4B;CAGrC,IAAI,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;EACrD,IAAI,OAAO,WAAW,YACpB,OAAO;GACL,SAAS;GACT,iBAAiB,KAAA;GACjB,mBAAmB;EACrB;EAEF,OAAO,4BAA4B,KAAK;CAC1C;CAEA,IAAI,OAAO,UAAU,YACnB,OAAO;EACL,SAAS;EACT,iBAAiB,KAAA;CACnB;CAGF,OAAO,4BAA4B;AACrC"}
1
+ {"version":3,"file":"middleware.js","names":[],"sources":["../../../src/define/middleware.ts"],"sourcesContent":["import { createMiddlewareUnitBuilder } from \"../builder/middleware-unit.js\";\nimport type {\n DefineMiddlewareResult,\n ExtractState,\n IsUnknown,\n MiddlewareRequirements,\n MiddlewareUnitBuilder,\n NextFn,\n StandaloneMiddlewareContext,\n} from \"../types/units.js\";\nimport type {\n AppContext,\n LayoutId,\n ResolveLayoutMiddlewaresState,\n ResolveLayoutsState,\n} from \"../types/index.js\";\n\nexport interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppContext> {\n /**\n * Defines a standalone, unscoped middleware using a short function signature.\n *\n * @example\n * ```ts\n * const auth = middleware((ctx, next) => {\n * return next({ user: \"alice\" });\n * });\n * ```\n */\n <TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(\n fn: (\n ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, {}, TRequires>,\n next: NextFn<NoInfer<TState>>,\n ) => R,\n ): DefineMiddlewareResult<\n unknown,\n unknown,\n unknown,\n IsUnknown<TState> extends true ? ExtractState<R> : TState,\n R,\n unknown,\n unknown,\n unknown,\n {},\n null,\n TRequires\n >;\n\n /**\n * Constructs a fluent unscoped middleware builder, with optional explicit State generic.\n *\n * @example\n * ```ts\n * const auth = middleware<{ user: string }>()\n * .query(z.object({ token: z.string() }))\n * .body(\"form\", z.object({ file: z.instanceof(File) }))\n * .returns({ 401: z.string() })\n * .handler(async (ctx, next) => next({ user: \"alice\" }));\n * ```\n */\n <TState = unknown>(): MiddlewareUnitBuilder<\n unknown,\n unknown,\n unknown,\n {},\n null,\n {},\n TAppContext,\n {},\n unknown,\n unknown,\n unknown,\n TState\n >;\n\n /**\n * Defines a standalone middleware scoped to a single layout branch using a short function signature.\n */\n <\n const Layout extends LayoutId,\n TState = unknown,\n TRequires extends MiddlewareRequirements = {},\n R = unknown,\n >(\n layout: Layout,\n fn: (\n ctx: StandaloneMiddlewareContext<\n unknown,\n unknown,\n unknown,\n TAppContext,\n ResolveLayoutMiddlewaresState<Layout>,\n TRequires\n >,\n next: NextFn<NoInfer<TState>>,\n ) => R,\n ): DefineMiddlewareResult<\n unknown,\n unknown,\n unknown,\n IsUnknown<TState> extends true ? ExtractState<R> : TState,\n R,\n unknown,\n unknown,\n unknown,\n {},\n Layout,\n TRequires\n >;\n\n /**\n * Defines a standalone middleware scoped to multiple layout branches using a short function signature.\n */\n <\n const Layouts extends readonly [LayoutId, ...LayoutId[]],\n TState = unknown,\n TRequires extends MiddlewareRequirements = {},\n R = unknown,\n >(\n layouts: Layouts,\n fn: (\n ctx: StandaloneMiddlewareContext<\n unknown,\n unknown,\n unknown,\n TAppContext,\n ResolveLayoutsState<Layouts>,\n TRequires\n >,\n next: NextFn<NoInfer<TState>>,\n ) => R,\n ): DefineMiddlewareResult<\n unknown,\n unknown,\n unknown,\n IsUnknown<TState> extends true ? ExtractState<R> : TState,\n R,\n unknown,\n unknown,\n unknown,\n {},\n Layouts,\n TRequires\n >;\n\n /**\n * Constructs a fluent middleware builder scoped to a single layout branch, with optional explicit State generic.\n */\n <const Layout extends LayoutId, TState = unknown>(\n layout: Layout,\n ): MiddlewareUnitBuilder<\n unknown,\n unknown,\n unknown,\n {},\n Layout,\n {},\n TAppContext,\n ResolveLayoutMiddlewaresState<Layout>,\n unknown,\n unknown,\n unknown,\n TState\n >;\n\n /**\n * Constructs a fluent middleware builder scoped to multiple layout branches (branch union), with optional explicit State generic.\n */\n <const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown>(\n layouts: Layouts,\n ): MiddlewareUnitBuilder<\n unknown,\n unknown,\n unknown,\n {},\n Layouts,\n {},\n TAppContext,\n ResolveLayoutsState<Layouts>,\n unknown,\n unknown,\n unknown,\n TState\n >;\n}\n\nexport const middleware: MiddlewareFn<AppContext> = function middleware(\n first?: any,\n second?: any,\n): any {\n if (first === undefined) {\n return createMiddlewareUnitBuilder();\n }\n\n if (typeof first === \"string\" || Array.isArray(first)) {\n if (typeof second === \"function\") {\n return {\n handler: second,\n __middlewareAcc: undefined as unknown,\n __requiredLayouts: first,\n };\n }\n return createMiddlewareUnitBuilder(first);\n }\n\n if (typeof first === \"function\") {\n return {\n handler: first,\n __middlewareAcc: undefined as unknown,\n };\n }\n\n return createMiddlewareUnitBuilder();\n};\n"],"mappings":";;AAyLA,IAAa,aAAuC,SAAS,WAC3D,OACA,QACK;CACL,IAAI,UAAU,KAAA,GACZ,OAAO,4BAA4B;CAGrC,IAAI,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;EACrD,IAAI,OAAO,WAAW,YACpB,OAAO;GACL,SAAS;GACT,iBAAiB,KAAA;GACjB,mBAAmB;EACrB;EAEF,OAAO,4BAA4B,KAAK;CAC1C;CAEA,IAAI,OAAO,UAAU,YACnB,OAAO;EACL,SAAS;EACT,iBAAiB,KAAA;CACnB;CAGF,OAAO,4BAA4B;AACrC"}
@@ -1,6 +1,10 @@
1
1
  export interface RouterRegister {
2
2
  }
3
- export type { AppContext, EmptyAppContext, HttpMethod, InferInput, InferOutput, InferRouteContext, InferRouteInput, InferRouteInputFromPath, InferRouteOutput, LayoutBuilder, LayoutId, LayoutTree, Method, MiddlewareBuilder, MiddlewareDefinition, MiddlewareUnit, MiddlewareUnitBuilder, PathParams, ReturnsMap, RouteByPathMethod, RouteDefinition, RouteExport, RoutePath, Schema, Simplify, StatusCode, } from './types/index.js';
3
+ export interface RouterMiddlewaresRegister {
4
+ }
5
+ export interface RouterRoutesRegister {
6
+ }
7
+ export type { AppContext, EmptyAppContext, HttpMethod, InferInput, InferOutput, InferRouteContext, InferRouteInput, InferRouteInputFromPath, InferRouteOutput, LayoutBuilder, LayoutId, LayoutMiddlewaresMap, LayoutTree, Method, MiddlewareBuilder, MiddlewareDefinition, MiddlewareUnit, MiddlewareUnitBuilder, PathParams, ReturnsMap, RouteByPathMethod, RouteDefinition, RouteExport, RoutePath, Schema, Simplify, StatusCode, } from './types/index.js';
4
8
  export type { ContextDefinition, CreateTaserAppOptions, InferAppContext, InferAppManifest, OnErrorOptions, RouteManifestShape, } from './types/app.js';
5
9
  export { ValidationError, validationErrorSchema } from '@taserjs/router-utils';
6
10
  export type { ResponseValidationFailureHandler, SuccessStatusCode } from '@taserjs/router-utils';
@@ -1,4 +1,5 @@
1
1
  import { MiddlewareHandler } from 'hono';
2
+ import { NextFn } from '../types/units.js';
2
3
  /**
3
4
  * Adapts a standard Web / Hono-compatible middleware function `(c, next) => ...`
4
5
  * into a Taser-compatible middleware handler function `(ctx, next) => Promise<Response>`.
@@ -13,4 +14,4 @@ import { MiddlewareHandler } from 'hono';
13
14
  * const customCors = middleware(honoMw(cors()));
14
15
  * ```
15
16
  */
16
- export declare function honoMw(middleware: MiddlewareHandler): (ctx: unknown, next: any) => Promise<Response>;
17
+ export declare function honoMw<TState extends Record<string, unknown> = {}>(middleware: MiddlewareHandler): (ctx: unknown, next: NextFn<TState>) => Promise<Response>;
@@ -1 +1 @@
1
- {"version":3,"file":"hono-mw.js","names":[],"sources":["../../../src/middleware/hono-mw.ts"],"sourcesContent":["import { createTaserCompatHandler } from \"@taserjs/router-core\";\nimport type { MiddlewareHandler } from \"hono\";\n\n/**\n * Adapts a standard Web / Hono-compatible middleware function `(c, next) => ...`\n * into a Taser-compatible middleware handler function `(ctx, next) => Promise<Response>`.\n *\n * @example\n * ```ts\n * import { honoMw } from \"@taserjs/router\";\n * import { cors } from \"hono/cors\";\n *\n * const app = t.get(\"/hello\").use(honoMw(cors()));\n * // or\n * const customCors = middleware(honoMw(cors()));\n * ```\n */\nexport function honoMw(\n middleware: MiddlewareHandler,\n): (ctx: unknown, next: any) => Promise<Response> {\n return createTaserCompatHandler(middleware) as (ctx: unknown, next: any) => Promise<Response>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAiBA,SAAgB,OACd,YACgD;CAChD,OAAO,yBAAyB,UAAU;AAC5C"}
1
+ {"version":3,"file":"hono-mw.js","names":[],"sources":["../../../src/middleware/hono-mw.ts"],"sourcesContent":["import { createTaserCompatHandler } from \"@taserjs/router-core\";\nimport type { MiddlewareHandler } from \"hono\";\n\nimport type { NextFn } from \"../types/units.js\";\n\n/**\n * Adapts a standard Web / Hono-compatible middleware function `(c, next) => ...`\n * into a Taser-compatible middleware handler function `(ctx, next) => Promise<Response>`.\n *\n * @example\n * ```ts\n * import { honoMw } from \"@taserjs/router\";\n * import { cors } from \"hono/cors\";\n *\n * const app = t.get(\"/hello\").use(honoMw(cors()));\n * // or\n * const customCors = middleware(honoMw(cors()));\n * ```\n */\nexport function honoMw<TState extends Record<string, unknown> = {}>(\n middleware: MiddlewareHandler,\n): (ctx: unknown, next: NextFn<TState>) => Promise<Response> {\n return createTaserCompatHandler(middleware) as (ctx: unknown, next: NextFn<TState>) => Promise<Response>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,SAAgB,OACd,YAC2D;CAC3D,OAAO,yBAAyB,UAAU;AAC5C"}
@@ -1,5 +1,5 @@
1
1
  import { Awaitable, TaserCookieJar, TaserHeaders } from '@taserjs/router-core';
2
- import { RouterRegister } from '../index.js';
2
+ import { RouterMiddlewaresRegister, RouterRegister, RouterRoutesRegister } from '../index.js';
3
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';
@@ -21,7 +21,14 @@ export type LayoutId = RouterRegister extends {
21
21
  export type LayoutTree = RouterRegister extends {
22
22
  LayoutTree: infer T;
23
23
  } ? T : Record<never, never>;
24
- export type RouteByPathMethod = RouterRegister extends {
24
+ export type LayoutMiddlewaresMap = RouterMiddlewaresRegister extends {
25
+ LayoutMiddlewares: infer M;
26
+ } ? M : RouterRegister extends {
27
+ LayoutMiddlewares: infer M;
28
+ } ? M : Record<never, never>;
29
+ export type RouteByPathMethod = RouterRoutesRegister extends {
30
+ RouteByPathMethod: infer R;
31
+ } ? R : RouterRegister extends {
25
32
  RouteByPathMethod: infer R;
26
33
  } ? R : Record<never, never>;
27
34
  export type LayoutBuilder<TAppContext extends Record<string, unknown> = AppContext> = <const Layout extends LayoutId>(layout: Layout) => MiddlewareBuilder<Layout, readonly [], TAppContext>;
@@ -33,19 +40,16 @@ type ParseParam<Segment extends string> = Segment extends "*" ? {
33
40
  type ParseParamsFromSegments<S extends string> = S extends `${infer Segment}/${infer Rest}` ? ParseParam<Segment> & ParseParamsFromSegments<Rest> : ParseParam<S>;
34
41
  export type PathParams<Path extends string> = Path extends `/${infer Rest}` ? ParseParamsFromSegments<Rest> : {};
35
42
  export type ResolveParams<TPathParams, TSchemaParams> = TSchemaParams extends Record<string, unknown> ? [keyof TSchemaParams] extends [never] ? TPathParams : Simplify<Omit<TPathParams, keyof TSchemaParams> & TSchemaParams> : TPathParams;
36
- type LayoutParentsMap = RouterRegister extends {
37
- LayoutParents: infer LP extends Record<string, unknown>;
38
- } ? LP : {};
39
- type LayoutParent<Layout extends LayoutId> = Layout extends keyof LayoutParentsMap ? LayoutParentsMap[Layout] extends LayoutId ? LayoutParentsMap[Layout] : null : LayoutTree[Layout] extends {
40
- parent: infer Parent extends LayoutId | null;
41
- } ? Parent : null;
42
- type LayoutMiddlewares<Layout extends LayoutId> = LayoutTree[Layout]["middlewares"] extends {
43
+ type LayoutParent<Layout extends LayoutId> = Layout extends keyof LayoutTree ? LayoutTree[Layout] extends {
44
+ parent: infer P extends LayoutId;
45
+ } ? P : null : null;
46
+ type LayoutMiddlewares<Layout extends LayoutId> = [Layout] extends [keyof LayoutMiddlewaresMap] ? LayoutMiddlewaresMap[Layout] extends {
43
47
  readonly __acc?: infer Acc extends readonly unknown[];
44
- } ? Acc : LayoutTree[Layout]["middlewares"] extends infer Acc extends readonly unknown[] ? Acc : readonly [];
45
- type ResolveLayoutMiddlewares<Layout extends LayoutId | null, Depth extends readonly unknown[] = []> = Depth["length"] extends 10 ? readonly [] : Layout extends LayoutId ? readonly [
46
- ...ResolveLayoutMiddlewares<LayoutParent<Layout>, [...Depth, unknown]>,
48
+ } ? Acc : LayoutMiddlewaresMap[Layout] extends readonly unknown[] ? LayoutMiddlewaresMap[Layout] : readonly [] : readonly [];
49
+ type ResolveLayoutMiddlewares<Layout extends LayoutId | null, Depth extends readonly unknown[] = []> = Depth["length"] extends 10 ? readonly [] : [Layout] extends [LayoutId] ? LayoutParent<Layout> extends infer Parent extends LayoutId ? readonly [
50
+ ...ResolveLayoutMiddlewares<Parent, [...Depth, unknown]>,
47
51
  ...LayoutMiddlewares<Layout>
48
- ] : readonly [];
52
+ ] : readonly [...LayoutMiddlewares<Layout>] : readonly [];
49
53
  export type ResolveLayoutIdChain<L extends LayoutId | null, Depth extends readonly unknown[] = []> = Depth["length"] extends 10 ? readonly [] : L extends LayoutId ? readonly [...ResolveLayoutIdChain<LayoutParent<L>, [...Depth, unknown]>, L] : readonly [];
50
54
  export type ResolveLayoutMiddlewaresState<Layout extends LayoutId | null> = Layout extends LayoutId ? MergeMiddlewareField<ResolveLayoutMiddlewares<Layout>, "state"> : {};
51
55
  export type ResolveLayoutsState<Layouts extends LayoutId | readonly LayoutId[]> = Layouts extends LayoutId ? ResolveLayoutMiddlewaresState<Layouts> : Layouts extends readonly LayoutId[] ? UnionToIntersection<Layouts[number] extends infer L extends LayoutId ? ResolveLayoutMiddlewaresState<L> : never> : {};
@@ -60,21 +64,18 @@ type ResolveLayoutChainMiddlewares<Chain extends readonly LayoutId[]> = Chain ex
60
64
  type RouteEntry<Path extends RoutePath, TMethod extends Method> = RouteByPathMethod[Path] extends {
61
65
  [K in TMethod]: infer Entry;
62
66
  } ? Entry : never;
63
- type RouteParent<Path extends RoutePath, TMethod extends Method> = RouteEntry<Path, TMethod> extends {
64
- parent: infer Parent extends LayoutId | null;
65
- } ? Parent : null;
66
67
  type RouteLayoutChain<Path extends RoutePath, TMethod extends Method> = RouteEntry<Path, TMethod> extends {
67
- layoutChain: infer Chain extends readonly LayoutId[];
68
- } ? Chain : RouteParent<Path, TMethod> extends LayoutId ? readonly [RouteParent<Path, TMethod>] : readonly [];
68
+ layouts: infer Chain extends readonly LayoutId[];
69
+ } ? Chain : readonly [];
69
70
  export type RouteLayoutMiddlewares<Path extends RoutePath, TMethod extends Method> = ResolveLayoutChainMiddlewares<RouteLayoutChain<Path, TMethod>>;
70
71
  export type RouteLayoutField<Path extends RoutePath, TMethod extends Method, Field extends "query" | "params" | "body" | "state"> = MergeMiddlewareField<RouteLayoutMiddlewares<Path, TMethod>, Field>;
71
72
  export type RouteLayoutInputField<Path extends RoutePath, TMethod extends Method, Field extends "query" | "params" | "body"> = MergeMiddlewareInputField<RouteLayoutMiddlewares<Path, TMethod>, Field>;
72
73
  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>;
73
74
  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 & {
74
- query: Simplify<MergePart<TQuery, RouteResolvedField<Path, TMethod, Acc, "query">>>;
75
- params: Simplify<ResolveParams<PathParams<Path>, MergePart<TParams, RouteResolvedField<Path, TMethod, Acc, "params">>>>;
76
- body: Simplify<MergePart<TBody, RouteResolvedField<Path, TMethod, Acc, "body">>>;
77
- state: Simplify<RouteResolvedField<Path, TMethod, Acc, "state">>;
75
+ query: MergePart<TQuery, RouteResolvedField<Path, TMethod, Acc, "query">>;
76
+ params: ResolveParams<PathParams<Path>, MergePart<TParams, RouteResolvedField<Path, TMethod, Acc, "params">>>;
77
+ body: MergePart<TBody, RouteResolvedField<Path, TMethod, Acc, "body">>;
78
+ state: RouteResolvedField<Path, TMethod, Acc, "state">;
78
79
  headers: TaserHeaders;
79
80
  cookies: TaserCookieJar;
80
81
  }>;
@@ -167,23 +168,23 @@ export type InferRouteInputFromPath<Path extends RoutePath, TMethod extends Meth
167
168
  Input: infer I;
168
169
  };
169
170
  } ? I : never : never;
170
- export type MiddlewareLayoutField<Layout extends LayoutId, Field extends "query" | "params" | "body" | "state"> = MergeMiddlewareField<ResolveLayoutMiddlewares<LayoutParent<Layout>>, Field>;
171
+ export type MiddlewareLayoutField<Layout extends LayoutId, Field extends "query" | "params" | "body" | "state"> = [LayoutParent<Layout>] extends [infer Parent extends LayoutId] ? MergeMiddlewareField<ResolveLayoutMiddlewares<Parent>, Field> : {};
171
172
  type MiddlewareChainField<Layout extends LayoutId, Acc extends readonly unknown[], Field extends "query" | "params" | "body" | "state"> = MiddlewareLayoutField<Layout, Field> & MergeMiddlewareField<Acc, Field>;
172
- export type MiddlewareChainContext<Layout extends LayoutId, Acc extends readonly unknown[], TQuery, TParams, TBody, TAppContext extends Record<string, unknown> = AppContext> = Simplify<TAppContext & UnitRuntimeContext & {
173
+ export type MiddlewareChainContext<Layout extends LayoutId, Acc extends readonly unknown[], TQuery = unknown, TParams = unknown, TBody = unknown, TAppContext extends Record<string, unknown> = AppContext> = Simplify<TAppContext & {
174
+ readonly request: Request;
175
+ readonly method: Method;
176
+ readonly url: URL;
177
+ readonly headers: TaserHeaders;
178
+ readonly cookies: TaserCookieJar;
173
179
  query: Simplify<MergePart<TQuery, MiddlewareChainField<Layout, Acc, "query">>>;
174
180
  params: Simplify<MergePart<TParams, MiddlewareChainField<Layout, Acc, "params">>>;
175
181
  body: Simplify<MergePart<TBody, MiddlewareChainField<Layout, Acc, "body">>>;
176
182
  state: Simplify<MiddlewareChainField<Layout, Acc, "state">>;
177
- headers: TaserHeaders;
178
- cookies: TaserCookieJar;
179
183
  }>;
180
184
  export type MiddlewareBuilder<Layout extends LayoutId, Acc extends readonly unknown[] = readonly [], TAppContext extends Record<string, unknown> = AppContext> = {
181
185
  readonly layout: Layout;
182
186
  readonly middlewares: readonly MiddlewareDefinition[];
183
187
  readonly __acc?: Acc;
184
- readonly $Infer: {
185
- Context: MiddlewareChainContext<Layout, Acc, unknown, unknown, unknown, TAppContext>;
186
- };
187
188
  use<TAcc, TReturns extends ReturnsMap = {}, TRequiredLayouts = unknown, TRequires extends MiddlewareRequirements = {}>(unit: [
188
189
  IsLayoutAllowed<TRequiredLayouts, ResolveLayoutIdChain<Layout>>,
189
190
  IsRequirementsSatisfied<{
@@ -192,19 +193,18 @@ export type MiddlewareBuilder<Layout extends LayoutId, Acc extends readonly unkn
192
193
  body: MiddlewareChainField<Layout, Acc, "body">;
193
194
  state: MiddlewareChainField<Layout, Acc, "state">;
194
195
  }, TRequires>
195
- ] extends [true, true] ? MiddlewareUnit<TAcc, TReturns, TRequiredLayouts, TRequires> : {
196
- error: "Middleware cannot be attached to this layout";
197
- requiredLayouts: TRequiredLayouts;
198
- layoutChain: ResolveLayoutIdChain<Layout>;
199
- requirements: TRequires;
200
- actual: {
201
- query: MiddlewareChainField<Layout, Acc, "query">;
202
- params: MiddlewareChainField<Layout, Acc, "params">;
203
- body: MiddlewareChainField<Layout, Acc, "body">;
204
- state: MiddlewareChainField<Layout, Acc, "state">;
205
- };
206
- }): MiddlewareBuilder<Layout, readonly [...Acc, TAcc], TAppContext>;
207
- use<R = unknown>(fn: (ctx: MiddlewareChainContext<Layout, Acc, unknown, unknown, unknown, TAppContext>, next: NextFn) => Awaitable<R>): MiddlewareBuilder<Layout, readonly [...Acc, MiddlewareReturnFromParts<unknown, unknown, unknown, ExtractState<R>>], TAppContext>;
196
+ ] extends [true, true] ? MiddlewareUnit<TAcc, TReturns, TRequiredLayouts, TRequires> : never): MiddlewareBuilder<Layout, readonly [...Acc, TAcc], TAppContext>;
197
+ use<R = unknown>(fn: (ctx: Simplify<TAppContext & {
198
+ readonly request: Request;
199
+ readonly method: Method;
200
+ readonly url: URL;
201
+ readonly headers: TaserHeaders;
202
+ readonly cookies: TaserCookieJar;
203
+ query: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "query">>>;
204
+ params: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "params">>>;
205
+ body: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "body">>>;
206
+ state: Simplify<MiddlewareChainField<Layout, Acc, "state">>;
207
+ }>, next: NextFn) => Awaitable<R>): MiddlewareBuilder<Layout, readonly [...Acc, MiddlewareReturnFromParts<unknown, unknown, unknown, ExtractState<R>>], TAppContext>;
208
208
  };
209
209
  export type RouteExport<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], TReturns extends ReturnsMap = {}, TOutput = Response> = {
210
210
  readonly path: Path;
@@ -274,18 +274,7 @@ export type RouteMiddlewareBuilder<Path extends RoutePath, TMethod extends Metho
274
274
  body: RouteResolvedField<Path, TMethod, Acc, "body">;
275
275
  state: RouteResolvedField<Path, TMethod, Acc, "state">;
276
276
  }, TRequires>
277
- ] extends [true, true] ? MiddlewareUnit<TAcc, UReturns, TRequiredLayouts, TRequires> : {
278
- error: "Middleware cannot be attached to this route";
279
- requiredLayouts: TRequiredLayouts;
280
- routeLayoutChain: RouteLayoutChain<Path, TMethod>;
281
- requirements: TRequires;
282
- actual: {
283
- query: RouteResolvedField<Path, TMethod, Acc, "query">;
284
- params: ResolveParams<PathParams<Path>, RouteResolvedField<Path, TMethod, Acc, "params">>;
285
- body: RouteResolvedField<Path, TMethod, Acc, "body">;
286
- state: RouteResolvedField<Path, TMethod, Acc, "state">;
287
- };
288
- }): RouteMiddlewareBuilder<Path, TMethod, readonly [...Acc, TAcc], Validators, Omit<TReturns, keyof UReturns> & UReturns, TAppContext>;
277
+ ] extends [true, true] ? MiddlewareUnit<TAcc, UReturns, TRequiredLayouts, TRequires> : never): RouteMiddlewareBuilder<Path, TMethod, readonly [...Acc, TAcc], Validators, Omit<TReturns, keyof UReturns> & UReturns, TAppContext>;
289
278
  use<R = unknown>(fn: (ctx: RouteChainContext<Path, TMethod, Acc, unknown, unknown, unknown, TAppContext>, next: NextFn) => Awaitable<R>): RouteMiddlewareBuilder<Path, TMethod, readonly [...Acc, MiddlewareReturnFromParts<unknown, unknown, unknown, ExtractState<R>>], Validators, TReturns, TAppContext>;
290
279
  };
291
280
  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> = RouteMiddlewareBuilder<Path, TMethod, Acc, Validators, TReturns, TAppContext>;
@@ -7,9 +7,9 @@ export type MiddlewareInputFieldName = "query" | "params" | "body";
7
7
  export type UnwrapPart<T> = unknown extends T ? {} : T;
8
8
  export type MergePart<T, Base> = unknown extends T ? Base : Base & T;
9
9
  /** Collapse intersections so `Omit`/`keyof` treat the result as one object type. */
10
- export type Simplify<T> = {
11
- [K in keyof T]: T[K];
12
- } & {};
10
+ export type Simplify<T> = [T] extends [infer U] ? {
11
+ [K in keyof U]: U[K];
12
+ } : never;
13
13
  /**
14
14
  * Request prop: when schema input is `unknown` (e.g. zod coerce),
15
15
  * fall back to the validated output type.
@@ -26,10 +26,10 @@ export type IsUnknown<T> = [unknown] extends [T] ? true : false;
26
26
  export type NextFn<TExpectedState = unknown> = IsUnknown<TExpectedState> extends true ? <S extends Record<string, unknown> = {}>(state?: S) => Promise<NextResult<S>> : (state: TExpectedState) => Promise<NextResult<TExpectedState>>;
27
27
  export type MiddlewareDefinition = CoreMiddlewareDefinition<ReturnsMap>;
28
28
  export type MiddlewareReturnFromParts<TQuery, TParams, TBody, TState, TQueryIn = TQuery, TParamsIn = TParams, TBodyIn = TBody> = {
29
- query: Simplify<UnwrapPart<TQuery>>;
30
- params: Simplify<UnwrapPart<TParams>>;
31
- body: Simplify<UnwrapPart<TBody>>;
32
- state: Simplify<UnwrapPart<TState>>;
29
+ query: UnwrapPart<TQuery>;
30
+ params: UnwrapPart<TParams>;
31
+ body: UnwrapPart<TBody>;
32
+ state: UnwrapPart<TState>;
33
33
  /** Pre-parse shapes merged into route `$Infer.Input`. */
34
34
  input: {
35
35
  query: RequestShape<TQueryIn, TQuery>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taserjs/router",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
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.1.7",
151
- "@taserjs/router-utils": "0.1.7"
150
+ "@taserjs/router-core": "0.1.8",
151
+ "@taserjs/router-utils": "0.1.8"
152
152
  },
153
153
  "devDependencies": {
154
154
  "@tanstack/vite-config": "^0.6.0",
@@ -17,66 +17,55 @@ import type {
17
17
 
18
18
  export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppContext> {
19
19
  /**
20
- * Constructs a fluent unscoped middleware builder, with optional explicit State generic.
20
+ * Defines a standalone, unscoped middleware using a short function signature.
21
21
  *
22
22
  * @example
23
23
  * ```ts
24
- * const auth = middleware<{ user: string }>()
25
- * .query(z.object({ token: z.string() }))
26
- * .body("form", z.object({ file: z.instanceof(File) }))
27
- * .returns({ 401: z.string() })
28
- * .handler(async (ctx, next) => next({ user: "alice" }));
24
+ * const auth = middleware((ctx, next) => {
25
+ * return next({ user: "alice" });
26
+ * });
29
27
  * ```
30
28
  */
31
- <TState = unknown>(): MiddlewareUnitBuilder<
32
- unknown,
33
- unknown,
34
- unknown,
35
- {},
36
- null,
37
- {},
38
- TAppContext,
39
- {},
29
+ <TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(
30
+ fn: (
31
+ ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, {}, TRequires>,
32
+ next: NextFn<NoInfer<TState>>,
33
+ ) => R,
34
+ ): DefineMiddlewareResult<
40
35
  unknown,
41
36
  unknown,
42
37
  unknown,
43
- TState
44
- >;
45
-
46
- /**
47
- * Constructs a fluent middleware builder scoped to a single layout branch, with optional explicit State generic.
48
- */
49
- <const Layout extends LayoutId, TState = unknown>(
50
- layout: Layout,
51
- ): MiddlewareUnitBuilder<
38
+ IsUnknown<TState> extends true ? ExtractState<R> : TState,
39
+ R,
52
40
  unknown,
53
41
  unknown,
54
42
  unknown,
55
43
  {},
56
- Layout,
57
- {},
58
- TAppContext,
59
- ResolveLayoutMiddlewaresState<Layout>,
60
- unknown,
61
- unknown,
62
- unknown,
63
- TState
44
+ null,
45
+ TRequires
64
46
  >;
65
47
 
66
48
  /**
67
- * Constructs a fluent middleware builder scoped to multiple layout branches (branch union), with optional explicit State generic.
49
+ * Constructs a fluent unscoped middleware builder, with optional explicit State generic.
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * const auth = middleware<{ user: string }>()
54
+ * .query(z.object({ token: z.string() }))
55
+ * .body("form", z.object({ file: z.instanceof(File) }))
56
+ * .returns({ 401: z.string() })
57
+ * .handler(async (ctx, next) => next({ user: "alice" }));
58
+ * ```
68
59
  */
69
- <const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown>(
70
- layouts: Layouts,
71
- ): MiddlewareUnitBuilder<
60
+ <TState = unknown>(): MiddlewareUnitBuilder<
72
61
  unknown,
73
62
  unknown,
74
63
  unknown,
75
64
  {},
76
- Layouts,
65
+ null,
77
66
  {},
78
67
  TAppContext,
79
- ResolveLayoutsState<Layouts>,
68
+ {},
80
69
  unknown,
81
70
  unknown,
82
71
  unknown,
@@ -154,32 +143,43 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
154
143
  >;
155
144
 
156
145
  /**
157
- * Defines a standalone, unscoped middleware using a short function signature.
158
- *
159
- * @example
160
- * ```ts
161
- * const auth = middleware((ctx, next) => {
162
- * return next({ user: "alice" });
163
- * });
164
- * ```
146
+ * Constructs a fluent middleware builder scoped to a single layout branch, with optional explicit State generic.
165
147
  */
166
- <TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(
167
- fn: (
168
- ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, {}, TRequires>,
169
- next: NextFn<NoInfer<TState>>,
170
- ) => R,
171
- ): DefineMiddlewareResult<
148
+ <const Layout extends LayoutId, TState = unknown>(
149
+ layout: Layout,
150
+ ): MiddlewareUnitBuilder<
172
151
  unknown,
173
152
  unknown,
174
153
  unknown,
175
- IsUnknown<TState> extends true ? ExtractState<R> : TState,
176
- R,
154
+ {},
155
+ Layout,
156
+ {},
157
+ TAppContext,
158
+ ResolveLayoutMiddlewaresState<Layout>,
159
+ unknown,
160
+ unknown,
161
+ unknown,
162
+ TState
163
+ >;
164
+
165
+ /**
166
+ * Constructs a fluent middleware builder scoped to multiple layout branches (branch union), with optional explicit State generic.
167
+ */
168
+ <const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown>(
169
+ layouts: Layouts,
170
+ ): MiddlewareUnitBuilder<
177
171
  unknown,
178
172
  unknown,
179
173
  unknown,
180
174
  {},
181
- null,
182
- TRequires
175
+ Layouts,
176
+ {},
177
+ TAppContext,
178
+ ResolveLayoutsState<Layouts>,
179
+ unknown,
180
+ unknown,
181
+ unknown,
182
+ TState
183
183
  >;
184
184
  }
185
185
 
package/src/index.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export interface RouterRegister {}
2
+ export interface RouterMiddlewaresRegister {}
3
+ export interface RouterRoutesRegister {}
2
4
  export type {
3
5
  AppContext,
4
6
  EmptyAppContext,
@@ -11,6 +13,7 @@ export type {
11
13
  InferRouteOutput,
12
14
  LayoutBuilder,
13
15
  LayoutId,
16
+ LayoutMiddlewaresMap,
14
17
  LayoutTree,
15
18
  Method,
16
19
  MiddlewareBuilder,
@@ -1,6 +1,8 @@
1
1
  import { createTaserCompatHandler } from "@taserjs/router-core";
2
2
  import type { MiddlewareHandler } from "hono";
3
3
 
4
+ import type { NextFn } from "../types/units.js";
5
+
4
6
  /**
5
7
  * Adapts a standard Web / Hono-compatible middleware function `(c, next) => ...`
6
8
  * into a Taser-compatible middleware handler function `(ctx, next) => Promise<Response>`.
@@ -15,8 +17,8 @@ import type { MiddlewareHandler } from "hono";
15
17
  * const customCors = middleware(honoMw(cors()));
16
18
  * ```
17
19
  */
18
- export function honoMw(
20
+ export function honoMw<TState extends Record<string, unknown> = {}>(
19
21
  middleware: MiddlewareHandler,
20
- ): (ctx: unknown, next: any) => Promise<Response> {
21
- return createTaserCompatHandler(middleware) as (ctx: unknown, next: any) => Promise<Response>;
22
+ ): (ctx: unknown, next: NextFn<TState>) => Promise<Response> {
23
+ return createTaserCompatHandler(middleware) as (ctx: unknown, next: NextFn<TState>) => Promise<Response>;
22
24
  }
@@ -1,5 +1,9 @@
1
1
  import type { Awaitable, TaserCookieJar, TaserHeaders } from "@taserjs/router-core";
2
- import type { RouterRegister } from "../index.js";
2
+ import type {
3
+ RouterMiddlewaresRegister,
4
+ RouterRegister,
5
+ RouterRoutesRegister,
6
+ } from "../index.js";
3
7
  import type {
4
8
  MergeMiddlewareField,
5
9
  MergeMiddlewareInputField,
@@ -74,9 +78,18 @@ export type AppContext = RouterRegister extends { AppContext: infer C } ? C : Em
74
78
  export type RoutePath = RouterRegister extends { RoutePath: infer P } ? P : never;
75
79
  export type LayoutId = RouterRegister extends { LayoutId: infer L } ? L : never;
76
80
  export type LayoutTree = RouterRegister extends { LayoutTree: infer T } ? T : Record<never, never>;
77
- export type RouteByPathMethod = RouterRegister extends { RouteByPathMethod: infer R }
81
+ export type LayoutMiddlewaresMap = RouterMiddlewaresRegister extends {
82
+ LayoutMiddlewares: infer M;
83
+ }
84
+ ? M
85
+ : RouterRegister extends { LayoutMiddlewares: infer M }
86
+ ? M
87
+ : Record<never, never>;
88
+ export type RouteByPathMethod = RouterRoutesRegister extends { RouteByPathMethod: infer R }
78
89
  ? R
79
- : Record<never, never>;
90
+ : RouterRegister extends { RouteByPathMethod: infer R }
91
+ ? R
92
+ : Record<never, never>;
80
93
 
81
94
  export type LayoutBuilder<TAppContext extends Record<string, unknown> = AppContext> = <
82
95
  const Layout extends LayoutId,
@@ -107,40 +120,32 @@ export type ResolveParams<TPathParams, TSchemaParams> =
107
120
  : Simplify<Omit<TPathParams, keyof TSchemaParams> & TSchemaParams>
108
121
  : TPathParams;
109
122
 
110
- type LayoutParentsMap = RouterRegister extends {
111
- LayoutParents: infer LP extends Record<string, unknown>;
112
- }
113
- ? LP
114
- : {};
115
-
116
- type LayoutParent<Layout extends LayoutId> = Layout extends keyof LayoutParentsMap
117
- ? LayoutParentsMap[Layout] extends LayoutId
118
- ? LayoutParentsMap[Layout]
123
+ type LayoutParent<Layout extends LayoutId> = Layout extends keyof LayoutTree
124
+ ? LayoutTree[Layout] extends { parent: infer P extends LayoutId }
125
+ ? P
119
126
  : null
120
- : LayoutTree[Layout] extends {
121
- parent: infer Parent extends LayoutId | null;
122
- }
123
- ? Parent
124
- : null;
125
-
126
- type LayoutMiddlewares<Layout extends LayoutId> = LayoutTree[Layout]["middlewares"] extends {
127
- readonly __acc?: infer Acc extends readonly unknown[];
128
- }
129
- ? Acc
130
- : LayoutTree[Layout]["middlewares"] extends infer Acc extends readonly unknown[]
127
+ : null;
128
+
129
+ type LayoutMiddlewares<Layout extends LayoutId> = [Layout] extends [keyof LayoutMiddlewaresMap]
130
+ ? LayoutMiddlewaresMap[Layout] extends { readonly __acc?: infer Acc extends readonly unknown[] }
131
131
  ? Acc
132
- : readonly [];
132
+ : LayoutMiddlewaresMap[Layout] extends readonly unknown[]
133
+ ? LayoutMiddlewaresMap[Layout]
134
+ : readonly []
135
+ : readonly [];
133
136
 
134
137
  type ResolveLayoutMiddlewares<
135
138
  Layout extends LayoutId | null,
136
139
  Depth extends readonly unknown[] = [],
137
140
  > = Depth["length"] extends 10
138
141
  ? readonly []
139
- : Layout extends LayoutId
140
- ? readonly [
141
- ...ResolveLayoutMiddlewares<LayoutParent<Layout>, [...Depth, unknown]>,
142
- ...LayoutMiddlewares<Layout>,
143
- ]
142
+ : [Layout] extends [LayoutId]
143
+ ? LayoutParent<Layout> extends infer Parent extends LayoutId
144
+ ? readonly [
145
+ ...ResolveLayoutMiddlewares<Parent, [...Depth, unknown]>,
146
+ ...LayoutMiddlewares<Layout>,
147
+ ]
148
+ : readonly [...LayoutMiddlewares<Layout>]
144
149
  : readonly [];
145
150
 
146
151
  export type ResolveLayoutIdChain<
@@ -184,17 +189,10 @@ type RouteEntry<Path extends RoutePath, TMethod extends Method> = RouteByPathMet
184
189
  ? Entry
185
190
  : never;
186
191
 
187
- type RouteParent<Path extends RoutePath, TMethod extends Method> =
188
- RouteEntry<Path, TMethod> extends { parent: infer Parent extends LayoutId | null }
189
- ? Parent
190
- : null;
191
-
192
192
  type RouteLayoutChain<Path extends RoutePath, TMethod extends Method> =
193
- RouteEntry<Path, TMethod> extends { layoutChain: infer Chain extends readonly LayoutId[] }
193
+ RouteEntry<Path, TMethod> extends { layouts: infer Chain extends readonly LayoutId[] }
194
194
  ? Chain
195
- : RouteParent<Path, TMethod> extends LayoutId
196
- ? readonly [RouteParent<Path, TMethod>]
197
- : readonly [];
195
+ : readonly [];
198
196
 
199
197
  export type RouteLayoutMiddlewares<
200
198
  Path extends RoutePath,
@@ -231,15 +229,13 @@ export type RouteChainContext<
231
229
  > = Simplify<
232
230
  TAppContext &
233
231
  UnitRuntimeContext & {
234
- query: Simplify<MergePart<TQuery, RouteResolvedField<Path, TMethod, Acc, "query">>>;
235
- params: Simplify<
236
- ResolveParams<
237
- PathParams<Path>,
238
- MergePart<TParams, RouteResolvedField<Path, TMethod, Acc, "params">>
239
- >
232
+ query: MergePart<TQuery, RouteResolvedField<Path, TMethod, Acc, "query">>;
233
+ params: ResolveParams<
234
+ PathParams<Path>,
235
+ MergePart<TParams, RouteResolvedField<Path, TMethod, Acc, "params">>
240
236
  >;
241
- body: Simplify<MergePart<TBody, RouteResolvedField<Path, TMethod, Acc, "body">>>;
242
- state: Simplify<RouteResolvedField<Path, TMethod, Acc, "state">>;
237
+ body: MergePart<TBody, RouteResolvedField<Path, TMethod, Acc, "body">>;
238
+ state: RouteResolvedField<Path, TMethod, Acc, "state">;
243
239
  headers: TaserHeaders;
244
240
  cookies: TaserCookieJar;
245
241
  }
@@ -496,7 +492,9 @@ export type InferRouteInputFromPath<Path extends RoutePath, TMethod extends Meth
496
492
  export type MiddlewareLayoutField<
497
493
  Layout extends LayoutId,
498
494
  Field extends "query" | "params" | "body" | "state",
499
- > = MergeMiddlewareField<ResolveLayoutMiddlewares<LayoutParent<Layout>>, Field>;
495
+ > = [LayoutParent<Layout>] extends [infer Parent extends LayoutId]
496
+ ? MergeMiddlewareField<ResolveLayoutMiddlewares<Parent>, Field>
497
+ : {};
500
498
 
501
499
  type MiddlewareChainField<
502
500
  Layout extends LayoutId,
@@ -507,20 +505,22 @@ type MiddlewareChainField<
507
505
  export type MiddlewareChainContext<
508
506
  Layout extends LayoutId,
509
507
  Acc extends readonly unknown[],
510
- TQuery,
511
- TParams,
512
- TBody,
508
+ TQuery = unknown,
509
+ TParams = unknown,
510
+ TBody = unknown,
513
511
  TAppContext extends Record<string, unknown> = AppContext,
514
512
  > = Simplify<
515
- TAppContext &
516
- UnitRuntimeContext & {
517
- query: Simplify<MergePart<TQuery, MiddlewareChainField<Layout, Acc, "query">>>;
518
- params: Simplify<MergePart<TParams, MiddlewareChainField<Layout, Acc, "params">>>;
519
- body: Simplify<MergePart<TBody, MiddlewareChainField<Layout, Acc, "body">>>;
520
- state: Simplify<MiddlewareChainField<Layout, Acc, "state">>;
521
- headers: TaserHeaders;
522
- cookies: TaserCookieJar;
523
- }
513
+ TAppContext & {
514
+ readonly request: Request;
515
+ readonly method: Method;
516
+ readonly url: URL;
517
+ readonly headers: TaserHeaders;
518
+ readonly cookies: TaserCookieJar;
519
+ query: Simplify<MergePart<TQuery, MiddlewareChainField<Layout, Acc, "query">>>;
520
+ params: Simplify<MergePart<TParams, MiddlewareChainField<Layout, Acc, "params">>>;
521
+ body: Simplify<MergePart<TBody, MiddlewareChainField<Layout, Acc, "body">>>;
522
+ state: Simplify<MiddlewareChainField<Layout, Acc, "state">>;
523
+ }
524
524
  >;
525
525
 
526
526
  export type MiddlewareBuilder<
@@ -531,9 +531,6 @@ export type MiddlewareBuilder<
531
531
  readonly layout: Layout;
532
532
  readonly middlewares: readonly MiddlewareDefinition[];
533
533
  readonly __acc?: Acc;
534
- readonly $Infer: {
535
- Context: MiddlewareChainContext<Layout, Acc, unknown, unknown, unknown, TAppContext>;
536
- };
537
534
  use<
538
535
  TAcc,
539
536
  TReturns extends ReturnsMap = {},
@@ -553,22 +550,23 @@ export type MiddlewareBuilder<
553
550
  >,
554
551
  ] extends [true, true]
555
552
  ? MiddlewareUnit<TAcc, TReturns, TRequiredLayouts, TRequires>
556
- : {
557
- error: "Middleware cannot be attached to this layout";
558
- requiredLayouts: TRequiredLayouts;
559
- layoutChain: ResolveLayoutIdChain<Layout>;
560
- requirements: TRequires;
561
- actual: {
562
- query: MiddlewareChainField<Layout, Acc, "query">;
563
- params: MiddlewareChainField<Layout, Acc, "params">;
564
- body: MiddlewareChainField<Layout, Acc, "body">;
565
- state: MiddlewareChainField<Layout, Acc, "state">;
566
- };
567
- },
553
+ : never,
568
554
  ): MiddlewareBuilder<Layout, readonly [...Acc, TAcc], TAppContext>;
569
555
  use<R = unknown>(
570
556
  fn: (
571
- ctx: MiddlewareChainContext<Layout, Acc, unknown, unknown, unknown, TAppContext>,
557
+ ctx: Simplify<
558
+ TAppContext & {
559
+ readonly request: Request;
560
+ readonly method: Method;
561
+ readonly url: URL;
562
+ readonly headers: TaserHeaders;
563
+ readonly cookies: TaserCookieJar;
564
+ query: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "query">>>;
565
+ params: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "params">>>;
566
+ body: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "body">>>;
567
+ state: Simplify<MiddlewareChainField<Layout, Acc, "state">>;
568
+ }
569
+ >,
572
570
  next: NextFn,
573
571
  ) => Awaitable<R>,
574
572
  ): MiddlewareBuilder<
@@ -747,21 +745,7 @@ export type RouteMiddlewareBuilder<
747
745
  >,
748
746
  ] extends [true, true]
749
747
  ? MiddlewareUnit<TAcc, UReturns, TRequiredLayouts, TRequires>
750
- : {
751
- error: "Middleware cannot be attached to this route";
752
- requiredLayouts: TRequiredLayouts;
753
- routeLayoutChain: RouteLayoutChain<Path, TMethod>;
754
- requirements: TRequires;
755
- actual: {
756
- query: RouteResolvedField<Path, TMethod, Acc, "query">;
757
- params: ResolveParams<
758
- PathParams<Path>,
759
- RouteResolvedField<Path, TMethod, Acc, "params">
760
- >;
761
- body: RouteResolvedField<Path, TMethod, Acc, "body">;
762
- state: RouteResolvedField<Path, TMethod, Acc, "state">;
763
- };
764
- },
748
+ : never,
765
749
  ): RouteMiddlewareBuilder<
766
750
  Path,
767
751
  TMethod,
@@ -13,7 +13,7 @@ export type UnwrapPart<T> = unknown extends T ? {} : T;
13
13
  export type MergePart<T, Base> = unknown extends T ? Base : Base & T;
14
14
 
15
15
  /** Collapse intersections so `Omit`/`keyof` treat the result as one object type. */
16
- export type Simplify<T> = { [K in keyof T]: T[K] } & {};
16
+ export type Simplify<T> = [T] extends [infer U] ? { [K in keyof U]: U[K] } : never;
17
17
 
18
18
  /**
19
19
  * Request prop: when schema input is `unknown` (e.g. zod coerce),
@@ -68,10 +68,10 @@ export type MiddlewareReturnFromParts<
68
68
  TParamsIn = TParams,
69
69
  TBodyIn = TBody,
70
70
  > = {
71
- query: Simplify<UnwrapPart<TQuery>>;
72
- params: Simplify<UnwrapPart<TParams>>;
73
- body: Simplify<UnwrapPart<TBody>>;
74
- state: Simplify<UnwrapPart<TState>>;
71
+ query: UnwrapPart<TQuery>;
72
+ params: UnwrapPart<TParams>;
73
+ body: UnwrapPart<TBody>;
74
+ state: UnwrapPart<TState>;
75
75
  /** Pre-parse shapes merged into route `$Infer.Input`. */
76
76
  input: {
77
77
  query: RequestShape<TQueryIn, TQuery>;