@taserjs/router 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +24 -0
  3. package/dist/cjs/constants.cjs +17 -0
  4. package/dist/cjs/constants.cjs.map +1 -0
  5. package/dist/cjs/constants.d.cts +8 -0
  6. package/dist/cjs/create-context.cjs +8 -0
  7. package/dist/cjs/create-context.cjs.map +1 -0
  8. package/dist/cjs/create-context.d.cts +5 -0
  9. package/dist/cjs/define/handler.cjs +38 -0
  10. package/dist/cjs/define/handler.cjs.map +1 -0
  11. package/dist/cjs/define/handler.d.cts +13 -0
  12. package/dist/cjs/define/middleware.cjs +36 -0
  13. package/dist/cjs/define/middleware.cjs.map +1 -0
  14. package/dist/cjs/define/middleware.d.cts +85 -0
  15. package/dist/cjs/define/validators.cjs +14 -0
  16. package/dist/cjs/define/validators.cjs.map +1 -0
  17. package/dist/cjs/define/validators.d.cts +8 -0
  18. package/dist/cjs/factories.cjs +29 -0
  19. package/dist/cjs/factories.cjs.map +1 -0
  20. package/dist/cjs/factories.d.cts +61 -0
  21. package/dist/cjs/index.cjs +42 -0
  22. package/dist/cjs/index.d.cts +12 -0
  23. package/dist/cjs/middleware/auth.cjs +34 -0
  24. package/dist/cjs/middleware/auth.cjs.map +1 -0
  25. package/dist/cjs/middleware/auth.d.cts +9 -0
  26. package/dist/cjs/middleware/body-limit.cjs +12 -0
  27. package/dist/cjs/middleware/body-limit.cjs.map +1 -0
  28. package/dist/cjs/middleware/body-limit.d.cts +3 -0
  29. package/dist/cjs/middleware/compress.cjs +12 -0
  30. package/dist/cjs/middleware/compress.cjs.map +1 -0
  31. package/dist/cjs/middleware/compress.d.cts +3 -0
  32. package/dist/cjs/middleware/cors.cjs +12 -0
  33. package/dist/cjs/middleware/cors.cjs.map +1 -0
  34. package/dist/cjs/middleware/cors.d.cts +3 -0
  35. package/dist/cjs/middleware/csrf.cjs +12 -0
  36. package/dist/cjs/middleware/csrf.cjs.map +1 -0
  37. package/dist/cjs/middleware/csrf.d.cts +3 -0
  38. package/dist/cjs/middleware/etag.cjs +12 -0
  39. package/dist/cjs/middleware/etag.cjs.map +1 -0
  40. package/dist/cjs/middleware/etag.d.cts +3 -0
  41. package/dist/cjs/middleware/jwk.cjs +25 -0
  42. package/dist/cjs/middleware/jwk.cjs.map +1 -0
  43. package/dist/cjs/middleware/jwk.d.cts +15 -0
  44. package/dist/cjs/middleware/jwt.cjs +16 -0
  45. package/dist/cjs/middleware/jwt.cjs.map +1 -0
  46. package/dist/cjs/middleware/jwt.d.cts +10 -0
  47. package/dist/cjs/middleware/secure-headers.cjs +12 -0
  48. package/dist/cjs/middleware/secure-headers.cjs.map +1 -0
  49. package/dist/cjs/middleware/secure-headers.d.cts +3 -0
  50. package/dist/cjs/middleware/timing.cjs +12 -0
  51. package/dist/cjs/middleware/timing.cjs.map +1 -0
  52. package/dist/cjs/middleware/timing.d.cts +3 -0
  53. package/dist/cjs/middleware.cjs +17 -0
  54. package/dist/cjs/middleware.cjs.map +1 -0
  55. package/dist/cjs/middleware.d.cts +2 -0
  56. package/dist/cjs/register.d.cts +2 -0
  57. package/dist/cjs/route.cjs +94 -0
  58. package/dist/cjs/route.cjs.map +1 -0
  59. package/dist/cjs/route.d.cts +5 -0
  60. package/dist/cjs/taser-app.cjs +42 -0
  61. package/dist/cjs/taser-app.cjs.map +1 -0
  62. package/dist/cjs/taser-app.d.cts +21 -0
  63. package/dist/cjs/taser-router.cjs +83 -0
  64. package/dist/cjs/taser-router.cjs.map +1 -0
  65. package/dist/cjs/taser-router.d.cts +44 -0
  66. package/dist/cjs/types/app.d.cts +46 -0
  67. package/dist/cjs/types/index.d.cts +305 -0
  68. package/dist/cjs/types/returns.d.cts +37 -0
  69. package/dist/cjs/types/schema.d.cts +14 -0
  70. package/dist/cjs/types/type-utils.d.cts +52 -0
  71. package/dist/cjs/types/units.cjs +8 -0
  72. package/dist/cjs/types/units.cjs.map +1 -0
  73. package/dist/cjs/types/units.d.cts +98 -0
  74. package/dist/esm/constants.d.ts +8 -0
  75. package/dist/esm/constants.js +16 -0
  76. package/dist/esm/constants.js.map +1 -0
  77. package/dist/esm/create-context.d.ts +5 -0
  78. package/dist/esm/create-context.js +8 -0
  79. package/dist/esm/create-context.js.map +1 -0
  80. package/dist/esm/define/handler.d.ts +13 -0
  81. package/dist/esm/define/handler.js +38 -0
  82. package/dist/esm/define/handler.js.map +1 -0
  83. package/dist/esm/define/middleware.d.ts +85 -0
  84. package/dist/esm/define/middleware.js +36 -0
  85. package/dist/esm/define/middleware.js.map +1 -0
  86. package/dist/esm/define/validators.d.ts +8 -0
  87. package/dist/esm/define/validators.js +14 -0
  88. package/dist/esm/define/validators.js.map +1 -0
  89. package/dist/esm/factories.d.ts +61 -0
  90. package/dist/esm/factories.js +21 -0
  91. package/dist/esm/factories.js.map +1 -0
  92. package/dist/esm/index.d.ts +12 -0
  93. package/dist/esm/index.js +8 -0
  94. package/dist/esm/middleware/auth.d.ts +9 -0
  95. package/dist/esm/middleware/auth.js +33 -0
  96. package/dist/esm/middleware/auth.js.map +1 -0
  97. package/dist/esm/middleware/body-limit.d.ts +3 -0
  98. package/dist/esm/middleware/body-limit.js +11 -0
  99. package/dist/esm/middleware/body-limit.js.map +1 -0
  100. package/dist/esm/middleware/compress.d.ts +3 -0
  101. package/dist/esm/middleware/compress.js +11 -0
  102. package/dist/esm/middleware/compress.js.map +1 -0
  103. package/dist/esm/middleware/cors.d.ts +3 -0
  104. package/dist/esm/middleware/cors.js +11 -0
  105. package/dist/esm/middleware/cors.js.map +1 -0
  106. package/dist/esm/middleware/csrf.d.ts +3 -0
  107. package/dist/esm/middleware/csrf.js +11 -0
  108. package/dist/esm/middleware/csrf.js.map +1 -0
  109. package/dist/esm/middleware/etag.d.ts +3 -0
  110. package/dist/esm/middleware/etag.js +11 -0
  111. package/dist/esm/middleware/etag.js.map +1 -0
  112. package/dist/esm/middleware/jwk.d.ts +15 -0
  113. package/dist/esm/middleware/jwk.js +24 -0
  114. package/dist/esm/middleware/jwk.js.map +1 -0
  115. package/dist/esm/middleware/jwt.d.ts +10 -0
  116. package/dist/esm/middleware/jwt.js +15 -0
  117. package/dist/esm/middleware/jwt.js.map +1 -0
  118. package/dist/esm/middleware/secure-headers.d.ts +3 -0
  119. package/dist/esm/middleware/secure-headers.js +11 -0
  120. package/dist/esm/middleware/secure-headers.js.map +1 -0
  121. package/dist/esm/middleware/timing.d.ts +3 -0
  122. package/dist/esm/middleware/timing.js +11 -0
  123. package/dist/esm/middleware/timing.js.map +1 -0
  124. package/dist/esm/middleware.d.ts +2 -0
  125. package/dist/esm/middleware.js +17 -0
  126. package/dist/esm/middleware.js.map +1 -0
  127. package/dist/esm/register.d.ts +2 -0
  128. package/dist/esm/route.d.ts +5 -0
  129. package/dist/esm/route.js +94 -0
  130. package/dist/esm/route.js.map +1 -0
  131. package/dist/esm/taser-app.d.ts +21 -0
  132. package/dist/esm/taser-app.js +40 -0
  133. package/dist/esm/taser-app.js.map +1 -0
  134. package/dist/esm/taser-router.d.ts +44 -0
  135. package/dist/esm/taser-router.js +82 -0
  136. package/dist/esm/taser-router.js.map +1 -0
  137. package/dist/esm/types/app.d.ts +46 -0
  138. package/dist/esm/types/index.d.ts +305 -0
  139. package/dist/esm/types/returns.d.ts +37 -0
  140. package/dist/esm/types/schema.d.ts +14 -0
  141. package/dist/esm/types/type-utils.d.ts +52 -0
  142. package/dist/esm/types/units.d.ts +98 -0
  143. package/dist/esm/types/units.js +8 -0
  144. package/dist/esm/types/units.js.map +1 -0
  145. package/package.json +149 -0
  146. package/src/constants.ts +10 -0
  147. package/src/create-context.ts +19 -0
  148. package/src/define/handler.ts +72 -0
  149. package/src/define/middleware.ts +289 -0
  150. package/src/define/validators.ts +22 -0
  151. package/src/factories.ts +183 -0
  152. package/src/index.ts +44 -0
  153. package/src/middleware/auth.ts +51 -0
  154. package/src/middleware/body-limit.ts +11 -0
  155. package/src/middleware/compress.ts +11 -0
  156. package/src/middleware/cors.ts +11 -0
  157. package/src/middleware/csrf.ts +11 -0
  158. package/src/middleware/etag.ts +11 -0
  159. package/src/middleware/jwk.ts +47 -0
  160. package/src/middleware/jwt.ts +18 -0
  161. package/src/middleware/secure-headers.ts +11 -0
  162. package/src/middleware/timing.ts +11 -0
  163. package/src/middleware.ts +19 -0
  164. package/src/register.ts +1 -0
  165. package/src/route.ts +145 -0
  166. package/src/taser-app.ts +43 -0
  167. package/src/taser-router.ts +160 -0
  168. package/src/types/app.ts +65 -0
  169. package/src/types/index.ts +1064 -0
  170. package/src/types/returns.ts +135 -0
  171. package/src/types/schema.ts +22 -0
  172. package/src/types/type-utils.ts +86 -0
  173. package/src/types/units.ts +167 -0
