@taserjs/router 0.1.5 → 0.1.7

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,4 +1,4 @@
1
- import { DefineMiddlewareResult, ExtractState, IsUnknown, MiddlewareUnitBuilder, NextFn, StandaloneMiddlewareContext } from '../types/units.js';
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
4
  /**
@@ -25,11 +25,11 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
25
25
  /**
26
26
  * Defines a standalone middleware scoped to a single layout branch using a short function signature.
27
27
  */
28
- <const Layout extends LayoutId, TState = unknown, TRequires = {}, R = unknown>(layout: Layout, fn: (ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, ResolveLayoutMiddlewaresState<Layout> & TRequires>, next: NextFn<NoInfer<TState>>) => R): DefineMiddlewareResult<unknown, unknown, unknown, IsUnknown<TState> extends true ? ExtractState<R> : TState, R, unknown, unknown, unknown, {}, Layout, TRequires>;
28
+ <const Layout extends LayoutId, TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(layout: Layout, fn: (ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, ResolveLayoutMiddlewaresState<Layout>, TRequires>, next: NextFn<NoInfer<TState>>) => R): DefineMiddlewareResult<unknown, unknown, unknown, IsUnknown<TState> extends true ? ExtractState<R> : TState, R, unknown, unknown, unknown, {}, Layout, TRequires>;
29
29
  /**
30
30
  * Defines a standalone middleware scoped to multiple layout branches using a short function signature.
31
31
  */
32
- <const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown, TRequires = {}, 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>;
32
+ <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
33
  /**
34
34
  * Defines a standalone, unscoped middleware using a short function signature.
35
35
  *
@@ -40,6 +40,6 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
40
40
  * });
41
41
  * ```
42
42
  */
