@taserjs/router 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/define/middleware.cjs.map +1 -1
- package/dist/cjs/define/middleware.d.cts +20 -20
- package/dist/cjs/index.d.cts +5 -1
- package/dist/cjs/middleware/hono-mw.cjs.map +1 -1
- package/dist/cjs/middleware/hono-mw.d.cts +2 -1
- package/dist/cjs/types/index.d.cts +46 -56
- package/dist/cjs/types/type-utils.d.cts +3 -3
- package/dist/cjs/types/units.d.cts +4 -4
- package/dist/esm/define/middleware.d.ts +20 -20
- package/dist/esm/define/middleware.js.map +1 -1
- package/dist/esm/index.d.ts +5 -1
- package/dist/esm/middleware/hono-mw.d.ts +2 -1
- package/dist/esm/middleware/hono-mw.js.map +1 -1
- package/dist/esm/types/index.d.ts +46 -56
- package/dist/esm/types/type-utils.d.ts +3 -3
- package/dist/esm/types/units.d.ts +4 -4
- package/package.json +3 -3
- package/src/define/middleware.ts +59 -58
- package/src/index.ts +4 -0
- package/src/middleware/hono-mw.ts +8 -3
- package/src/types/index.ts +83 -91
- package/src/types/type-utils.ts +1 -1
- package/src/types/units.ts +4 -4
|
@@ -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 *
|
|
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 LayoutParams,\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 LayoutParams<Layout>,\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 LayoutParams<Layouts[number]>,\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 LayoutParams<Layout>,\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 LayoutParams<Layouts[number]>,\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":";;AA0LA,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
|
-
import { AppContext, LayoutId, ResolveLayoutMiddlewaresState, ResolveLayoutsState } from '../types/index.js';
|
|
2
|
+
import { AppContext, LayoutId, LayoutParams, 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,32 +25,21 @@ 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
|
*/
|
|
28
|
-
<const Layout extends LayoutId, TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(layout: Layout, fn: (ctx: StandaloneMiddlewareContext<unknown,
|
|
31
|
+
<const Layout extends LayoutId, TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(layout: Layout, fn: (ctx: StandaloneMiddlewareContext<unknown, LayoutParams<Layout>, 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
32
|
/**
|
|
30
33
|
* Defines a standalone middleware scoped to multiple layout branches using a short function signature.
|
|
31
34
|
*/
|
|
32
|
-
<const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(layouts: Layouts, fn: (ctx: StandaloneMiddlewareContext<unknown,
|
|
35
|
+
<const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(layouts: Layouts, fn: (ctx: StandaloneMiddlewareContext<unknown, LayoutParams<Layouts[number]>, 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
|
-
*
|
|
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
|
-
<
|
|
39
|
+
<const Layout extends LayoutId, TState = unknown>(layout: Layout): MiddlewareUnitBuilder<unknown, LayoutParams<Layout>, 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, LayoutParams<Layouts[number]>, unknown, {}, Layouts, {}, TAppContext, ResolveLayoutsState<Layouts>, unknown, unknown, unknown, TState>;
|
|
44
44
|
}
|
|
45
45
|
export declare const middleware: MiddlewareFn<AppContext>;
|
package/dist/cjs/index.d.cts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export interface RouterRegister {
|
|
2
2
|
}
|
|
3
|
-
export
|
|
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, LayoutParams, 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:
|
|
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 (\n ctx: unknown,\n next: NextFn<TState>,\n ) => Promise<Response>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,SAAgB,OACd,YAC2D;CAC3D,QAAA,GAAA,qBAAA,yBAAA,CAAgC,UAAU;AAI5C"}
|
|
@@ -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:
|
|
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
|
|
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>;
|
|
@@ -31,21 +38,19 @@ type ParseParam<Segment extends string> = Segment extends "*" ? {
|
|
|
31
38
|
[K in Name]: string;
|
|
32
39
|
} : {};
|
|
33
40
|
type ParseParamsFromSegments<S extends string> = S extends `${infer Segment}/${infer Rest}` ? ParseParam<Segment> & ParseParamsFromSegments<Rest> : ParseParam<S>;
|
|
34
|
-
export type PathParams<Path extends string> = Path extends `/${infer Rest}` ? ParseParamsFromSegments<Rest> :
|
|
41
|
+
export type PathParams<Path extends string> = Path extends `/${infer Rest}` ? ParseParamsFromSegments<Rest> : ParseParamsFromSegments<Path>;
|
|
42
|
+
export type LayoutParams<Layout extends string> = PathParams<Layout>;
|
|
35
43
|
export type ResolveParams<TPathParams, TSchemaParams> = TSchemaParams extends Record<string, unknown> ? [keyof TSchemaParams] extends [never] ? TPathParams : Simplify<Omit<TPathParams, keyof TSchemaParams> & TSchemaParams> : TPathParams;
|
|
36
|
-
type
|
|
37
|
-
|
|
38
|
-
} ?
|
|
39
|
-
type
|
|
40
|
-
parent: infer Parent extends LayoutId | null;
|
|
41
|
-
} ? Parent : null;
|
|
42
|
-
type LayoutMiddlewares<Layout extends LayoutId> = LayoutTree[Layout]["middlewares"] extends {
|
|
44
|
+
type LayoutParent<Layout extends LayoutId> = Layout extends keyof LayoutTree ? LayoutTree[Layout] extends {
|
|
45
|
+
parent: infer P extends LayoutId;
|
|
46
|
+
} ? P : null : null;
|
|
47
|
+
type LayoutMiddlewares<Layout extends LayoutId> = [Layout] extends [keyof LayoutMiddlewaresMap] ? LayoutMiddlewaresMap[Layout] extends {
|
|
43
48
|
readonly __acc?: infer Acc extends readonly unknown[];
|
|
44
|
-
} ? Acc :
|
|
45
|
-
type ResolveLayoutMiddlewares<Layout extends LayoutId | null, Depth extends readonly unknown[] = []> = Depth["length"] extends 10 ? readonly [] : Layout extends LayoutId ? readonly [
|
|
46
|
-
...ResolveLayoutMiddlewares<
|
|
49
|
+
} ? Acc : LayoutMiddlewaresMap[Layout] extends readonly unknown[] ? LayoutMiddlewaresMap[Layout] : readonly [] : readonly [];
|
|
50
|
+
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 [
|
|
51
|
+
...ResolveLayoutMiddlewares<Parent, [...Depth, unknown]>,
|
|
47
52
|
...LayoutMiddlewares<Layout>
|
|
48
|
-
] : readonly [];
|
|
53
|
+
] : readonly [...LayoutMiddlewares<Layout>] : readonly [];
|
|
49
54
|
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
55
|
export type ResolveLayoutMiddlewaresState<Layout extends LayoutId | null> = Layout extends LayoutId ? MergeMiddlewareField<ResolveLayoutMiddlewares<Layout>, "state"> : {};
|
|
51
56
|
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 +65,18 @@ type ResolveLayoutChainMiddlewares<Chain extends readonly LayoutId[]> = Chain ex
|
|
|
60
65
|
type RouteEntry<Path extends RoutePath, TMethod extends Method> = RouteByPathMethod[Path] extends {
|
|
61
66
|
[K in TMethod]: infer Entry;
|
|
62
67
|
} ? 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
68
|
type RouteLayoutChain<Path extends RoutePath, TMethod extends Method> = RouteEntry<Path, TMethod> extends {
|
|
67
|
-
|
|
68
|
-
} ? Chain :
|
|
69
|
+
layouts: infer Chain extends readonly LayoutId[];
|
|
70
|
+
} ? Chain : readonly [];
|
|
69
71
|
export type RouteLayoutMiddlewares<Path extends RoutePath, TMethod extends Method> = ResolveLayoutChainMiddlewares<RouteLayoutChain<Path, TMethod>>;
|
|
70
72
|
export type RouteLayoutField<Path extends RoutePath, TMethod extends Method, Field extends "query" | "params" | "body" | "state"> = MergeMiddlewareField<RouteLayoutMiddlewares<Path, TMethod>, Field>;
|
|
71
73
|
export type RouteLayoutInputField<Path extends RoutePath, TMethod extends Method, Field extends "query" | "params" | "body"> = MergeMiddlewareInputField<RouteLayoutMiddlewares<Path, TMethod>, Field>;
|
|
72
74
|
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
75
|
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:
|
|
75
|
-
params:
|
|
76
|
-
body:
|
|
77
|
-
state:
|
|
76
|
+
query: MergePart<TQuery, RouteResolvedField<Path, TMethod, Acc, "query">>;
|
|
77
|
+
params: ResolveParams<PathParams<Path>, MergePart<TParams, RouteResolvedField<Path, TMethod, Acc, "params">>>;
|
|
78
|
+
body: MergePart<TBody, RouteResolvedField<Path, TMethod, Acc, "body">>;
|
|
79
|
+
state: RouteResolvedField<Path, TMethod, Acc, "state">;
|
|
78
80
|
headers: TaserHeaders;
|
|
79
81
|
cookies: TaserCookieJar;
|
|
80
82
|
}>;
|
|
@@ -167,23 +169,23 @@ export type InferRouteInputFromPath<Path extends RoutePath, TMethod extends Meth
|
|
|
167
169
|
Input: infer I;
|
|
168
170
|
};
|
|
169
171
|
} ? I : never : never;
|
|
170
|
-
export type MiddlewareLayoutField<Layout extends LayoutId, Field extends "query" | "params" | "body" | "state"> = MergeMiddlewareField<ResolveLayoutMiddlewares<
|
|
172
|
+
export type MiddlewareLayoutField<Layout extends LayoutId, Field extends "query" | "params" | "body" | "state"> = [LayoutParent<Layout>] extends [infer Parent extends LayoutId] ? MergeMiddlewareField<ResolveLayoutMiddlewares<Parent>, Field> : {};
|
|
171
173
|
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 &
|
|
174
|
+
export type MiddlewareChainContext<Layout extends LayoutId, Acc extends readonly unknown[], TQuery = unknown, TParams = unknown, TBody = unknown, TAppContext extends Record<string, unknown> = AppContext> = Simplify<TAppContext & {
|
|
175
|
+
readonly request: Request;
|
|
176
|
+
readonly method: Method;
|
|
177
|
+
readonly url: URL;
|
|
178
|
+
readonly headers: TaserHeaders;
|
|
179
|
+
readonly cookies: TaserCookieJar;
|
|
173
180
|
query: Simplify<MergePart<TQuery, MiddlewareChainField<Layout, Acc, "query">>>;
|
|
174
|
-
params: Simplify<MergePart<TParams, MiddlewareChainField<Layout, Acc, "params"
|
|
181
|
+
params: Simplify<ResolveParams<LayoutParams<Layout>, Simplify<MergePart<TParams, MiddlewareChainField<Layout, Acc, "params">>>>>;
|
|
175
182
|
body: Simplify<MergePart<TBody, MiddlewareChainField<Layout, Acc, "body">>>;
|
|
176
183
|
state: Simplify<MiddlewareChainField<Layout, Acc, "state">>;
|
|
177
|
-
headers: TaserHeaders;
|
|
178
|
-
cookies: TaserCookieJar;
|
|
179
184
|
}>;
|
|
180
185
|
export type MiddlewareBuilder<Layout extends LayoutId, Acc extends readonly unknown[] = readonly [], TAppContext extends Record<string, unknown> = AppContext> = {
|
|
181
186
|
readonly layout: Layout;
|
|
182
187
|
readonly middlewares: readonly MiddlewareDefinition[];
|
|
183
188
|
readonly __acc?: Acc;
|
|
184
|
-
readonly $Infer: {
|
|
185
|
-
Context: MiddlewareChainContext<Layout, Acc, unknown, unknown, unknown, TAppContext>;
|
|
186
|
-
};
|
|
187
189
|
use<TAcc, TReturns extends ReturnsMap = {}, TRequiredLayouts = unknown, TRequires extends MiddlewareRequirements = {}>(unit: [
|
|
188
190
|
IsLayoutAllowed<TRequiredLayouts, ResolveLayoutIdChain<Layout>>,
|
|
189
191
|
IsRequirementsSatisfied<{
|
|
@@ -192,19 +194,18 @@ export type MiddlewareBuilder<Layout extends LayoutId, Acc extends readonly unkn
|
|
|
192
194
|
body: MiddlewareChainField<Layout, Acc, "body">;
|
|
193
195
|
state: MiddlewareChainField<Layout, Acc, "state">;
|
|
194
196
|
}, TRequires>
|
|
195
|
-
] extends [true, true] ? MiddlewareUnit<TAcc, TReturns, TRequiredLayouts, TRequires> :
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}): MiddlewareBuilder<Layout, readonly [...Acc,
|
|
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>;
|
|
197
|
+
] extends [true, true] ? MiddlewareUnit<TAcc, TReturns, TRequiredLayouts, TRequires> : never): MiddlewareBuilder<Layout, readonly [...Acc, TAcc], TAppContext>;
|
|
198
|
+
use<R = unknown>(fn: (ctx: Simplify<TAppContext & {
|
|
199
|
+
readonly request: Request;
|
|
200
|
+
readonly method: Method;
|
|
201
|
+
readonly url: URL;
|
|
202
|
+
readonly headers: TaserHeaders;
|
|
203
|
+
readonly cookies: TaserCookieJar;
|
|
204
|
+
query: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "query">>>;
|
|
205
|
+
params: Simplify<ResolveParams<LayoutParams<Layout>, Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "params">>>>>;
|
|
206
|
+
body: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "body">>>;
|
|
207
|
+
state: Simplify<MiddlewareChainField<Layout, Acc, "state">>;
|
|
208
|
+
}>, next: NextFn) => Awaitable<R>): MiddlewareBuilder<Layout, readonly [...Acc, MiddlewareReturnFromParts<unknown, unknown, unknown, ExtractState<R>>], TAppContext>;
|
|
208
209
|
};
|
|
209
210
|
export type RouteExport<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], TReturns extends ReturnsMap = {}, TOutput = Response> = {
|
|
210
211
|
readonly path: Path;
|
|
@@ -274,18 +275,7 @@ export type RouteMiddlewareBuilder<Path extends RoutePath, TMethod extends Metho
|
|
|
274
275
|
body: RouteResolvedField<Path, TMethod, Acc, "body">;
|
|
275
276
|
state: RouteResolvedField<Path, TMethod, Acc, "state">;
|
|
276
277
|
}, 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>;
|
|
278
|
+
] extends [true, true] ? MiddlewareUnit<TAcc, UReturns, TRequiredLayouts, TRequires> : never): RouteMiddlewareBuilder<Path, TMethod, readonly [...Acc, TAcc], Validators, Omit<TReturns, keyof UReturns> & UReturns, TAppContext>;
|
|
289
279
|
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
280
|
};
|
|
291
281
|
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
|
|
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:
|
|
30
|
-
params:
|
|
31
|
-
body:
|
|
32
|
-
state:
|
|
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
|
-
import { AppContext, LayoutId, ResolveLayoutMiddlewaresState, ResolveLayoutsState } from '../types/index.js';
|
|
2
|
+
import { AppContext, LayoutId, LayoutParams, 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,32 +25,21 @@ 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
|
*/
|
|
28
|
-
<const Layout extends LayoutId, TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(layout: Layout, fn: (ctx: StandaloneMiddlewareContext<unknown,
|
|
31
|
+
<const Layout extends LayoutId, TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(layout: Layout, fn: (ctx: StandaloneMiddlewareContext<unknown, LayoutParams<Layout>, 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
32
|
/**
|
|
30
33
|
* Defines a standalone middleware scoped to multiple layout branches using a short function signature.
|
|
31
34
|
*/
|
|
32
|
-
<const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(layouts: Layouts, fn: (ctx: StandaloneMiddlewareContext<unknown,
|
|
35
|
+
<const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(layouts: Layouts, fn: (ctx: StandaloneMiddlewareContext<unknown, LayoutParams<Layouts[number]>, 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
|
-
*
|
|
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
|
-
<
|
|
39
|
+
<const Layout extends LayoutId, TState = unknown>(layout: Layout): MiddlewareUnitBuilder<unknown, LayoutParams<Layout>, 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, LayoutParams<Layouts[number]>, 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 *
|
|
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 LayoutParams,\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 LayoutParams<Layout>,\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 LayoutParams<Layouts[number]>,\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 LayoutParams<Layout>,\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 LayoutParams<Layouts[number]>,\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":";;AA0LA,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"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export interface RouterRegister {
|
|
2
2
|
}
|
|
3
|
-
export
|
|
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, LayoutParams, 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:
|
|
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:
|
|
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 (\n ctx: unknown,\n next: NextFn<TState>,\n ) => Promise<Response>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,SAAgB,OACd,YAC2D;CAC3D,OAAO,yBAAyB,UAAU;AAI5C"}
|
|
@@ -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
|
|
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>;
|
|
@@ -31,21 +38,19 @@ type ParseParam<Segment extends string> = Segment extends "*" ? {
|
|
|
31
38
|
[K in Name]: string;
|
|
32
39
|
} : {};
|
|
33
40
|
type ParseParamsFromSegments<S extends string> = S extends `${infer Segment}/${infer Rest}` ? ParseParam<Segment> & ParseParamsFromSegments<Rest> : ParseParam<S>;
|
|
34
|
-
export type PathParams<Path extends string> = Path extends `/${infer Rest}` ? ParseParamsFromSegments<Rest> :
|
|
41
|
+
export type PathParams<Path extends string> = Path extends `/${infer Rest}` ? ParseParamsFromSegments<Rest> : ParseParamsFromSegments<Path>;
|
|
42
|
+
export type LayoutParams<Layout extends string> = PathParams<Layout>;
|
|
35
43
|
export type ResolveParams<TPathParams, TSchemaParams> = TSchemaParams extends Record<string, unknown> ? [keyof TSchemaParams] extends [never] ? TPathParams : Simplify<Omit<TPathParams, keyof TSchemaParams> & TSchemaParams> : TPathParams;
|
|
36
|
-
type
|
|
37
|
-
|
|
38
|
-
} ?
|
|
39
|
-
type
|
|
40
|
-
parent: infer Parent extends LayoutId | null;
|
|
41
|
-
} ? Parent : null;
|
|
42
|
-
type LayoutMiddlewares<Layout extends LayoutId> = LayoutTree[Layout]["middlewares"] extends {
|
|
44
|
+
type LayoutParent<Layout extends LayoutId> = Layout extends keyof LayoutTree ? LayoutTree[Layout] extends {
|
|
45
|
+
parent: infer P extends LayoutId;
|
|
46
|
+
} ? P : null : null;
|
|
47
|
+
type LayoutMiddlewares<Layout extends LayoutId> = [Layout] extends [keyof LayoutMiddlewaresMap] ? LayoutMiddlewaresMap[Layout] extends {
|
|
43
48
|
readonly __acc?: infer Acc extends readonly unknown[];
|
|
44
|
-
} ? Acc :
|
|
45
|
-
type ResolveLayoutMiddlewares<Layout extends LayoutId | null, Depth extends readonly unknown[] = []> = Depth["length"] extends 10 ? readonly [] : Layout extends LayoutId ? readonly [
|
|
46
|
-
...ResolveLayoutMiddlewares<
|
|
49
|
+
} ? Acc : LayoutMiddlewaresMap[Layout] extends readonly unknown[] ? LayoutMiddlewaresMap[Layout] : readonly [] : readonly [];
|
|
50
|
+
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 [
|
|
51
|
+
...ResolveLayoutMiddlewares<Parent, [...Depth, unknown]>,
|
|
47
52
|
...LayoutMiddlewares<Layout>
|
|
48
|
-
] : readonly [];
|
|
53
|
+
] : readonly [...LayoutMiddlewares<Layout>] : readonly [];
|
|
49
54
|
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
55
|
export type ResolveLayoutMiddlewaresState<Layout extends LayoutId | null> = Layout extends LayoutId ? MergeMiddlewareField<ResolveLayoutMiddlewares<Layout>, "state"> : {};
|
|
51
56
|
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 +65,18 @@ type ResolveLayoutChainMiddlewares<Chain extends readonly LayoutId[]> = Chain ex
|
|
|
60
65
|
type RouteEntry<Path extends RoutePath, TMethod extends Method> = RouteByPathMethod[Path] extends {
|
|
61
66
|
[K in TMethod]: infer Entry;
|
|
62
67
|
} ? 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
68
|
type RouteLayoutChain<Path extends RoutePath, TMethod extends Method> = RouteEntry<Path, TMethod> extends {
|
|
67
|
-
|
|
68
|
-
} ? Chain :
|
|
69
|
+
layouts: infer Chain extends readonly LayoutId[];
|
|
70
|
+
} ? Chain : readonly [];
|
|
69
71
|
export type RouteLayoutMiddlewares<Path extends RoutePath, TMethod extends Method> = ResolveLayoutChainMiddlewares<RouteLayoutChain<Path, TMethod>>;
|
|
70
72
|
export type RouteLayoutField<Path extends RoutePath, TMethod extends Method, Field extends "query" | "params" | "body" | "state"> = MergeMiddlewareField<RouteLayoutMiddlewares<Path, TMethod>, Field>;
|
|
71
73
|
export type RouteLayoutInputField<Path extends RoutePath, TMethod extends Method, Field extends "query" | "params" | "body"> = MergeMiddlewareInputField<RouteLayoutMiddlewares<Path, TMethod>, Field>;
|
|
72
74
|
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
75
|
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:
|
|
75
|
-
params:
|
|
76
|
-
body:
|
|
77
|
-
state:
|
|
76
|
+
query: MergePart<TQuery, RouteResolvedField<Path, TMethod, Acc, "query">>;
|
|
77
|
+
params: ResolveParams<PathParams<Path>, MergePart<TParams, RouteResolvedField<Path, TMethod, Acc, "params">>>;
|
|
78
|
+
body: MergePart<TBody, RouteResolvedField<Path, TMethod, Acc, "body">>;
|
|
79
|
+
state: RouteResolvedField<Path, TMethod, Acc, "state">;
|
|
78
80
|
headers: TaserHeaders;
|
|
79
81
|
cookies: TaserCookieJar;
|
|
80
82
|
}>;
|
|
@@ -167,23 +169,23 @@ export type InferRouteInputFromPath<Path extends RoutePath, TMethod extends Meth
|
|
|
167
169
|
Input: infer I;
|
|
168
170
|
};
|
|
169
171
|
} ? I : never : never;
|
|
170
|
-
export type MiddlewareLayoutField<Layout extends LayoutId, Field extends "query" | "params" | "body" | "state"> = MergeMiddlewareField<ResolveLayoutMiddlewares<
|
|
172
|
+
export type MiddlewareLayoutField<Layout extends LayoutId, Field extends "query" | "params" | "body" | "state"> = [LayoutParent<Layout>] extends [infer Parent extends LayoutId] ? MergeMiddlewareField<ResolveLayoutMiddlewares<Parent>, Field> : {};
|
|
171
173
|
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 &
|
|
174
|
+
export type MiddlewareChainContext<Layout extends LayoutId, Acc extends readonly unknown[], TQuery = unknown, TParams = unknown, TBody = unknown, TAppContext extends Record<string, unknown> = AppContext> = Simplify<TAppContext & {
|
|
175
|
+
readonly request: Request;
|
|
176
|
+
readonly method: Method;
|
|
177
|
+
readonly url: URL;
|
|
178
|
+
readonly headers: TaserHeaders;
|
|
179
|
+
readonly cookies: TaserCookieJar;
|
|
173
180
|
query: Simplify<MergePart<TQuery, MiddlewareChainField<Layout, Acc, "query">>>;
|
|
174
|
-
params: Simplify<MergePart<TParams, MiddlewareChainField<Layout, Acc, "params"
|
|
181
|
+
params: Simplify<ResolveParams<LayoutParams<Layout>, Simplify<MergePart<TParams, MiddlewareChainField<Layout, Acc, "params">>>>>;
|
|
175
182
|
body: Simplify<MergePart<TBody, MiddlewareChainField<Layout, Acc, "body">>>;
|
|
176
183
|
state: Simplify<MiddlewareChainField<Layout, Acc, "state">>;
|
|
177
|
-
headers: TaserHeaders;
|
|
178
|
-
cookies: TaserCookieJar;
|
|
179
184
|
}>;
|
|
180
185
|
export type MiddlewareBuilder<Layout extends LayoutId, Acc extends readonly unknown[] = readonly [], TAppContext extends Record<string, unknown> = AppContext> = {
|
|
181
186
|
readonly layout: Layout;
|
|
182
187
|
readonly middlewares: readonly MiddlewareDefinition[];
|
|
183
188
|
readonly __acc?: Acc;
|
|
184
|
-
readonly $Infer: {
|
|
185
|
-
Context: MiddlewareChainContext<Layout, Acc, unknown, unknown, unknown, TAppContext>;
|
|
186
|
-
};
|
|
187
189
|
use<TAcc, TReturns extends ReturnsMap = {}, TRequiredLayouts = unknown, TRequires extends MiddlewareRequirements = {}>(unit: [
|
|
188
190
|
IsLayoutAllowed<TRequiredLayouts, ResolveLayoutIdChain<Layout>>,
|
|
189
191
|
IsRequirementsSatisfied<{
|
|
@@ -192,19 +194,18 @@ export type MiddlewareBuilder<Layout extends LayoutId, Acc extends readonly unkn
|
|
|
192
194
|
body: MiddlewareChainField<Layout, Acc, "body">;
|
|
193
195
|
state: MiddlewareChainField<Layout, Acc, "state">;
|
|
194
196
|
}, TRequires>
|
|
195
|
-
] extends [true, true] ? MiddlewareUnit<TAcc, TReturns, TRequiredLayouts, TRequires> :
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}): MiddlewareBuilder<Layout, readonly [...Acc,
|
|
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>;
|
|
197
|
+
] extends [true, true] ? MiddlewareUnit<TAcc, TReturns, TRequiredLayouts, TRequires> : never): MiddlewareBuilder<Layout, readonly [...Acc, TAcc], TAppContext>;
|
|
198
|
+
use<R = unknown>(fn: (ctx: Simplify<TAppContext & {
|
|
199
|
+
readonly request: Request;
|
|
200
|
+
readonly method: Method;
|
|
201
|
+
readonly url: URL;
|
|
202
|
+
readonly headers: TaserHeaders;
|
|
203
|
+
readonly cookies: TaserCookieJar;
|
|
204
|
+
query: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "query">>>;
|
|
205
|
+
params: Simplify<ResolveParams<LayoutParams<Layout>, Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "params">>>>>;
|
|
206
|
+
body: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "body">>>;
|
|
207
|
+
state: Simplify<MiddlewareChainField<Layout, Acc, "state">>;
|
|
208
|
+
}>, next: NextFn) => Awaitable<R>): MiddlewareBuilder<Layout, readonly [...Acc, MiddlewareReturnFromParts<unknown, unknown, unknown, ExtractState<R>>], TAppContext>;
|
|
208
209
|
};
|
|
209
210
|
export type RouteExport<Path extends RoutePath, TMethod extends Method, Acc extends readonly unknown[], TReturns extends ReturnsMap = {}, TOutput = Response> = {
|
|
210
211
|
readonly path: Path;
|
|
@@ -274,18 +275,7 @@ export type RouteMiddlewareBuilder<Path extends RoutePath, TMethod extends Metho
|
|
|
274
275
|
body: RouteResolvedField<Path, TMethod, Acc, "body">;
|
|
275
276
|
state: RouteResolvedField<Path, TMethod, Acc, "state">;
|
|
276
277
|
}, 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>;
|
|
278
|
+
] extends [true, true] ? MiddlewareUnit<TAcc, UReturns, TRequiredLayouts, TRequires> : never): RouteMiddlewareBuilder<Path, TMethod, readonly [...Acc, TAcc], Validators, Omit<TReturns, keyof UReturns> & UReturns, TAppContext>;
|
|
289
279
|
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
280
|
};
|
|
291
281
|
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
|
|
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:
|
|
30
|
-
params:
|
|
31
|
-
body:
|
|
32
|
-
state:
|
|
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.
|
|
3
|
+
"version": "0.1.9",
|
|
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.
|
|
151
|
-
"@taserjs/router-utils": "0.1.
|
|
150
|
+
"@taserjs/router-core": "0.1.9",
|
|
151
|
+
"@taserjs/router-utils": "0.1.9"
|
|
152
152
|
},
|
|
153
153
|
"devDependencies": {
|
|
154
154
|
"@tanstack/vite-config": "^0.6.0",
|
package/src/define/middleware.ts
CHANGED
|
@@ -11,72 +11,62 @@ import type {
|
|
|
11
11
|
import type {
|
|
12
12
|
AppContext,
|
|
13
13
|
LayoutId,
|
|
14
|
+
LayoutParams,
|
|
14
15
|
ResolveLayoutMiddlewaresState,
|
|
15
16
|
ResolveLayoutsState,
|
|
16
17
|
} from "../types/index.js";
|
|
17
18
|
|
|
18
19
|
export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppContext> {
|
|
19
20
|
/**
|
|
20
|
-
*
|
|
21
|
+
* Defines a standalone, unscoped middleware using a short function signature.
|
|
21
22
|
*
|
|
22
23
|
* @example
|
|
23
24
|
* ```ts
|
|
24
|
-
* const auth = middleware
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* .returns({ 401: z.string() })
|
|
28
|
-
* .handler(async (ctx, next) => next({ user: "alice" }));
|
|
25
|
+
* const auth = middleware((ctx, next) => {
|
|
26
|
+
* return next({ user: "alice" });
|
|
27
|
+
* });
|
|
29
28
|
* ```
|
|
30
29
|
*/
|
|
31
|
-
<TState = unknown>(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
{},
|
|
38
|
-
TAppContext,
|
|
39
|
-
{},
|
|
30
|
+
<TState = unknown, TRequires extends MiddlewareRequirements = {}, R = unknown>(
|
|
31
|
+
fn: (
|
|
32
|
+
ctx: StandaloneMiddlewareContext<unknown, unknown, unknown, TAppContext, {}, TRequires>,
|
|
33
|
+
next: NextFn<NoInfer<TState>>,
|
|
34
|
+
) => R,
|
|
35
|
+
): DefineMiddlewareResult<
|
|
40
36
|
unknown,
|
|
41
37
|
unknown,
|
|
42
38
|
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<
|
|
39
|
+
IsUnknown<TState> extends true ? ExtractState<R> : TState,
|
|
40
|
+
R,
|
|
52
41
|
unknown,
|
|
53
42
|
unknown,
|
|
54
43
|
unknown,
|
|
55
44
|
{},
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
TAppContext,
|
|
59
|
-
ResolveLayoutMiddlewaresState<Layout>,
|
|
60
|
-
unknown,
|
|
61
|
-
unknown,
|
|
62
|
-
unknown,
|
|
63
|
-
TState
|
|
45
|
+
null,
|
|
46
|
+
TRequires
|
|
64
47
|
>;
|
|
65
48
|
|
|
66
49
|
/**
|
|
67
|
-
* Constructs a fluent middleware builder
|
|
50
|
+
* Constructs a fluent unscoped middleware builder, with optional explicit State generic.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* const auth = middleware<{ user: string }>()
|
|
55
|
+
* .query(z.object({ token: z.string() }))
|
|
56
|
+
* .body("form", z.object({ file: z.instanceof(File) }))
|
|
57
|
+
* .returns({ 401: z.string() })
|
|
58
|
+
* .handler(async (ctx, next) => next({ user: "alice" }));
|
|
59
|
+
* ```
|
|
68
60
|
*/
|
|
69
|
-
<
|
|
70
|
-
layouts: Layouts,
|
|
71
|
-
): MiddlewareUnitBuilder<
|
|
61
|
+
<TState = unknown>(): MiddlewareUnitBuilder<
|
|
72
62
|
unknown,
|
|
73
63
|
unknown,
|
|
74
64
|
unknown,
|
|
75
65
|
{},
|
|
76
|
-
|
|
66
|
+
null,
|
|
77
67
|
{},
|
|
78
68
|
TAppContext,
|
|
79
|
-
|
|
69
|
+
{},
|
|
80
70
|
unknown,
|
|
81
71
|
unknown,
|
|
82
72
|
unknown,
|
|
@@ -96,7 +86,7 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
|
|
|
96
86
|
fn: (
|
|
97
87
|
ctx: StandaloneMiddlewareContext<
|
|
98
88
|
unknown,
|
|
99
|
-
|
|
89
|
+
LayoutParams<Layout>,
|
|
100
90
|
unknown,
|
|
101
91
|
TAppContext,
|
|
102
92
|
ResolveLayoutMiddlewaresState<Layout>,
|
|
@@ -131,7 +121,7 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
|
|
|
131
121
|
fn: (
|
|
132
122
|
ctx: StandaloneMiddlewareContext<
|
|
133
123
|
unknown,
|
|
134
|
-
|
|
124
|
+
LayoutParams<Layouts[number]>,
|
|
135
125
|
unknown,
|
|
136
126
|
TAppContext,
|
|
137
127
|
ResolveLayoutsState<Layouts>,
|
|
@@ -154,32 +144,43 @@ export interface MiddlewareFn<TAppContext extends Record<string, unknown> = AppC
|
|
|
154
144
|
>;
|
|
155
145
|
|
|
156
146
|
/**
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* @example
|
|
160
|
-
* ```ts
|
|
161
|
-
* const auth = middleware((ctx, next) => {
|
|
162
|
-
* return next({ user: "alice" });
|
|
163
|
-
* });
|
|
164
|
-
* ```
|
|
147
|
+
* Constructs a fluent middleware builder scoped to a single layout branch, with optional explicit State generic.
|
|
165
148
|
*/
|
|
166
|
-
<
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
next: NextFn<NoInfer<TState>>,
|
|
170
|
-
) => R,
|
|
171
|
-
): DefineMiddlewareResult<
|
|
149
|
+
<const Layout extends LayoutId, TState = unknown>(
|
|
150
|
+
layout: Layout,
|
|
151
|
+
): MiddlewareUnitBuilder<
|
|
172
152
|
unknown,
|
|
153
|
+
LayoutParams<Layout>,
|
|
154
|
+
unknown,
|
|
155
|
+
{},
|
|
156
|
+
Layout,
|
|
157
|
+
{},
|
|
158
|
+
TAppContext,
|
|
159
|
+
ResolveLayoutMiddlewaresState<Layout>,
|
|
173
160
|
unknown,
|
|
174
161
|
unknown,
|
|
175
|
-
IsUnknown<TState> extends true ? ExtractState<R> : TState,
|
|
176
|
-
R,
|
|
177
162
|
unknown,
|
|
163
|
+
TState
|
|
164
|
+
>;
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Constructs a fluent middleware builder scoped to multiple layout branches (branch union), with optional explicit State generic.
|
|
168
|
+
*/
|
|
169
|
+
<const Layouts extends readonly [LayoutId, ...LayoutId[]], TState = unknown>(
|
|
170
|
+
layouts: Layouts,
|
|
171
|
+
): MiddlewareUnitBuilder<
|
|
178
172
|
unknown,
|
|
173
|
+
LayoutParams<Layouts[number]>,
|
|
179
174
|
unknown,
|
|
180
175
|
{},
|
|
181
|
-
|
|
182
|
-
|
|
176
|
+
Layouts,
|
|
177
|
+
{},
|
|
178
|
+
TAppContext,
|
|
179
|
+
ResolveLayoutsState<Layouts>,
|
|
180
|
+
unknown,
|
|
181
|
+
unknown,
|
|
182
|
+
unknown,
|
|
183
|
+
TState
|
|
183
184
|
>;
|
|
184
185
|
}
|
|
185
186
|
|
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,8 @@ export type {
|
|
|
11
13
|
InferRouteOutput,
|
|
12
14
|
LayoutBuilder,
|
|
13
15
|
LayoutId,
|
|
16
|
+
LayoutMiddlewaresMap,
|
|
17
|
+
LayoutParams,
|
|
14
18
|
LayoutTree,
|
|
15
19
|
Method,
|
|
16
20
|
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,11 @@ 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:
|
|
21
|
-
return createTaserCompatHandler(middleware) as (
|
|
22
|
+
): (ctx: unknown, next: NextFn<TState>) => Promise<Response> {
|
|
23
|
+
return createTaserCompatHandler(middleware) as (
|
|
24
|
+
ctx: unknown,
|
|
25
|
+
next: NextFn<TState>,
|
|
26
|
+
) => Promise<Response>;
|
|
22
27
|
}
|
package/src/types/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Awaitable, TaserCookieJar, TaserHeaders } from "@taserjs/router-core";
|
|
2
|
-
import type { RouterRegister } from "../index.js";
|
|
2
|
+
import type { RouterMiddlewaresRegister, RouterRegister, RouterRoutesRegister } from "../index.js";
|
|
3
3
|
import type {
|
|
4
4
|
MergeMiddlewareField,
|
|
5
5
|
MergeMiddlewareInputField,
|
|
@@ -74,9 +74,18 @@ export type AppContext = RouterRegister extends { AppContext: infer C } ? C : Em
|
|
|
74
74
|
export type RoutePath = RouterRegister extends { RoutePath: infer P } ? P : never;
|
|
75
75
|
export type LayoutId = RouterRegister extends { LayoutId: infer L } ? L : never;
|
|
76
76
|
export type LayoutTree = RouterRegister extends { LayoutTree: infer T } ? T : Record<never, never>;
|
|
77
|
-
export type
|
|
77
|
+
export type LayoutMiddlewaresMap = RouterMiddlewaresRegister extends {
|
|
78
|
+
LayoutMiddlewares: infer M;
|
|
79
|
+
}
|
|
80
|
+
? M
|
|
81
|
+
: RouterRegister extends { LayoutMiddlewares: infer M }
|
|
82
|
+
? M
|
|
83
|
+
: Record<never, never>;
|
|
84
|
+
export type RouteByPathMethod = RouterRoutesRegister extends { RouteByPathMethod: infer R }
|
|
78
85
|
? R
|
|
79
|
-
:
|
|
86
|
+
: RouterRegister extends { RouteByPathMethod: infer R }
|
|
87
|
+
? R
|
|
88
|
+
: Record<never, never>;
|
|
80
89
|
|
|
81
90
|
export type LayoutBuilder<TAppContext extends Record<string, unknown> = AppContext> = <
|
|
82
91
|
const Layout extends LayoutId,
|
|
@@ -98,7 +107,9 @@ type ParseParamsFromSegments<S extends string> = S extends `${infer Segment}/${i
|
|
|
98
107
|
|
|
99
108
|
export type PathParams<Path extends string> = Path extends `/${infer Rest}`
|
|
100
109
|
? ParseParamsFromSegments<Rest>
|
|
101
|
-
:
|
|
110
|
+
: ParseParamsFromSegments<Path>;
|
|
111
|
+
|
|
112
|
+
export type LayoutParams<Layout extends string> = PathParams<Layout>;
|
|
102
113
|
|
|
103
114
|
export type ResolveParams<TPathParams, TSchemaParams> =
|
|
104
115
|
TSchemaParams extends Record<string, unknown>
|
|
@@ -107,40 +118,32 @@ export type ResolveParams<TPathParams, TSchemaParams> =
|
|
|
107
118
|
: Simplify<Omit<TPathParams, keyof TSchemaParams> & TSchemaParams>
|
|
108
119
|
: TPathParams;
|
|
109
120
|
|
|
110
|
-
type
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
? LP
|
|
114
|
-
: {};
|
|
115
|
-
|
|
116
|
-
type LayoutParent<Layout extends LayoutId> = Layout extends keyof LayoutParentsMap
|
|
117
|
-
? LayoutParentsMap[Layout] extends LayoutId
|
|
118
|
-
? LayoutParentsMap[Layout]
|
|
121
|
+
type LayoutParent<Layout extends LayoutId> = Layout extends keyof LayoutTree
|
|
122
|
+
? LayoutTree[Layout] extends { parent: infer P extends LayoutId }
|
|
123
|
+
? P
|
|
119
124
|
: null
|
|
120
|
-
:
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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[]
|
|
125
|
+
: null;
|
|
126
|
+
|
|
127
|
+
type LayoutMiddlewares<Layout extends LayoutId> = [Layout] extends [keyof LayoutMiddlewaresMap]
|
|
128
|
+
? LayoutMiddlewaresMap[Layout] extends { readonly __acc?: infer Acc extends readonly unknown[] }
|
|
131
129
|
? Acc
|
|
132
|
-
: readonly []
|
|
130
|
+
: LayoutMiddlewaresMap[Layout] extends readonly unknown[]
|
|
131
|
+
? LayoutMiddlewaresMap[Layout]
|
|
132
|
+
: readonly []
|
|
133
|
+
: readonly [];
|
|
133
134
|
|
|
134
135
|
type ResolveLayoutMiddlewares<
|
|
135
136
|
Layout extends LayoutId | null,
|
|
136
137
|
Depth extends readonly unknown[] = [],
|
|
137
138
|
> = Depth["length"] extends 10
|
|
138
139
|
? readonly []
|
|
139
|
-
: Layout extends LayoutId
|
|
140
|
-
?
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
140
|
+
: [Layout] extends [LayoutId]
|
|
141
|
+
? LayoutParent<Layout> extends infer Parent extends LayoutId
|
|
142
|
+
? readonly [
|
|
143
|
+
...ResolveLayoutMiddlewares<Parent, [...Depth, unknown]>,
|
|
144
|
+
...LayoutMiddlewares<Layout>,
|
|
145
|
+
]
|
|
146
|
+
: readonly [...LayoutMiddlewares<Layout>]
|
|
144
147
|
: readonly [];
|
|
145
148
|
|
|
146
149
|
export type ResolveLayoutIdChain<
|
|
@@ -184,17 +187,10 @@ type RouteEntry<Path extends RoutePath, TMethod extends Method> = RouteByPathMet
|
|
|
184
187
|
? Entry
|
|
185
188
|
: never;
|
|
186
189
|
|
|
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
190
|
type RouteLayoutChain<Path extends RoutePath, TMethod extends Method> =
|
|
193
|
-
RouteEntry<Path, TMethod> extends {
|
|
191
|
+
RouteEntry<Path, TMethod> extends { layouts: infer Chain extends readonly LayoutId[] }
|
|
194
192
|
? Chain
|
|
195
|
-
:
|
|
196
|
-
? readonly [RouteParent<Path, TMethod>]
|
|
197
|
-
: readonly [];
|
|
193
|
+
: readonly [];
|
|
198
194
|
|
|
199
195
|
export type RouteLayoutMiddlewares<
|
|
200
196
|
Path extends RoutePath,
|
|
@@ -231,15 +227,13 @@ export type RouteChainContext<
|
|
|
231
227
|
> = Simplify<
|
|
232
228
|
TAppContext &
|
|
233
229
|
UnitRuntimeContext & {
|
|
234
|
-
query:
|
|
235
|
-
params:
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
MergePart<TParams, RouteResolvedField<Path, TMethod, Acc, "params">>
|
|
239
|
-
>
|
|
230
|
+
query: MergePart<TQuery, RouteResolvedField<Path, TMethod, Acc, "query">>;
|
|
231
|
+
params: ResolveParams<
|
|
232
|
+
PathParams<Path>,
|
|
233
|
+
MergePart<TParams, RouteResolvedField<Path, TMethod, Acc, "params">>
|
|
240
234
|
>;
|
|
241
|
-
body:
|
|
242
|
-
state:
|
|
235
|
+
body: MergePart<TBody, RouteResolvedField<Path, TMethod, Acc, "body">>;
|
|
236
|
+
state: RouteResolvedField<Path, TMethod, Acc, "state">;
|
|
243
237
|
headers: TaserHeaders;
|
|
244
238
|
cookies: TaserCookieJar;
|
|
245
239
|
}
|
|
@@ -496,7 +490,9 @@ export type InferRouteInputFromPath<Path extends RoutePath, TMethod extends Meth
|
|
|
496
490
|
export type MiddlewareLayoutField<
|
|
497
491
|
Layout extends LayoutId,
|
|
498
492
|
Field extends "query" | "params" | "body" | "state",
|
|
499
|
-
> =
|
|
493
|
+
> = [LayoutParent<Layout>] extends [infer Parent extends LayoutId]
|
|
494
|
+
? MergeMiddlewareField<ResolveLayoutMiddlewares<Parent>, Field>
|
|
495
|
+
: {};
|
|
500
496
|
|
|
501
497
|
type MiddlewareChainField<
|
|
502
498
|
Layout extends LayoutId,
|
|
@@ -507,20 +503,27 @@ type MiddlewareChainField<
|
|
|
507
503
|
export type MiddlewareChainContext<
|
|
508
504
|
Layout extends LayoutId,
|
|
509
505
|
Acc extends readonly unknown[],
|
|
510
|
-
TQuery,
|
|
511
|
-
TParams,
|
|
512
|
-
TBody,
|
|
506
|
+
TQuery = unknown,
|
|
507
|
+
TParams = unknown,
|
|
508
|
+
TBody = unknown,
|
|
513
509
|
TAppContext extends Record<string, unknown> = AppContext,
|
|
514
510
|
> = Simplify<
|
|
515
|
-
TAppContext &
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
511
|
+
TAppContext & {
|
|
512
|
+
readonly request: Request;
|
|
513
|
+
readonly method: Method;
|
|
514
|
+
readonly url: URL;
|
|
515
|
+
readonly headers: TaserHeaders;
|
|
516
|
+
readonly cookies: TaserCookieJar;
|
|
517
|
+
query: Simplify<MergePart<TQuery, MiddlewareChainField<Layout, Acc, "query">>>;
|
|
518
|
+
params: Simplify<
|
|
519
|
+
ResolveParams<
|
|
520
|
+
LayoutParams<Layout>,
|
|
521
|
+
Simplify<MergePart<TParams, MiddlewareChainField<Layout, Acc, "params">>>
|
|
522
|
+
>
|
|
523
|
+
>;
|
|
524
|
+
body: Simplify<MergePart<TBody, MiddlewareChainField<Layout, Acc, "body">>>;
|
|
525
|
+
state: Simplify<MiddlewareChainField<Layout, Acc, "state">>;
|
|
526
|
+
}
|
|
524
527
|
>;
|
|
525
528
|
|
|
526
529
|
export type MiddlewareBuilder<
|
|
@@ -531,9 +534,6 @@ export type MiddlewareBuilder<
|
|
|
531
534
|
readonly layout: Layout;
|
|
532
535
|
readonly middlewares: readonly MiddlewareDefinition[];
|
|
533
536
|
readonly __acc?: Acc;
|
|
534
|
-
readonly $Infer: {
|
|
535
|
-
Context: MiddlewareChainContext<Layout, Acc, unknown, unknown, unknown, TAppContext>;
|
|
536
|
-
};
|
|
537
537
|
use<
|
|
538
538
|
TAcc,
|
|
539
539
|
TReturns extends ReturnsMap = {},
|
|
@@ -553,22 +553,28 @@ export type MiddlewareBuilder<
|
|
|
553
553
|
>,
|
|
554
554
|
] extends [true, true]
|
|
555
555
|
? 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
|
-
},
|
|
556
|
+
: never,
|
|
568
557
|
): MiddlewareBuilder<Layout, readonly [...Acc, TAcc], TAppContext>;
|
|
569
558
|
use<R = unknown>(
|
|
570
559
|
fn: (
|
|
571
|
-
ctx:
|
|
560
|
+
ctx: Simplify<
|
|
561
|
+
TAppContext & {
|
|
562
|
+
readonly request: Request;
|
|
563
|
+
readonly method: Method;
|
|
564
|
+
readonly url: URL;
|
|
565
|
+
readonly headers: TaserHeaders;
|
|
566
|
+
readonly cookies: TaserCookieJar;
|
|
567
|
+
query: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "query">>>;
|
|
568
|
+
params: Simplify<
|
|
569
|
+
ResolveParams<
|
|
570
|
+
LayoutParams<Layout>,
|
|
571
|
+
Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "params">>>
|
|
572
|
+
>
|
|
573
|
+
>;
|
|
574
|
+
body: Simplify<MergePart<unknown, MiddlewareChainField<Layout, Acc, "body">>>;
|
|
575
|
+
state: Simplify<MiddlewareChainField<Layout, Acc, "state">>;
|
|
576
|
+
}
|
|
577
|
+
>,
|
|
572
578
|
next: NextFn,
|
|
573
579
|
) => Awaitable<R>,
|
|
574
580
|
): MiddlewareBuilder<
|
|
@@ -747,21 +753,7 @@ export type RouteMiddlewareBuilder<
|
|
|
747
753
|
>,
|
|
748
754
|
] extends [true, true]
|
|
749
755
|
? 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
|
-
},
|
|
756
|
+
: never,
|
|
765
757
|
): RouteMiddlewareBuilder<
|
|
766
758
|
Path,
|
|
767
759
|
TMethod,
|
package/src/types/type-utils.ts
CHANGED
|
@@ -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
|
|
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),
|
package/src/types/units.ts
CHANGED
|
@@ -68,10 +68,10 @@ export type MiddlewareReturnFromParts<
|
|
|
68
68
|
TParamsIn = TParams,
|
|
69
69
|
TBodyIn = TBody,
|
|
70
70
|
> = {
|
|
71
|
-
query:
|
|
72
|
-
params:
|
|
73
|
-
body:
|
|
74
|
-
state:
|
|
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>;
|