package/package.json ADDED
@@ -0,0 +1,149 @@
1
+ {
2
+ "name": "@taserjs/router",
3
+ "version": "0.0.0",
4
+ "description": "Type-safe Node.js router with runtime validation and middleware",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "main": "./dist/cjs/index.cjs",
8
+ "module": "./dist/esm/index.js",
9
+ "types": "./dist/esm/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "import": {
13
+ "types": "./dist/esm/index.d.ts",
14
+ "default": "./dist/esm/index.js"
15
+ },
16
+ "require": {
17
+ "types": "./dist/cjs/index.d.cts",
18
+ "default": "./dist/cjs/index.cjs"
19
+ }
20
+ },
21
+ "./body-limit": {
22
+ "import": {
23
+ "types": "./dist/esm/middleware/body-limit.d.ts",
24
+ "default": "./dist/esm/middleware/body-limit.js"
25
+ },
26
+ "require": {
27
+ "types": "./dist/cjs/middleware/body-limit.d.cts",
28
+ "default": "./dist/cjs/middleware/body-limit.cjs"
29
+ }
30
+ },
31
+ "./compress": {
32
+ "import": {
33
+ "types": "./dist/esm/middleware/compress.d.ts",
34
+ "default": "./dist/esm/middleware/compress.js"
35
+ },
36
+ "require": {
37
+ "types": "./dist/cjs/middleware/compress.d.cts",
38
+ "default": "./dist/cjs/middleware/compress.cjs"
39
+ }
40
+ },
41
+ "./cors": {
42
+ "import": {
43
+ "types": "./dist/esm/middleware/cors.d.ts",
44
+ "default": "./dist/esm/middleware/cors.js"
45
+ },
46
+ "require": {
47
+ "types": "./dist/cjs/middleware/cors.d.cts",
48
+ "default": "./dist/cjs/middleware/cors.cjs"
49
+ }
50
+ },
51
+ "./csrf": {
52
+ "import": {
53
+ "types": "./dist/esm/middleware/csrf.d.ts",
54
+ "default": "./dist/esm/middleware/csrf.js"
55
+ },
56
+ "require": {
57
+ "types": "./dist/cjs/middleware/csrf.d.cts",
58
+ "default": "./dist/cjs/middleware/csrf.cjs"
59
+ }
60
+ },
61
+ "./etag": {
62
+ "import": {
63
+ "types": "./dist/esm/middleware/etag.d.ts",
64
+ "default": "./dist/esm/middleware/etag.js"
65
+ },
66
+ "require": {
67
+ "types": "./dist/cjs/middleware/etag.d.cts",
68
+ "default": "./dist/cjs/middleware/etag.cjs"
69
+ }
70
+ },
71
+ "./jwk": {
72
+ "import": {
73
+ "types": "./dist/esm/middleware/jwk.d.ts",
74
+ "default": "./dist/esm/middleware/jwk.js"
75
+ },
76
+ "require": {
77
+ "types": "./dist/cjs/middleware/jwk.d.cts",
78
+ "default": "./dist/cjs/middleware/jwk.cjs"
79
+ }
80
+ },
81
+ "./jwt": {
82
+ "import": {
83
+ "types": "./dist/esm/middleware/jwt.d.ts",
84
+ "default": "./dist/esm/middleware/jwt.js"
85
+ },
86
+ "require": {
87
+ "types": "./dist/cjs/middleware/jwt.d.cts",
88
+ "default": "./dist/cjs/middleware/jwt.cjs"
89
+ }
90
+ },
91
+ "./secure-headers": {
92
+ "import": {
93
+ "types": "./dist/esm/middleware/secure-headers.d.ts",
94
+ "default": "./dist/esm/middleware/secure-headers.js"
95
+ },
96
+ "require": {
97
+ "types": "./dist/cjs/middleware/secure-headers.d.cts",
98
+ "default": "./dist/cjs/middleware/secure-headers.cjs"
99
+ }
100
+ },
101
+ "./timing": {
102
+ "import": {
103
+ "types": "./dist/esm/middleware/timing.d.ts",
104
+ "default": "./dist/esm/middleware/timing.js"
105
+ },
106
+ "require": {
107
+ "types": "./dist/cjs/middleware/timing.d.cts",
108
+ "default": "./dist/cjs/middleware/timing.cjs"
109
+ }
110
+ },
111
+ "./package.json": "./package.json"
112
+ },
113
+ "files": [
114
+ "dist",
115
+ "src"
116
+ ],
117
+ "dependencies": {
118
+ "@standard-schema/spec": "^1.1.0",
119
+ "hono": "^4.10.3",
120
+ "@taserjs/router-core": "0.0.0",
121
+ "@taserjs/router-utils": "0.0.0"
122
+ },
123
+ "devDependencies": {
124
+ "@tanstack/vite-config": "^0.6.0",
125
+ "publint": "^0.3.22",
126
+ "vite": "^8.1.5",
127
+ "vitest": "^4.1.10",
128
+ "zod": "^4.4.3"
129
+ },
130
+ "engines": {
131
+ "node": ">=20.19"
132
+ },
133
+ "license": "ISC",
134
+ "repository": {
135
+ "type": "git",
136
+ "url": "git+https://github.com/taserjs/taserjs.git",
137
+ "directory": "packages/router"
138
+ },
139
+ "publishConfig": {
140
+ "access": "public",
141
+ "registry": "https://registry.npmjs.org"
142
+ },
143
+ "scripts": {
144
+ "clean": "rimraf dist",
145
+ "build": "vite build && publint --strict",
146
+ "typecheck": "tsc --noEmit -p tsconfig.json",
147
+ "test": "vitest run"
148
+ }
149
+ }
@@ -0,0 +1,10 @@
1
+ /** Input schema keys validated by middleware and route handlers. Headers/cookies are parsed only. */
2
+ export const SCHEMA_KEYS = ['query', 'params', 'body'] as const
3
+
4
+ export type SchemaKey = (typeof SCHEMA_KEYS)[number]
5
+
6
+ export const HANDLER_SCHEMA_KEY_MAP = {
7
+ query: 'handlerQuery',
8
+ params: 'handlerParams',
9
+ body: 'handlerBody',
10
+ } as const satisfies Record<SchemaKey, string>
@@ -0,0 +1,19 @@
1
+ import type { ReservedContextKey } from '@taserjs/router-core'
2
+
3
+ import type { ContextDefinition } from './types/app.js'
4
+
5
+ type NoReservedKeysConstraint<TBoot extends Record<string, unknown>, TReq extends Record<string, unknown>>
6
+ = Extract<keyof TBoot | keyof TReq, ReservedContextKey> extends never
7
+ ? unknown
8
+ : never
9
+
10
+ export function createContext<
11
+ TBoot extends Record<string, unknown> = Record<string, never>,
12
+ TReq extends Record<string, unknown> = Record<string, never>,
13
+ >(
14
+ definition: ContextDefinition<TBoot, TReq> & NoReservedKeysConstraint<TBoot, TReq>,
15
+ ): ContextDefinition<TBoot, TReq> {
16
+ return definition
17
+ }
18
+
19
+ export type { ContextDefinition, InferAppContext } from './types/app.js'
@@ -0,0 +1,72 @@
1
+ import type { HandlerBuilder } from '../types/index.js'
2
+ import type {
3
+ AppContext,
4
+ HandlerUnit,
5
+ MiddlewareDefinition,
6
+ ReturnsMap,
7
+ ValidatorParts,
8
+ } from '../types/units.js'
9
+ import type { Schema } from '../types/schema.js'
10
+ import { pickDefinedSchemas, type SchemaValidators } from './validators.js'
11
+ import { collectReturnsFromDefinitions } from '@taserjs/router-utils'
12
+
13
+ function createHandlerBuilder<TAppContext extends Record<string, unknown> = AppContext>(
14
+ validators: SchemaValidators,
15
+ middlewares: MiddlewareDefinition[],
16
+ returnsMap: ReturnsMap,
17
+ ): HandlerBuilder<readonly [], ValidatorParts, {}, TAppContext> {
18
+ const builder = {
19
+ returns(map: ReturnsMap) {
20
+ return createHandlerBuilder<TAppContext>(validators, middlewares, { ...returnsMap, ...map })
21
+ },
22
+ use(unitOrOptions: MiddlewareDefinition) {
23
+ middlewares.push(unitOrOptions)
24
+ return builder
25
+ },
26
+ handler(fn: (ctx: unknown) => unknown) {
27
+ const mwReturns = collectReturnsFromDefinitions(middlewares)
28
+ const mergedReturns = { ...mwReturns, ...returnsMap }
29
+ const unit = {
30
+ $Infer: { Output: undefined as unknown as Response },
31
+ middlewares: [...middlewares],
32
+ handler: fn as HandlerUnit<readonly [], ValidatorParts>['handler'],
33
+ ...pickDefinedSchemas(validators),
34
+ ...(Object.keys(mergedReturns).length > 0 ? { returns: mergedReturns } : {}),
35
+ } as HandlerUnit<readonly [], ValidatorParts>
36
+ return unit
37
+ },
38
+ }
39
+
40
+ return builder as unknown as HandlerBuilder<readonly [], ValidatorParts, {}, TAppContext>
41
+ }
42
+
43
+ export function defineHandler<TAppContext extends Record<string, unknown> = AppContext>(): HandlerBuilder<
44
+ readonly [],
45
+ {},
46
+ {},
47
+ TAppContext
48
+ >
49
+
50
+ export function defineHandler<
51
+ TAppContext extends Record<string, unknown> = AppContext,
52
+ TQuery = unknown,
53
+ TParams = unknown,
54
+ TBody = unknown,
55
+ >(
56
+ options: {
57
+ query?: Schema<TQuery>
58
+ params?: Schema<TParams>
59
+ body?: Schema<TBody>
60
+ },
61
+ ): HandlerBuilder<
62
+ readonly [],
63
+ { query: TQuery, params: TParams, body: TBody },
64
+ {},
65
+ TAppContext
66
+ >
67
+
68
+ export function defineHandler<TAppContext extends Record<string, unknown> = AppContext>(
69
+ options?: SchemaValidators,
70
+ ): HandlerBuilder<readonly [], ValidatorParts, {}, TAppContext> {
71
+ return createHandlerBuilder<TAppContext>(options ?? {}, [], {})
72
+ }
@@ -0,0 +1,289 @@
1
+ import type { ReplyResult } from '@taserjs/router-utils'
2
+ import { createTaserCompatHandler } from '@taserjs/router-core'
3
+
4
+ import type { Awaitable, ReturnsMap } from '../types/index.js'
5
+ import type {
6
+ AppContext,
7
+ MiddlewareReturnFromParts,
8
+ MiddlewareUnit,
9
+ StandaloneMiddlewareContext,
10
+ } from '../types/units.js'
11
+ import type { Schema } from '../types/schema.js'
12
+
13
+ type HonoMiddlewareHandler = Parameters<typeof createTaserCompatHandler>[0]
14
+
15
+ type HonoMiddlewareUnit = MiddlewareUnit<
16
+ MiddlewareReturnFromParts<unknown, unknown, unknown, {}>
17
+ >
18
+
19
+ type MiddlewareBuilderState<
20
+ TQuery = unknown,
21
+ TParams = unknown,
22
+ TBody = unknown,
23
+ TState = unknown,
24
+ TCtx = unknown,
25
+ TReturns extends ReturnsMap = {},
26
+ > = {
27
+ state?: Schema<TState>
28
+ ctx?: Schema<TCtx>
29
+ query?: Schema<TQuery>
30
+ params?: Schema<TParams>
31
+ body?: Schema<TBody>
32
+ returns?: TReturns
33
+ }
34
+
35
+ type FluentNext<TState, TCtx>
36
+ = [TState] extends [undefined]
37
+ ? [TCtx] extends [undefined]
38
+ ? () => Promise<ReplyResult>
39
+ : (args: { ctx: TCtx }) => Promise<ReplyResult>
40
+ : [TCtx] extends [undefined]
41
+ ? (args: { state: TState }) => Promise<ReplyResult>
42
+ : (args: { state: TState, ctx: TCtx }) => Promise<ReplyResult>
43
+
44
+ type FluentMiddlewareBuilder<
45
+ TQuery = unknown,
46
+ TParams = unknown,
47
+ TBody = unknown,
48
+ TState = undefined,
49
+ TCtx = undefined,
50
+ TReturns extends ReturnsMap = {},
51
+ TAppContext extends Record<string, unknown> = AppContext,
52
+ > = {
53
+ returns<const M extends ReturnsMap>(
54
+ map: M,
55
+ ): FluentMiddlewareBuilder<
56
+ TQuery,
57
+ TParams,
58
+ TBody,
59
+ TState,
60
+ TCtx,
61
+ Omit<TReturns, keyof M> & M,
62
+ TAppContext
63
+ >
64
+ handler(
65
+ fn: (
66
+ ctx: StandaloneMiddlewareContext<TQuery, TParams, TBody, TAppContext>,
67
+ next: FluentNext<TState, TCtx>,
68
+ ) => Awaitable<ReplyResult | Response | unknown>,
69
+ ): MiddlewareUnit<
70
+ MiddlewareReturnFromParts<
71
+ TQuery,
72
+ TParams,
73
+ TBody,
74
+ TState extends undefined ? {} : TState,
75
+ TCtx extends undefined ? {} : TCtx
76
+ >,
77
+ TReturns
78
+ >
79
+ }
80
+
81
+ function createFluentBuilder<TAppContext extends Record<string, unknown> = AppContext>(
82
+ state: MiddlewareBuilderState,
83
+ ): FluentMiddlewareBuilder<unknown, unknown, unknown, undefined, undefined, {}, TAppContext> {
84
+ return {
85
+ returns(map: ReturnsMap) {
86
+ return createFluentBuilder<TAppContext>({
87
+ ...state,
88
+ returns: { ...(state.returns ?? {}), ...map },
89
+ })
90
+ },
91
+ handler(fn: (...args: never[]) => unknown) {
92
+ const unit = {
93
+ ...state,
94
+ handler: fn,
95
+ __middlewareAcc: undefined as unknown,
96
+ ...(state.returns ? { __returns: state.returns } : {}),
97
+ }
98
+ return unit as unknown as MiddlewareUnit<
99
+ MiddlewareReturnFromParts<unknown, unknown, unknown, unknown, unknown>,
100
+ ReturnsMap
101
+ >
102
+ },
103
+ } as unknown as FluentMiddlewareBuilder<unknown, unknown, unknown, undefined, undefined, {}, TAppContext>
104
+ }
105
+
106
+ export function defineMiddleware(middleware: HonoMiddlewareHandler): HonoMiddlewareUnit
107
+
108
+ export function defineMiddleware<
109
+ TAppContext extends Record<string, unknown> = AppContext,
110
+ TState = unknown,
111
+ TCtx = unknown,
112
+ TQuery = unknown,
113
+ TParams = unknown,
114
+ TBody = unknown,
115
+ TReturns extends ReturnsMap = {},
116
+ >(
117
+ options: {
118
+ state: Schema<TState>
119
+ ctx: Schema<TCtx>
120
+ query?: Schema<TQuery>
121
+ params?: Schema<TParams>
122
+ body?: Schema<TBody>
123
+ returns?: TReturns
124
+ handler: (
125
+ ctx: StandaloneMiddlewareContext<TQuery, TParams, TBody, TAppContext>,
126
+ next: (args: { state: TState, ctx: TCtx }) => Promise<ReplyResult>,
127
+ ) => Awaitable<ReplyResult | Response | unknown>
128
+ },
129
+ ): MiddlewareUnit<
130
+ MiddlewareReturnFromParts<TQuery, TParams, TBody, TState, TCtx>,
131
+ TReturns
132
+ >
133
+
134
+ export function defineMiddleware<
135
+ TAppContext extends Record<string, unknown> = AppContext,
136
+ TState = unknown,
137
+ TQuery = unknown,
138
+ TParams = unknown,
139
+ TBody = unknown,
140
+ TReturns extends ReturnsMap = {},
141
+ >(
142
+ options: {
143
+ state: Schema<TState>
144
+ query?: Schema<TQuery>
145
+ params?: Schema<TParams>
146
+ body?: Schema<TBody>
147
+ returns?: TReturns
148
+ handler: (
149
+ ctx: StandaloneMiddlewareContext<TQuery, TParams, TBody, TAppContext>,
150
+ next: (args: { state: TState }) => Promise<ReplyResult>,
151
+ ) => Awaitable<ReplyResult | Response | unknown>
152
+ },
153
+ ): MiddlewareUnit<
154
+ MiddlewareReturnFromParts<TQuery, TParams, TBody, TState>,
155
+ TReturns
156
+ >
157
+
158
+ export function defineMiddleware<
159
+ TAppContext extends Record<string, unknown> = AppContext,
160
+ TCtx = unknown,
161
+ TQuery = unknown,
162
+ TParams = unknown,
163
+ TBody = unknown,
164
+ TReturns extends ReturnsMap = {},
165
+ >(
166
+ options: {
167
+ ctx: Schema<TCtx>
168
+ query?: Schema<TQuery>
169
+ params?: Schema<TParams>
170
+ body?: Schema<TBody>
171
+ returns?: TReturns
172
+ handler: (
173
+ ctx: StandaloneMiddlewareContext<TQuery, TParams, TBody, TAppContext>,
174
+ next: (args: { ctx: TCtx }) => Promise<ReplyResult>,
175
+ ) => Awaitable<ReplyResult | Response | unknown>
176
+ },
177
+ ): MiddlewareUnit<
178
+ MiddlewareReturnFromParts<TQuery, TParams, TBody, {}, TCtx>,
179
+ TReturns
180
+ >
181
+
182
+ export function defineMiddleware<
183
+ TAppContext extends Record<string, unknown> = AppContext,
184
+ TQuery = unknown,
185
+ TParams = unknown,
186
+ TBody = unknown,
187
+ TReturns extends ReturnsMap = {},
188
+ >(
189
+ options: {
190
+ query?: Schema<TQuery>
191
+ params?: Schema<TParams>
192
+ body?: Schema<TBody>
193
+ returns?: TReturns
194
+ handler: (
195
+ ctx: StandaloneMiddlewareContext<TQuery, TParams, TBody, TAppContext>,
196
+ next: () => Promise<ReplyResult>,
197
+ ) => Awaitable<ReplyResult | Response | unknown>
198
+ },
199
+ ): MiddlewareUnit<
200
+ MiddlewareReturnFromParts<TQuery, TParams, TBody, {}>,
201
+ TReturns
202
+ >
203
+
204
+ export function defineMiddleware<
205
+ TAppContext extends Record<string, unknown> = AppContext,
206
+ >(): FluentMiddlewareBuilder<unknown, unknown, unknown, undefined, undefined, {}, TAppContext>
207
+
208
+ export function defineMiddleware<
209
+ TAppContext extends Record<string, unknown> = AppContext,
210
+ TQuery = unknown,
211
+ TParams = unknown,
212
+ TBody = unknown,
213
+ >(
214
+ options: {
215
+ query?: Schema<TQuery>
216
+ params?: Schema<TParams>
217
+ body?: Schema<TBody>
218
+ },
219
+ ): FluentMiddlewareBuilder<TQuery, TParams, TBody, undefined, undefined, {}, TAppContext>
220
+
221
+ export function defineMiddleware<
222
+ TAppContext extends Record<string, unknown> = AppContext,
223
+ TState = unknown,
224
+ TQuery = unknown,
225
+ TParams = unknown,
226
+ TBody = unknown,
227
+ >(
228
+ options: {
229
+ state: Schema<TState>
230
+ query?: Schema<TQuery>
231
+ params?: Schema<TParams>
232
+ body?: Schema<TBody>
233
+ },
234
+ ): FluentMiddlewareBuilder<TQuery, TParams, TBody, TState, undefined, {}, TAppContext>
235
+
236
+ export function defineMiddleware<
237
+ TAppContext extends Record<string, unknown> = AppContext,
238
+ TCtx = unknown,
239
+ TQuery = unknown,
240
+ TParams = unknown,
241
+ TBody = unknown,
242
+ >(
243
+ options: {
244
+ ctx: Schema<TCtx>
245
+ query?: Schema<TQuery>
246
+ params?: Schema<TParams>
247
+ body?: Schema<TBody>
248
+ },
249
+ ): FluentMiddlewareBuilder<TQuery, TParams, TBody, undefined, TCtx, {}, TAppContext>
250
+
251
+ export function defineMiddleware<
252
+ TAppContext extends Record<string, unknown> = AppContext,
253
+ TState = unknown,
254
+ TCtx = unknown,
255
+ TQuery = unknown,
256
+ TParams = unknown,
257
+ TBody = unknown,
258
+ >(
259
+ options: {
260
+ state: Schema<TState>
261
+ ctx: Schema<TCtx>
262
+ query?: Schema<TQuery>
263
+ params?: Schema<TParams>
264
+ body?: Schema<TBody>
265
+ },
266
+ ): FluentMiddlewareBuilder<TQuery, TParams, TBody, TState, TCtx, {}, TAppContext>
267
+
268
+ export function defineMiddleware(options?: unknown): unknown {
269
+ if (typeof options === 'function') {
270
+ const honoMiddleware = options as HonoMiddlewareHandler
271
+ return defineMiddleware({
272
+ handler: (ctx, next) => createTaserCompatHandler(honoMiddleware)(ctx, next),
273
+ })
274
+ }
275
+
276
+ if (options === undefined) {
277
+ return createFluentBuilder({})
278
+ }
279
+
280
+ if (
281
+ typeof options === 'object'
282
+ && options !== null
283
+ && !('handler' in options)
284
+ ) {
285
+ return createFluentBuilder(options)
286
+ }
287
+
288
+ return options
289
+ }
@@ -0,0 +1,22 @@
1
+ import type { Schema } from '../types/schema.js'
2
+ import { SCHEMA_KEYS, type SchemaKey } from '../constants.js'
3
+
4
+ export type SchemaValidators = {
5
+ query?: Schema<unknown>
6
+ params?: Schema<unknown>
7
+ body?: Schema<unknown>
8
+ }
9
+
10
+ export function pickDefinedSchemas(
11
+ source: SchemaValidators,
12
+ keyMap?: Partial<Record<SchemaKey, string>>,
13
+ ): Record<string, Schema<unknown>> {
14
+ const result: Record<string, Schema<unknown>> = {}
15
+ for (const key of SCHEMA_KEYS) {
16
+ const value = source[key]
17
+ if (value !== undefined) {
18
+ result[keyMap?.[key] ?? key] = value
19
+ }
20
+ }
21
+ return result
22
+ }