43
- <TState = unknown, TRequires = {}, 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>;
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>;
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 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 <const Layout extends LayoutId, TState = unknown, TRequires = {}, R = unknown>(\n layout: Layout,\n fn: (\n ctx: StandaloneMiddlewareContext<\n unknown,\n unknown,\n unknown,\n TAppContext,\n ResolveLayoutMiddlewaresState<Layout> & 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 = {},\n R = unknown,\n >(\n layouts: Layouts,\n fn: (\n ctx: StandaloneMiddlewareContext<\n unknown,\n unknown,\n unknown,\n TAppContext,\n ResolveLayoutsState<Layouts> & 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 = {}, 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":";;AAiLA,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 * 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"}
@@ -4,7 +4,7 @@ export type { AppContext, EmptyAppContext, HttpMethod, InferInput, InferOutput,
4
4
  export type { ContextDefinition, CreateTaserAppOptions, InferAppContext, InferAppManifest, OnErrorOptions, RouteManifestShape, } from './types/app.js';
5
5
  export { ValidationError, validationErrorSchema } from '@taserjs/router-utils';
6
6
  export type { ResponseValidationFailureHandler, SuccessStatusCode } from '@taserjs/router-utils';
7
- export { all, any, del, get, head, layout, middleware, options, patch, post, put, t, type TaserNamespace, } from './builder/standalone.js';
7
+ export { all, any, del, get, head, layout, middleware, options, patch, post, put, query, t, type TaserNamespace, } from './builder/standalone.js';
8
8
  export { createTaserApp, TaserRouter } from './builder/router.js';
9
9
  export { TaserApp } from './builder/app.js';
10
10
  export { createContext } from './context/create-context.js';
package/dist/esm/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { all, any, del, get, head, layout, middleware, options, patch, post, put, t } from "./builder/standalone.js";
1
+ import { all, any, del, get, head, layout, middleware, options, patch, post, put, query, t } from "./builder/standalone.js";
2
2
  import { TaserApp } from "./builder/app.js";
3
3
  import { TaserRouter, createTaserApp } from "./builder/router.js";
4
4
  import { createContext } from "./context/create-context.js";
5
5
  import { honoMw } from "./middleware/hono-mw.js";
6
6
  import { ValidationError, validationErrorSchema } from "@taserjs/router-utils";
7
- export { TaserApp, TaserRouter, ValidationError, all, any, createContext, createTaserApp, del, get, head, honoMw, layout, middleware, options, patch, post, put, t, validationErrorSchema };
7
+ export { TaserApp, TaserRouter, ValidationError, all, any, createContext, createTaserApp, del, get, head, honoMw, layout, middleware, options, patch, post, put, query, t, validationErrorSchema };
@@ -3,12 +3,12 @@ import { RouterRegister } 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';
6
- import { EmptyAppContext, ExtractState, Method, MiddlewareDefinition, MiddlewareReturnFromParts, MiddlewareUnit, NextFn, ValidatorParts } from './units.js';
6
+ import { EmptyAppContext, ExtractState, Method, MiddlewareDefinition, MiddlewareRequirements, MiddlewareReturnFromParts, MiddlewareUnit, NextFn, ValidatorParts } from './units.js';
7
7
  export type { Awaitable } from '@taserjs/router-core';
8
8
  export type { SchemaRequestShape, InferInput, InferOutput, Schema, StandardSchemaV1, } from './schema.js';
9
9
  export type { MergeMiddlewareField, MergeMiddlewareInputField, MergePart, RequestShape, Simplify, UnitRuntimeContext, UnwrapPart, } from './type-utils.js';
10
10
  export type { EmptyReturns, EnforceHandlerReply, HandlerReply, HasReturns, MergeReturns, ReplyFor, ReturnsMap, StatusCode, ValidHandlerReply, } from './returns.js';
11
- export type { EmptyAppContext, ExtractState, HttpMethod, IsUnknown, Method, MiddlewareDefinition, MiddlewareReturnFromParts, MiddlewareUnit, MiddlewareUnitBuilder, NextFn, NextResult, StandaloneMiddlewareContext, StateBrand, ValidatorParts, } from './units.js';
11
+ export type { EmptyAppContext, ExtractState, HttpMethod, IsUnknown, Method, MiddlewareDefinition, MiddlewareRequirements, MiddlewareReturnFromParts, MiddlewareUnit, MiddlewareUnitBuilder, NextFn, NextResult, StandaloneMiddlewareContext, StateBrand, ValidatorParts, } from './units.js';
12
12
  export type AppContext = RouterRegister extends {
13
13
  AppContext: infer C;
14
14
  } ? C : EmptyAppContext;
@@ -39,9 +39,12 @@ type LayoutParentsMap = RouterRegister extends {
39
39
  type LayoutParent<Layout extends LayoutId> = Layout extends keyof LayoutParentsMap ? LayoutParentsMap[Layout] extends LayoutId ? LayoutParentsMap[Layout] : null : LayoutTree[Layout] extends {
40
40
  parent: infer Parent extends LayoutId | null;
41
41
  } ? Parent : null;
42
+ type LayoutMiddlewares<Layout extends LayoutId> = LayoutTree[Layout]["middlewares"] extends {
43
+ readonly __acc?: infer Acc extends readonly unknown[];
44
+ } ? Acc : LayoutTree[Layout]["middlewares"] extends infer Acc extends readonly unknown[] ? Acc : readonly [];
42
45
  type ResolveLayoutMiddlewares<Layout extends LayoutId | null, Depth extends readonly unknown[] = []> = Depth["length"] extends 10 ? readonly [] : Layout extends LayoutId ? readonly [
43
46
  ...ResolveLayoutMiddlewares<LayoutParent<Layout>, [...Depth, unknown]>,
44
- ...LayoutTree[Layout]["middlewares"]
47
+ ...LayoutMiddlewares<Layout>
45
48
  ] : readonly [];
46
49
  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 [];
47
50
  export type ResolveLayoutMiddlewaresState<Layout extends LayoutId | null> = Layout extends LayoutId ? MergeMiddlewareField<ResolveLayoutMiddlewares<Layout>, "state"> : {};
@@ -51,7 +54,7 @@ type ResolveLayoutChainMiddlewares<Chain extends readonly LayoutId[]> = Chain ex
51
54
  infer Head extends LayoutId,
52
55
  ...infer Rest
53
56
  ] ? readonly [
54
- ...LayoutTree[Head]["middlewares"],
57
+ ...LayoutMiddlewares<Head>,
55
58
  ...ResolveLayoutChainMiddlewares<Rest extends readonly LayoutId[] ? Rest : readonly []>
56
59
  ] : readonly [];
57
60
  type RouteEntry<Path extends RoutePath, TMethod extends Method> = RouteByPathMethod[Path] extends {
@@ -118,7 +121,25 @@ type IsEmptyObject<T> = [keyof T] extends [never] ? true : false;
118
121
  export type IsLayoutAllowed<TRequiredLayouts, TChain extends readonly LayoutId[]> = [
119
122
  TRequiredLayouts
120
123
  ] extends [never] ? true : [unknown] extends [TRequiredLayouts] ? true : [null] extends [TRequiredLayouts] ? true : [undefined] extends [TRequiredLayouts] ? true : TRequiredLayouts extends LayoutId ? TRequiredLayouts extends TChain[number] ? true : false : TRequiredLayouts extends readonly LayoutId[] ? [TRequiredLayouts[number] & TChain[number]] extends [never] ? false : true : true;
121
- export type IsStateSatisfied<TActualState, TRequiredState> = [TRequiredState] extends [never] ? true : [unknown] extends [TRequiredState] ? true : [null] extends [TRequiredState] ? true : [undefined] extends [TRequiredState] ? true : [IsEmptyObject<TRequiredState>] extends [true] ? true : [TActualState] extends [TRequiredState] ? true : false;
124
+ export type IsRequirementsSatisfied<TActual extends {
125
+ query?: unknown;
126
+ params?: unknown;
127
+ body?: unknown;
128
+ state?: unknown;
129
+ }, TRequires extends MiddlewareRequirements> = [TRequires] extends [never] ? true : [unknown] extends [TRequires] ? true : [null] extends [TRequires] ? true : [undefined] extends [TRequires] ? true : [IsEmptyObject<TRequires>] extends [true] ? true : (TRequires extends {
130
+ state: infer S extends Record<string, unknown>;
131
+ } ? [TActual["state"]] extends [S] ? true : false : true) extends false ? false : (TRequires extends {
132
+ query: infer Q extends Record<string, unknown>;
133
+ } ? [TActual["query"]] extends [Q] ? true : false : true) extends false ? false : (TRequires extends {
134
+ params: infer P extends Record<string, unknown>;
135
+ } ? [TActual["params"]] extends [P] ? true : false : true) extends false ? false : (TRequires extends {
136
+ body: infer B;
137
+ } ? unknown extends B ? true : [TRequires["body"]] extends [undefined] ? true : [TActual["body"]] extends [B] ? true : false : true) extends false ? false : true;
138
+ export type IsStateSatisfied<TActualState, TRequiredState> = IsRequirementsSatisfied<{
139
+ state: TActualState;
140
+ }, {
141
+ state: TRequiredState extends Record<string, unknown> ? TRequiredState : {};
142
+ }>;
122
143
  type InputFacet<T, K extends string> = IsNever<T> extends true ? {} : IsEmptyObject<T> extends true ? {} : {
123
144
  [Key in K]: T;
124
145
  };
@@ -156,31 +177,41 @@ export type MiddlewareChainContext<Layout extends LayoutId, Acc extends readonly
156
177
  headers: TaserHeaders;
157
178
  cookies: TaserCookieJar;
158
179
  }>;
159
- export type MiddlewareBuilder<Layout extends LayoutId, Acc extends readonly unknown[] = readonly [], TAppContext extends Record<string, unknown> = AppContext> = Acc & {
180
+ export type MiddlewareBuilder<Layout extends LayoutId, Acc extends readonly unknown[] = readonly [], TAppContext extends Record<string, unknown> = AppContext> = {
160
181
  readonly layout: Layout;
161
182
  readonly middlewares: readonly MiddlewareDefinition[];
183
+ readonly __acc?: Acc;
162
184
  readonly $Infer: {
163
185
  Context: MiddlewareChainContext<Layout, Acc, unknown, unknown, unknown, TAppContext>;
164
186
  };
165
- use<TAcc, TReturns extends ReturnsMap = {}, TRequiredLayouts = unknown, TRequiredState = unknown>(unit: MiddlewareUnit<TAcc, TReturns, TRequiredLayouts, TRequiredState>, ..._assert: [
187
+ use<TAcc, TReturns extends ReturnsMap = {}, TRequiredLayouts = unknown, TRequires extends MiddlewareRequirements = {}>(unit: [
166
188
  IsLayoutAllowed<TRequiredLayouts, ResolveLayoutIdChain<Layout>>,
167
- IsStateSatisfied<MiddlewareChainField<Layout, Acc, "state">, TRequiredState>
168
- ] extends [true, true] ? [] : [
169
- {
170
- error: "Middleware cannot be attached to this layout";
171
- requiredLayouts: TRequiredLayouts;
172
- layoutChain: ResolveLayoutIdChain<Layout>;
173
- requiredState: TRequiredState;
174
- actualState: MiddlewareChainField<Layout, Acc, "state">;
175
- }
176
- ]): MiddlewareBuilder<Layout, readonly [...Acc, TAcc], TAppContext>;
189
+ IsRequirementsSatisfied<{
190
+ query: MiddlewareChainField<Layout, Acc, "query">;
191
+ params: MiddlewareChainField<Layout, Acc, "params">;
192
+ body: MiddlewareChainField<Layout, Acc, "body">;
193
+ state: MiddlewareChainField<Layout, Acc, "state">;
194
+ }, 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>;
177
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>;
178
208
  };
179
- export type RouteExport<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], TReturns extends ReturnsMap = {}, TOutput = Response> = Acc & {
209
+ export type RouteExport<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], TReturns extends ReturnsMap = {}, TOutput = Response> = {
180
210
  readonly path: Path;
181
211
  readonly method: TMethod | "ANY" | "ALL";
182
212
  readonly methods?: readonly Method[];
183
213
  readonly middlewares: readonly MiddlewareDefinition[];
214
+ readonly __acc?: Acc;
184
215
  readonly returns?: TReturns;
185
216
  readonly bodyMode?: "json" | "form" | "urlencoded";
186
217
  handler: (ctx: unknown) => Awaitable<Response>;
@@ -200,7 +231,7 @@ type RouteHandleResult<Path extends RoutePath, TMethod extends Method, Acc exten
200
231
  Output: TOutput;
201
232
  };
202
233
  };
203
- export type RouteBuilderBase<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[] = readonly [], Validators extends ValidatorParts = {}, TReturns extends ReturnsMap = {}, TAppContext extends Record<string, unknown> = AppContext> = {
234
+ export type RouteContractBuilderBase<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[] = readonly [], Validators extends ValidatorParts = {}, TReturns extends ReturnsMap = {}, TAppContext extends Record<string, unknown> = AppContext> = {
204
235
  readonly path: Path;
205
236
  readonly method: TMethod;
206
237
  readonly $Infer: {
@@ -208,28 +239,15 @@ export type RouteBuilderBase<Path extends RoutePath, TMethod extends Method, Acc
208
239
  Input: TMethod extends "GET" | "DELETE" | "HEAD" | "OPTIONS" ? RouteHandleInputWithoutBody<Path, TMethod, Acc, Validators> : RouteHandleInput<Path, TMethod, Acc, Validators>;
209
240
  Output: TReturns;
210
241
  };
211
- query<TQuery, TQueryIn = unknown>(schema: Schema<TQuery, TQueryIn>): RouteBuilder<Path, TMethod, Acc, Omit<Validators, "query" | "queryIn"> & {
242
+ query<TQuery, TQueryIn = unknown>(schema: Schema<TQuery, TQueryIn>): RouteContractBuilder<Path, TMethod, Acc, Omit<Validators, "query" | "queryIn"> & {
212
243
  query: TQuery;
213
244
  queryIn: TQueryIn;
214
245
  }, TReturns, TAppContext>;
215
- params<TParams, TParamsIn = unknown>(schema: Schema<TParams, TParamsIn>): RouteBuilder<Path, TMethod, Acc, Omit<Validators, "params" | "paramsIn"> & {
246
+ params<TParams, TParamsIn = unknown>(schema: Schema<TParams, TParamsIn>): RouteContractBuilder<Path, TMethod, Acc, Omit<Validators, "params" | "paramsIn"> & {
216
247
  params: TParams;
217
248
  paramsIn: TParamsIn;
218
249
  }, TReturns, TAppContext>;
219
- returns<const M extends ReturnsMap>(map: M): RouteBuilder<Path, TMethod, Acc, Validators, Omit<TReturns, keyof M> & M, TAppContext>;
220
- use<TAcc, UReturns extends ReturnsMap = {}, TRequiredLayouts = unknown, TRequiredState = unknown>(unit: MiddlewareUnit<TAcc, UReturns, TRequiredLayouts, TRequiredState>, ..._assert: [
221
- IsLayoutAllowed<TRequiredLayouts, RouteLayoutChain<Path, TMethod>>,
222
- IsStateSatisfied<RouteResolvedField<Path, TMethod, Acc, "state">, TRequiredState>
223
- ] extends [true, true] ? [] : [
224
- {
225
- error: "Middleware cannot be attached to this route";
226
- requiredLayouts: TRequiredLayouts;
227
- routeLayoutChain: RouteLayoutChain<Path, TMethod>;
228
- requiredState: TRequiredState;
229
- actualState: RouteResolvedField<Path, TMethod, Acc, "state">;
230
- }
231
- ]): RouteBuilder<Path, TMethod, readonly [...Acc, TAcc], Validators, Omit<TReturns, keyof UReturns> & UReturns, TAppContext>;
232
- use<R = unknown>(fn: (ctx: RouteChainContext<Path, TMethod, Acc, unknown, unknown, unknown, TAppContext>, next: NextFn) => Awaitable<R>): RouteBuilder<Path, TMethod, readonly [...Acc, MiddlewareReturnFromParts<unknown, unknown, unknown, ExtractState<R>>], Validators, TReturns, TAppContext>;
250
+ returns<const M extends ReturnsMap>(map: M): RouteContractBuilder<Path, TMethod, Acc, Validators, Omit<TReturns, keyof M> & M, TAppContext>;
233
251
  handler<R extends Response = Response>(fn: (ctx: TMethod extends "GET" | "DELETE" | "HEAD" | "OPTIONS" ? RouteHandleContextWithoutBody<Path, TMethod, Acc, Validators, TAppContext> : RouteHandleContext<Path, TMethod, Acc, Validators, TAppContext>) => Awaitable<R>, ..._assert: [R] extends [ValidHandlerReply<R, TReturns>] ? [] : [
234
252
  {
235
253
  expected: ValidHandlerReply<R, TReturns>;
@@ -237,16 +255,40 @@ export type RouteBuilderBase<Path extends RoutePath, TMethod extends Method, Acc
237
255
  }
238
256
  ]): RouteHandleResult<Path, TMethod, Acc, Validators, TReturns, R, TAppContext>;
239
257
  };
240
- export type RouteBuilder<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[] = readonly [], Validators extends ValidatorParts = {}, TReturns extends ReturnsMap = {}, TAppContext extends Record<string, unknown> = AppContext> = RouteBuilderBase<Path, TMethod, Acc, Validators, TReturns, TAppContext> & (TMethod extends "GET" | "DELETE" | "HEAD" | "OPTIONS" ? {} : {
241
- body<TBody, TBodyIn = unknown>(schema: Schema<TBody, TBodyIn>): RouteBuilder<Path, TMethod, Acc, Omit<Validators, "body" | "bodyIn"> & {
258
+ export type RouteContractBuilder<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[] = readonly [], Validators extends ValidatorParts = {}, TReturns extends ReturnsMap = {}, TAppContext extends Record<string, unknown> = AppContext> = RouteContractBuilderBase<Path, TMethod, Acc, Validators, TReturns, TAppContext> & (TMethod extends "GET" | "DELETE" | "HEAD" | "OPTIONS" ? {} : {
259
+ body<TBody, TBodyIn = unknown>(schema: Schema<TBody, TBodyIn>): RouteContractBuilder<Path, TMethod, Acc, Omit<Validators, "body" | "bodyIn"> & {
242
260
  body: TBody;
243
261
  bodyIn: TBodyIn;
244
262
  }, TReturns, TAppContext>;
245
- body<Mode extends "json" | "form" | "urlencoded", TBody, TBodyIn = unknown>(mode: Mode, schema: Schema<TBody, TBodyIn>): RouteBuilder<Path, TMethod, Acc, Omit<Validators, "body" | "bodyIn"> & {
263
+ body<Mode extends "json" | "form" | "urlencoded", TBody, TBodyIn = unknown>(mode: Mode, schema: Schema<TBody, TBodyIn>): RouteContractBuilder<Path, TMethod, Acc, Omit<Validators, "body" | "bodyIn"> & {
246
264
  body: TBody;
247
265
  bodyIn: TBodyIn;
248
266
  }, TReturns, TAppContext>;
249
267
  });
268
+ export type RouteMiddlewareBuilder<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[] = readonly [], Validators extends ValidatorParts = {}, TReturns extends ReturnsMap = {}, TAppContext extends Record<string, unknown> = AppContext> = RouteContractBuilder<Path, TMethod, Acc, Validators, TReturns, TAppContext> & {
269
+ use<TAcc, UReturns extends ReturnsMap = {}, TRequiredLayouts = unknown, TRequires extends MiddlewareRequirements = {}>(unit: [
270
+ IsLayoutAllowed<TRequiredLayouts, RouteLayoutChain<Path, TMethod>>,
271
+ IsRequirementsSatisfied<{
272
+ query: RouteResolvedField<Path, TMethod, Acc, "query">;
273
+ params: ResolveParams<PathParams<Path>, RouteResolvedField<Path, TMethod, Acc, "params">>;
274
+ body: RouteResolvedField<Path, TMethod, Acc, "body">;
275
+ state: RouteResolvedField<Path, TMethod, Acc, "state">;
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>;
289
+ 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
+ };
291
+ 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>;
250
292
  export type RouteDefinition<Path extends RoutePath = RoutePath, TMethod extends Method = Method, Acc extends readonly unknown[] = readonly unknown[], Validators extends ValidatorParts = ValidatorParts, TReturns extends ReturnsMap = ReturnsMap, TOutput = Response, TAppContext extends Record<string, unknown> = AppContext> = RouteHandleResult<Path, TMethod, Acc, Validators, TReturns, TOutput, TAppContext>;
251
293
  export type InferRouteContext<R> = R extends {
252
294
  $Infer: {
@@ -37,29 +37,35 @@ export type MiddlewareReturnFromParts<TQuery, TParams, TBody, TState, TQueryIn =
37
37
  body: RequestShape<TBodyIn, TBody>;
38
38
  };
39
39
  };
40
- export type DefineMiddlewareResult<TQuery, TParams, TBody, TState, R, TQueryIn = TQuery, TParamsIn = TParams, TBodyIn = TBody, TReturns extends ReturnsMap = {}, TLayout = null, TRequires = {}> = MiddlewareUnit<MiddlewareReturnFromParts<TQuery, TParams, TBody, IsUnknown<TState> extends true ? ExtractState<R> : TState, TQueryIn, TParamsIn, TBodyIn>, TReturns, TLayout, TRequires>;
41
- export type StandaloneMiddlewareContext<TQuery = unknown, TParams = unknown, TBody = unknown, TAppContext extends Record<string, unknown> = EmptyAppContext, TState = {}> = Simplify<TAppContext & UnitRuntimeContext & {
42
- query: Simplify<UnwrapPart<TQuery>>;
43
- params: Simplify<UnwrapPart<TParams>>;
44
- body: Simplify<UnwrapPart<TBody>>;
45
- state: Simplify<UnwrapPart<TState>>;
40
+ export type MiddlewareRequirements = {
41
+ query?: Record<string, unknown>;
42
+ params?: Record<string, unknown>;
43
+ body?: unknown;
44
+ state?: Record<string, unknown>;
45
+ };
46
+ export type DefineMiddlewareResult<TQuery, TParams, TBody, TState, R, TQueryIn = TQuery, TParamsIn = TParams, TBodyIn = TBody, TReturns extends ReturnsMap = {}, TLayout = null, TRequires extends MiddlewareRequirements = {}> = MiddlewareUnit<MiddlewareReturnFromParts<TQuery, TParams, TBody, IsUnknown<TState> extends true ? ExtractState<R> : TState, TQueryIn, TParamsIn, TBodyIn>, TReturns, TLayout, TRequires>;
47
+ export type StandaloneMiddlewareContext<TQuery = unknown, TParams = unknown, TBody = unknown, TAppContext extends Record<string, unknown> = EmptyAppContext, TState = {}, TRequires extends MiddlewareRequirements = {}> = Simplify<TAppContext & UnitRuntimeContext & {
48
+ query: Simplify<UnwrapPart<TQuery> & (TRequires["query"] extends Record<string, unknown> ? TRequires["query"] : {})>;
49
+ params: Simplify<UnwrapPart<TParams> & (TRequires["params"] extends Record<string, unknown> ? TRequires["params"] : {})>;
50
+ body: Simplify<UnwrapPart<TBody> & (unknown extends TRequires["body"] ? {} : [TRequires["body"]] extends [undefined] ? {} : TRequires["body"])>;
51
+ state: Simplify<UnwrapPart<TState> & (TRequires["state"] extends Record<string, unknown> ? TRequires["state"] : {})>;
46
52
  headers: TaserHeaders;
47
53
  cookies: TaserCookieJar;
48
54
  }>;
49
55
  export declare const MiddlewareUnitBrand: unique symbol;
50
- export type MiddlewareUnit<TAcc = unknown, TReturns extends ReturnsMap = {}, TRequiredLayouts = unknown, TRequiredState = unknown> = MiddlewareDefinition & {
56
+ export type MiddlewareUnit<TAcc = unknown, TReturns extends ReturnsMap = {}, TRequiredLayouts = unknown, TRequires extends MiddlewareRequirements = {}> = MiddlewareDefinition & {
51
57
  readonly [MiddlewareUnitBrand]: true;
52
58
  readonly __middlewareAcc: TAcc;
53
59
  readonly __returns?: TReturns;
54
60
  readonly __requiredLayouts?: TRequiredLayouts;
55
- readonly __requiredState?: TRequiredState;
61
+ readonly __requirements?: TRequires;
56
62
  };
57
- export type MiddlewareUnitBuilder<TQuery = unknown, TParams = unknown, TBody = unknown, TReturns extends ReturnsMap = {}, TRequiredLayouts = unknown, TRequiredState = {}, TAppContext extends Record<string, unknown> = EmptyAppContext, TInheritedState = {}, TQueryIn = unknown, TParamsIn = unknown, TBodyIn = unknown, TExpectedState = unknown> = MiddlewareUnit<MiddlewareReturnFromParts<TQuery, TParams, TBody, IsUnknown<TExpectedState> extends true ? {} : TExpectedState, TQueryIn, TParamsIn, TBodyIn>, TReturns, TRequiredLayouts, TRequiredState> & {
58
- query<Q, QIn = unknown>(schema: Schema<Q, QIn>): MiddlewareUnitBuilder<Q, TParams, TBody, TReturns, TRequiredLayouts, TRequiredState, TAppContext, TInheritedState, QIn, TParamsIn, TBodyIn, TExpectedState>;
59
- params<P, PIn = unknown>(schema: Schema<P, PIn>): MiddlewareUnitBuilder<TQuery, P, TBody, TReturns, TRequiredLayouts, TRequiredState, TAppContext, TInheritedState, TQueryIn, PIn, TBodyIn, TExpectedState>;
60
- body<B, BIn = unknown>(schema: Schema<B, BIn>): MiddlewareUnitBuilder<TQuery, TParams, B, TReturns, TRequiredLayouts, TRequiredState, TAppContext, TInheritedState, TQueryIn, TParamsIn, BIn, TExpectedState>;
61
- body<Mode extends "json" | "form" | "urlencoded", B, BIn = unknown>(mode: Mode, schema: Schema<B, BIn>): MiddlewareUnitBuilder<TQuery, TParams, B, TReturns, TRequiredLayouts, TRequiredState, TAppContext, TInheritedState, TQueryIn, TParamsIn, BIn, TExpectedState>;
62
- returns<const M extends ReturnsMap>(map: M): MiddlewareUnitBuilder<TQuery, TParams, TBody, Omit<TReturns, keyof M> & M, TRequiredLayouts, TRequiredState, TAppContext, TInheritedState, TQueryIn, TParamsIn, TBodyIn, TExpectedState>;
63
- requires<Requires extends Record<string, unknown>>(): MiddlewareUnitBuilder<TQuery, TParams, TBody, TReturns, TRequiredLayouts, TRequiredState & Requires, TAppContext, TInheritedState, TQueryIn, TParamsIn, TBodyIn, TExpectedState>;
64
- handler<R>(fn: (ctx: StandaloneMiddlewareContext<TQuery, TParams, TBody, TAppContext, TInheritedState & TRequiredState>, next: NextFn<TExpectedState>) => R): DefineMiddlewareResult<TQuery, TParams, TBody, IsUnknown<TExpectedState> extends true ? ExtractState<R> : TExpectedState, R, TQueryIn, TParamsIn, TBodyIn, TReturns, TRequiredLayouts, TRequiredState>;
63
+ export type MiddlewareUnitBuilder<TQuery = unknown, TParams = unknown, TBody = unknown, TReturns extends ReturnsMap = {}, TRequiredLayouts = unknown, TRequires extends MiddlewareRequirements = {}, TAppContext extends Record<string, unknown> = EmptyAppContext, TInheritedState = {}, TQueryIn = unknown, TParamsIn = unknown, TBodyIn = unknown, TExpectedState = unknown> = MiddlewareUnit<MiddlewareReturnFromParts<TQuery, TParams, TBody, IsUnknown<TExpectedState> extends true ? {} : TExpectedState, TQueryIn, TParamsIn, TBodyIn>, TReturns, TRequiredLayouts, TRequires> & {
64
+ query<Q, QIn = unknown>(schema: Schema<Q, QIn>): MiddlewareUnitBuilder<Q, TParams, TBody, TReturns, TRequiredLayouts, TRequires, TAppContext, TInheritedState, QIn, TParamsIn, TBodyIn, TExpectedState>;
65
+ params<P, PIn = unknown>(schema: Schema<P, PIn>): MiddlewareUnitBuilder<TQuery, P, TBody, TReturns, TRequiredLayouts, TRequires, TAppContext, TInheritedState, TQueryIn, PIn, TBodyIn, TExpectedState>;
66
+ body<B, BIn = unknown>(schema: Schema<B, BIn>): MiddlewareUnitBuilder<TQuery, TParams, B, TReturns, TRequiredLayouts, TRequires, TAppContext, TInheritedState, TQueryIn, TParamsIn, BIn, TExpectedState>;
67
+ body<Mode extends "json" | "form" | "urlencoded", B, BIn = unknown>(mode: Mode, schema: Schema<B, BIn>): MiddlewareUnitBuilder<TQuery, TParams, B, TReturns, TRequiredLayouts, TRequires, TAppContext, TInheritedState, TQueryIn, TParamsIn, BIn, TExpectedState>;
68
+ returns<const M extends ReturnsMap>(map: M): MiddlewareUnitBuilder<TQuery, TParams, TBody, Omit<TReturns, keyof M> & M, TRequiredLayouts, TRequires, TAppContext, TInheritedState, TQueryIn, TParamsIn, TBodyIn, TExpectedState>;
69
+ requires<Requires extends MiddlewareRequirements>(): MiddlewareUnitBuilder<TQuery, TParams, TBody, TReturns, TRequiredLayouts, TRequires & Requires, TAppContext, TInheritedState, TQueryIn, TParamsIn, TBodyIn, TExpectedState>;
70
+ handler<R>(fn: (ctx: StandaloneMiddlewareContext<TQuery, TParams, TBody, TAppContext, TInheritedState, TRequires>, next: NextFn<TExpectedState>) => R): DefineMiddlewareResult<TQuery, TParams, TBody, IsUnknown<TExpectedState> extends true ? ExtractState<R> : TExpectedState, R, TQueryIn, TParamsIn, TBodyIn, TReturns, TRequiredLayouts, TRequires>;
65
71
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taserjs/router",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
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-utils": "0.1.5",
151
- "@taserjs/router-core": "0.1.5"
150
+ "@taserjs/router-core": "0.1.7",
151
+ "@taserjs/router-utils": "0.1.7"
152
152
  },
153
153
  "devDependencies": {
154
154
  "@tanstack/vite-config": "^0.6.0",
@@ -10,7 +10,7 @@ export type CreateWithoutBodyRoute<
10
10
  ) => RouteBuilder<Path, M, readonly [], {}, {}, TAppContext>;
11
11
 
12
12
  export type CreateWithBodyRoute<
13
- M extends "POST" | "PUT" | "PATCH",
13
+ M extends "POST" | "PUT" | "PATCH" | "QUERY",
14
14
  TAppContext extends Record<string, unknown> = AppContext,
15
15
  > = <const Path extends RoutePath>(
16
16
  path: Path,
@@ -37,7 +37,7 @@ function createWithoutBodyRoute<M extends "GET" | "DELETE" | "OPTIONS" | "HEAD">
37
37
  createRouteBuilder(path, method)) as unknown as CreateWithoutBodyRoute<M>;
38
38
  }
39
39
 
40
- function createWithBodyRoute<M extends "POST" | "PUT" | "PATCH">(
40
+ function createWithBodyRoute<M extends "POST" | "PUT" | "PATCH" | "QUERY">(
41
41
  method: M,
42
42
  ): CreateWithBodyRoute<M> {
43
43
  return ((path: string) => createRouteBuilder(path, method)) as unknown as CreateWithBodyRoute<M>;
@@ -50,6 +50,7 @@ export const createHeadRoute = createWithoutBodyRoute("HEAD");
50
50
  export const createPostRoute = createWithBodyRoute("POST");
51
51
  export const createPutRoute = createWithBodyRoute("PUT");
52
52
  export const createPatchRoute = createWithBodyRoute("PATCH");
53
+ export const createQueryRoute = createWithBodyRoute("QUERY");
53
54
 
54
55
  export const createAnyRoute: CreateAnyRoute = ((path: string, methods: readonly HttpMethod[]) =>
55
56
  createRouteBuilder(path, "ANY", methods)) as unknown as CreateAnyRoute;
@@ -9,6 +9,7 @@ import {
9
9
  createPatchRoute,
10
10
  createPostRoute,
11
11
  createPutRoute,
12
+ createQueryRoute,
12
13
  type CreateAllRoute,
13
14
  type CreateAnyRoute,
14
15
  type CreateWithBodyRoute,
@@ -35,6 +36,8 @@ export const options: CreateWithoutBodyRoute<"OPTIONS", AppContext> =
35
36
  createOptionsRoute as CreateWithoutBodyRoute<"OPTIONS", AppContext>;
36
37
  export const head: CreateWithoutBodyRoute<"HEAD", AppContext> =
37
38
  createHeadRoute as CreateWithoutBodyRoute<"HEAD", AppContext>;
39
+ export const query: CreateWithBodyRoute<"QUERY", AppContext> =
40
+ createQueryRoute as CreateWithBodyRoute<"QUERY", AppContext>;
38
41
  export const any: CreateAnyRoute<AppContext> = createAnyRoute as CreateAnyRoute<AppContext>;
39
42
  export const all: CreateAllRoute<AppContext> = createAllRoute as CreateAllRoute<AppContext>;
40
43
 
@@ -49,6 +52,7 @@ export type TaserNamespace<TAppContext extends Record<string, unknown> = AppCont
49
52
  readonly delete: CreateWithoutBodyRoute<"DELETE", TAppContext>;
50
53
  readonly options: CreateWithoutBodyRoute<"OPTIONS", TAppContext>;
51
54
  readonly head: CreateWithoutBodyRoute<"HEAD", TAppContext>;
55
+ readonly query: CreateWithBodyRoute<"QUERY", TAppContext>;
52
56
  readonly any: CreateAnyRoute<TAppContext>;
53
57
  readonly all: CreateAllRoute<TAppContext>;
54
58
  readonly layout: LayoutBuilder<TAppContext>;
@@ -63,6 +67,7 @@ export const t: TaserNamespace<AppContext> = {
63
67
  delete: del,
64
68
  options,
65
69
  head,
70
+ query,
66
71
  any,
67
72
  all,
68
73
  layout,
@@ -3,6 +3,7 @@ import type {
3
3
  DefineMiddlewareResult,
4
4
  ExtractState,
5
5
  IsUnknown,
6
+ MiddlewareRequirements,
6
7
  MiddlewareUnitBuilder,
7
8
  NextFn,
8
9
  StandaloneMiddlewareContext,
@@ -85,7 +86,12 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
85
86
  /**
86
87
  * Defines a standalone middleware scoped to a single layout branch using a short function signature.
87
88
  */
88
- <const Layout extends LayoutId, TState = unknown, TRequires = {}, R = unknown>(
89
+ <
90
+ const Layout extends LayoutId,
91
+ TState = unknown,
92
+ TRequires extends MiddlewareRequirements = {},
93
+ R = unknown,
94
+ >(
89
95
  layout: Layout,
90
96
  fn: (
91
97
  ctx: StandaloneMiddlewareContext<
@@ -93,7 +99,8 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
93
99
  unknown,
94
100
  unknown,
95
101
  TAppContext,
96
- ResolveLayoutMiddlewaresState<Layout> & TRequires
102
+ ResolveLayoutMiddlewaresState<Layout>,
103
+ TRequires
97
104
  >,
98
105
  next: NextFn<NoInfer<TState>>,
99
106
  ) => R,
@@ -117,7 +124,7 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
117
124
  <
118
125
  const Layouts extends readonly [LayoutId, ...LayoutId[]],
119
126
  TState = unknown,
120
- TRequires = {},
127
+ TRequires extends MiddlewareRequirements = {},
121
128
  R = unknown,
122
129
  >(
123
130
  layouts: Layouts,
@@ -127,7 +134,8 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
127
134
  unknown,
128
135
  unknown,
129
136
  TAppContext,
130
- ResolveLayoutsState<Layouts> & TRequires
137
+ ResolveLayoutsState<Layouts>,
138
+ TRequires
131
139
  >,
132
140
  next: NextFn<NoInfer<TState>>,
133
141
  ) => R,
@@ -155,9 +163,9 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
155
163
  * });
156
164
  * ```
157
165
  */
158
- <TState = unknown, TRequires = {}, R = unknown>(
166
+ <TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(
159
167
  fn: (
160
- ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, TRequires>,
168
+ ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, {}, TRequires>,
161
169
  next: NextFn<NoInfer<TState>>,
162
170
  ) => R,
163
171
  ): DefineMiddlewareResult<
package/src/index.ts CHANGED
@@ -51,6 +51,7 @@ export {
51
51
  patch,
52
52
  post,
53
53
  put,
54
+ query,
54
55
  t,
55
56
  type TaserNamespace,
56
57
  } from "./builder/standalone.js";