@kerebron/extension-server-hono 0.4.28 → 0.4.30
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/esm/HonoYjsMemAdapter.js +1 -0
- package/esm/HonoYjsMemAdapter.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/compose.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/compose.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/context.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/context.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/helper/websocket/index.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/helper/websocket/index.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/hono-base.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/hono-base.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/http-exception.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/http-exception.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/request/constants.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/request/constants.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/request.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/request.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/router.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/router.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/types.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/types.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/body.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/body.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/constants.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/constants.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/headers.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/headers.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/html.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/html.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/http-status.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/http-status.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/mime.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/mime.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/types.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/types.js.map +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/url.js +1 -0
- package/esm/deps/jsr.io/@hono/hono/4.11.3/src/utils/url.js.map +1 -0
- package/esm/mod.js +1 -0
- package/esm/mod.js.map +1 -0
- package/package.json +5 -1
- package/src/HonoYjsMemAdapter.ts +264 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/compose.ts +73 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/context.ts +770 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/helper/websocket/index.ts +140 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/hono-base.ts +539 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/http-exception.ts +78 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/request/constants.ts +1 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/request.ts +487 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/router.ts +103 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/types.ts +2489 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/utils/body.ts +229 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/utils/constants.ts +4 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/utils/headers.ts +333 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/utils/html.ts +182 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/utils/http-status.ts +72 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/utils/mime.ts +96 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/utils/types.ts +116 -0
- package/src/deps/jsr.io/@hono/hono/4.11.3/src/utils/url.ts +310 -0
- package/src/mod.ts +5 -0
|
@@ -0,0 +1,770 @@
|
|
|
1
|
+
import { HonoRequest } from './request.js'
|
|
2
|
+
import type { Result } from './router.js'
|
|
3
|
+
import type {
|
|
4
|
+
Env,
|
|
5
|
+
FetchEventLike,
|
|
6
|
+
H,
|
|
7
|
+
Input,
|
|
8
|
+
NotFoundHandler,
|
|
9
|
+
RouterRoute,
|
|
10
|
+
TypedResponse,
|
|
11
|
+
} from './types.js'
|
|
12
|
+
import type { ResponseHeader } from './utils/headers.js'
|
|
13
|
+
import { HtmlEscapedCallbackPhase, resolveCallback } from './utils/html.js'
|
|
14
|
+
import type { ContentfulStatusCode, RedirectStatusCode, StatusCode } from './utils/http-status.js'
|
|
15
|
+
import type { BaseMime } from './utils/mime.js'
|
|
16
|
+
import type { InvalidJSONValue, IsAny, JSONParsed, JSONValue } from './utils/types.js'
|
|
17
|
+
|
|
18
|
+
type HeaderRecord =
|
|
19
|
+
| Record<'Content-Type', BaseMime>
|
|
20
|
+
| Record<ResponseHeader, string | string[]>
|
|
21
|
+
| Record<string, string | string[]>
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Data type can be a string, ArrayBuffer, Uint8Array (buffer), or ReadableStream.
|
|
25
|
+
*/
|
|
26
|
+
export type Data = string | ArrayBuffer | ReadableStream | Uint8Array<ArrayBuffer>
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Interface for the execution context in a web worker or similar environment.
|
|
30
|
+
*/
|
|
31
|
+
export interface ExecutionContext {
|
|
32
|
+
/**
|
|
33
|
+
* Extends the lifetime of the event callback until the promise is settled.
|
|
34
|
+
*
|
|
35
|
+
* @param promise - A promise to wait for.
|
|
36
|
+
*/
|
|
37
|
+
waitUntil(promise: Promise<unknown>): void
|
|
38
|
+
/**
|
|
39
|
+
* Allows the event to be passed through to subsequent event listeners.
|
|
40
|
+
*/
|
|
41
|
+
passThroughOnException(): void
|
|
42
|
+
/**
|
|
43
|
+
* For compatibility with Wrangler 4.x.
|
|
44
|
+
*/
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
|
+
props: any
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Interface for context variable mapping.
|
|
51
|
+
*/
|
|
52
|
+
export interface ContextVariableMap {}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Interface for context renderer.
|
|
56
|
+
*/
|
|
57
|
+
export interface ContextRenderer {}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Interface representing a renderer for content.
|
|
61
|
+
*
|
|
62
|
+
* @interface DefaultRenderer
|
|
63
|
+
* @param {string | Promise<string>} content - The content to be rendered, which can be either a string or a Promise resolving to a string.
|
|
64
|
+
* @returns {Response | Promise<Response>} - The response after rendering the content, which can be either a Response or a Promise resolving to a Response.
|
|
65
|
+
*/
|
|
66
|
+
interface DefaultRenderer {
|
|
67
|
+
(content: string | Promise<string>): Response | Promise<Response>
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Renderer type which can either be a ContextRenderer or DefaultRenderer.
|
|
72
|
+
*/
|
|
73
|
+
export type Renderer = ContextRenderer extends Function ? ContextRenderer : DefaultRenderer
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Extracts the props for the renderer.
|
|
77
|
+
*/
|
|
78
|
+
export type PropsForRenderer = [...Required<Parameters<Renderer>>] extends [unknown, infer Props]
|
|
79
|
+
? Props
|
|
80
|
+
: unknown
|
|
81
|
+
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
83
|
+
export type Layout<T = Record<string, any>> = (props: T) => any
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Interface for getting context variables.
|
|
87
|
+
*
|
|
88
|
+
* @template E - Environment type.
|
|
89
|
+
*/
|
|
90
|
+
interface Get<E extends Env> {
|
|
91
|
+
<Key extends keyof E['Variables']>(key: Key): E['Variables'][Key]
|
|
92
|
+
<Key extends keyof ContextVariableMap>(key: Key): ContextVariableMap[Key]
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Interface for setting context variables.
|
|
97
|
+
*
|
|
98
|
+
* @template E - Environment type.
|
|
99
|
+
*/
|
|
100
|
+
interface Set<E extends Env> {
|
|
101
|
+
<Key extends keyof E['Variables']>(key: Key, value: E['Variables'][Key]): void
|
|
102
|
+
<Key extends keyof ContextVariableMap>(key: Key, value: ContextVariableMap[Key]): void
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Interface for creating a new response.
|
|
107
|
+
*/
|
|
108
|
+
interface NewResponse {
|
|
109
|
+
(data: Data | null, status?: StatusCode, headers?: HeaderRecord): Response
|
|
110
|
+
(data: Data | null, init?: ResponseOrInit): Response
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Interface for responding with a body.
|
|
115
|
+
*/
|
|
116
|
+
interface BodyRespond {
|
|
117
|
+
// if we return content, only allow the status codes that allow for returning the body
|
|
118
|
+
<T extends Data, U extends ContentfulStatusCode>(
|
|
119
|
+
data: T,
|
|
120
|
+
status?: U,
|
|
121
|
+
headers?: HeaderRecord
|
|
122
|
+
): Response & TypedResponse<T, U, 'body'>
|
|
123
|
+
<T extends Data, U extends ContentfulStatusCode>(
|
|
124
|
+
data: T,
|
|
125
|
+
init?: ResponseOrInit<U>
|
|
126
|
+
): Response & TypedResponse<T, U, 'body'>
|
|
127
|
+
<T extends null, U extends StatusCode>(
|
|
128
|
+
data: T,
|
|
129
|
+
status?: U,
|
|
130
|
+
headers?: HeaderRecord
|
|
131
|
+
): Response & TypedResponse<null, U, 'body'>
|
|
132
|
+
<T extends null, U extends StatusCode>(
|
|
133
|
+
data: T,
|
|
134
|
+
init?: ResponseOrInit<U>
|
|
135
|
+
): Response & TypedResponse<null, U, 'body'>
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Interface for responding with text.
|
|
140
|
+
*
|
|
141
|
+
* @interface TextRespond
|
|
142
|
+
* @template T - The type of the text content.
|
|
143
|
+
* @template U - The type of the status code.
|
|
144
|
+
*
|
|
145
|
+
* @param {T} text - The text content to be included in the response.
|
|
146
|
+
* @param {U} [status] - An optional status code for the response.
|
|
147
|
+
* @param {HeaderRecord} [headers] - An optional record of headers to include in the response.
|
|
148
|
+
*
|
|
149
|
+
* @returns {Response & TypedResponse<T, U, 'text'>} - The response after rendering the text content, typed with the provided text and status code types.
|
|
150
|
+
*/
|
|
151
|
+
interface TextRespond {
|
|
152
|
+
<T extends string, U extends ContentfulStatusCode = ContentfulStatusCode>(
|
|
153
|
+
text: T,
|
|
154
|
+
status?: U,
|
|
155
|
+
headers?: HeaderRecord
|
|
156
|
+
): Response & TypedResponse<T, U, 'text'>
|
|
157
|
+
<T extends string, U extends ContentfulStatusCode = ContentfulStatusCode>(
|
|
158
|
+
text: T,
|
|
159
|
+
init?: ResponseOrInit<U>
|
|
160
|
+
): Response & TypedResponse<T, U, 'text'>
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Interface for responding with JSON.
|
|
165
|
+
*
|
|
166
|
+
* @interface JSONRespond
|
|
167
|
+
* @template T - The type of the JSON value or simplified unknown type.
|
|
168
|
+
* @template U - The type of the status code.
|
|
169
|
+
*
|
|
170
|
+
* @param {T} object - The JSON object to be included in the response.
|
|
171
|
+
* @param {U} [status] - An optional status code for the response.
|
|
172
|
+
* @param {HeaderRecord} [headers] - An optional record of headers to include in the response.
|
|
173
|
+
*
|
|
174
|
+
* @returns {JSONRespondReturn<T, U>} - The response after rendering the JSON object, typed with the provided object and status code types.
|
|
175
|
+
*/
|
|
176
|
+
interface JSONRespond {
|
|
177
|
+
<
|
|
178
|
+
T extends JSONValue | {} | InvalidJSONValue,
|
|
179
|
+
U extends ContentfulStatusCode = ContentfulStatusCode,
|
|
180
|
+
>(
|
|
181
|
+
object: T,
|
|
182
|
+
status?: U,
|
|
183
|
+
headers?: HeaderRecord
|
|
184
|
+
): JSONRespondReturn<T, U>
|
|
185
|
+
<
|
|
186
|
+
T extends JSONValue | {} | InvalidJSONValue,
|
|
187
|
+
U extends ContentfulStatusCode = ContentfulStatusCode,
|
|
188
|
+
>(
|
|
189
|
+
object: T,
|
|
190
|
+
init?: ResponseOrInit<U>
|
|
191
|
+
): JSONRespondReturn<T, U>
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* @template T - The type of the JSON value or simplified unknown type.
|
|
196
|
+
* @template U - The type of the status code.
|
|
197
|
+
*
|
|
198
|
+
* @returns {Response & TypedResponse<JSONParsed<T>, U, 'json'>} - The response after rendering the JSON object, typed with the provided object and status code types.
|
|
199
|
+
*/
|
|
200
|
+
type JSONRespondReturn<
|
|
201
|
+
T extends JSONValue | {} | InvalidJSONValue,
|
|
202
|
+
U extends ContentfulStatusCode,
|
|
203
|
+
> = Response & TypedResponse<JSONParsed<T>, U, 'json'>
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Interface representing a function that responds with HTML content.
|
|
207
|
+
*
|
|
208
|
+
* @param html - The HTML content to respond with, which can be a string or a Promise that resolves to a string.
|
|
209
|
+
* @param status - (Optional) The HTTP status code for the response.
|
|
210
|
+
* @param headers - (Optional) A record of headers to include in the response.
|
|
211
|
+
* @param init - (Optional) The response initialization object.
|
|
212
|
+
*
|
|
213
|
+
* @returns A Response object or a Promise that resolves to a Response object.
|
|
214
|
+
*/
|
|
215
|
+
interface HTMLRespond {
|
|
216
|
+
<T extends string | Promise<string>>(
|
|
217
|
+
html: T,
|
|
218
|
+
status?: ContentfulStatusCode,
|
|
219
|
+
headers?: HeaderRecord
|
|
220
|
+
): T extends string ? Response : Promise<Response>
|
|
221
|
+
<T extends string | Promise<string>>(
|
|
222
|
+
html: T,
|
|
223
|
+
init?: ResponseOrInit<ContentfulStatusCode>
|
|
224
|
+
): T extends string ? Response : Promise<Response>
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Options for configuring the context.
|
|
229
|
+
*
|
|
230
|
+
* @template E - Environment type.
|
|
231
|
+
*/
|
|
232
|
+
type ContextOptions<E extends Env> = {
|
|
233
|
+
/**
|
|
234
|
+
* Bindings for the environment.
|
|
235
|
+
*/
|
|
236
|
+
env: E['Bindings']
|
|
237
|
+
/**
|
|
238
|
+
* Execution context for the request.
|
|
239
|
+
*/
|
|
240
|
+
executionCtx?: FetchEventLike | ExecutionContext | undefined
|
|
241
|
+
/**
|
|
242
|
+
* Handler for not found responses.
|
|
243
|
+
*/
|
|
244
|
+
notFoundHandler?: NotFoundHandler<E>
|
|
245
|
+
matchResult?: Result<[H, RouterRoute]>
|
|
246
|
+
path?: string
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
interface SetHeadersOptions {
|
|
250
|
+
append?: boolean
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
interface SetHeaders {
|
|
254
|
+
(name: 'Content-Type', value?: BaseMime, options?: SetHeadersOptions): void
|
|
255
|
+
(name: ResponseHeader, value?: string, options?: SetHeadersOptions): void
|
|
256
|
+
(name: string, value?: string, options?: SetHeadersOptions): void
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
type ResponseHeadersInit =
|
|
260
|
+
| [string, string][]
|
|
261
|
+
| Record<'Content-Type', BaseMime>
|
|
262
|
+
| Record<ResponseHeader, string>
|
|
263
|
+
| Record<string, string>
|
|
264
|
+
| Headers
|
|
265
|
+
|
|
266
|
+
interface ResponseInit<T extends StatusCode = StatusCode> {
|
|
267
|
+
headers?: ResponseHeadersInit
|
|
268
|
+
status?: T
|
|
269
|
+
statusText?: string
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
type ResponseOrInit<T extends StatusCode = StatusCode> = ResponseInit<T> | Response
|
|
273
|
+
|
|
274
|
+
export const TEXT_PLAIN = 'text/plain; charset=UTF-8'
|
|
275
|
+
|
|
276
|
+
const setDefaultContentType = (contentType: string, headers?: HeaderRecord): HeaderRecord => {
|
|
277
|
+
return {
|
|
278
|
+
'Content-Type': contentType,
|
|
279
|
+
...headers,
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export class Context<
|
|
284
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
285
|
+
E extends Env = any,
|
|
286
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
287
|
+
P extends string = any,
|
|
288
|
+
I extends Input = {},
|
|
289
|
+
> {
|
|
290
|
+
#rawRequest: Request
|
|
291
|
+
#req: HonoRequest<P, I['out']> | undefined
|
|
292
|
+
/**
|
|
293
|
+
* `.env` can get bindings (environment variables, secrets, KV namespaces, D1 database, R2 bucket etc.) in Cloudflare Workers.
|
|
294
|
+
*
|
|
295
|
+
* @see {@link https://hono.dev/docs/api/context#env}
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* ```ts
|
|
299
|
+
* // Environment object for Cloudflare Workers
|
|
300
|
+
* app.get('*', async c => {
|
|
301
|
+
* const counter = c.env.COUNTER
|
|
302
|
+
* })
|
|
303
|
+
* ```
|
|
304
|
+
*/
|
|
305
|
+
env: E['Bindings'] = {}
|
|
306
|
+
#var: Map<unknown, unknown> | undefined
|
|
307
|
+
finalized: boolean = false
|
|
308
|
+
/**
|
|
309
|
+
* `.error` can get the error object from the middleware if the Handler throws an error.
|
|
310
|
+
*
|
|
311
|
+
* @see {@link https://hono.dev/docs/api/context#error}
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```ts
|
|
315
|
+
* app.use('*', async (c, next) => {
|
|
316
|
+
* await next()
|
|
317
|
+
* if (c.error) {
|
|
318
|
+
* // do something...
|
|
319
|
+
* }
|
|
320
|
+
* })
|
|
321
|
+
* ```
|
|
322
|
+
*/
|
|
323
|
+
error: Error | undefined
|
|
324
|
+
|
|
325
|
+
#status: StatusCode | undefined
|
|
326
|
+
#executionCtx: FetchEventLike | ExecutionContext | undefined
|
|
327
|
+
#res: Response | undefined
|
|
328
|
+
#layout: Layout<PropsForRenderer & { Layout: Layout }> | undefined
|
|
329
|
+
#renderer: Renderer | undefined
|
|
330
|
+
#notFoundHandler: NotFoundHandler<E> | undefined
|
|
331
|
+
#preparedHeaders: Headers | undefined
|
|
332
|
+
|
|
333
|
+
#matchResult: Result<[H, RouterRoute]> | undefined
|
|
334
|
+
#path: string | undefined
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Creates an instance of the Context class.
|
|
338
|
+
*
|
|
339
|
+
* @param req - The Request object.
|
|
340
|
+
* @param options - Optional configuration options for the context.
|
|
341
|
+
*/
|
|
342
|
+
constructor(req: Request, options?: ContextOptions<E>) {
|
|
343
|
+
this.#rawRequest = req
|
|
344
|
+
if (options) {
|
|
345
|
+
this.#executionCtx = options.executionCtx
|
|
346
|
+
this.env = options.env
|
|
347
|
+
this.#notFoundHandler = options.notFoundHandler
|
|
348
|
+
this.#path = options.path
|
|
349
|
+
this.#matchResult = options.matchResult
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* `.req` is the instance of {@link HonoRequest}.
|
|
355
|
+
*/
|
|
356
|
+
get req(): HonoRequest<P, I['out']> {
|
|
357
|
+
this.#req ??= new HonoRequest(this.#rawRequest, this.#path, this.#matchResult)
|
|
358
|
+
return this.#req
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* @see {@link https://hono.dev/docs/api/context#event}
|
|
363
|
+
* The FetchEvent associated with the current request.
|
|
364
|
+
*
|
|
365
|
+
* @throws Will throw an error if the context does not have a FetchEvent.
|
|
366
|
+
*/
|
|
367
|
+
get event(): FetchEventLike {
|
|
368
|
+
if (this.#executionCtx && 'respondWith' in this.#executionCtx) {
|
|
369
|
+
return this.#executionCtx
|
|
370
|
+
} else {
|
|
371
|
+
throw Error('This context has no FetchEvent')
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* @see {@link https://hono.dev/docs/api/context#executionctx}
|
|
377
|
+
* The ExecutionContext associated with the current request.
|
|
378
|
+
*
|
|
379
|
+
* @throws Will throw an error if the context does not have an ExecutionContext.
|
|
380
|
+
*/
|
|
381
|
+
get executionCtx(): ExecutionContext {
|
|
382
|
+
if (this.#executionCtx) {
|
|
383
|
+
return this.#executionCtx as ExecutionContext
|
|
384
|
+
} else {
|
|
385
|
+
throw Error('This context has no ExecutionContext')
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* @see {@link https://hono.dev/docs/api/context#res}
|
|
391
|
+
* The Response object for the current request.
|
|
392
|
+
*/
|
|
393
|
+
get res(): Response {
|
|
394
|
+
return (this.#res ||= new Response(null, {
|
|
395
|
+
headers: (this.#preparedHeaders ??= new Headers()),
|
|
396
|
+
}))
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Sets the Response object for the current request.
|
|
401
|
+
*
|
|
402
|
+
* @param _res - The Response object to set.
|
|
403
|
+
*/
|
|
404
|
+
set res(_res: Response | undefined) {
|
|
405
|
+
if (this.#res && _res) {
|
|
406
|
+
_res = new Response(_res.body, _res)
|
|
407
|
+
for (const [k, v] of this.#res.headers.entries()) {
|
|
408
|
+
if (k === 'content-type') {
|
|
409
|
+
continue
|
|
410
|
+
}
|
|
411
|
+
if (k === 'set-cookie') {
|
|
412
|
+
const cookies = this.#res.headers.getSetCookie()
|
|
413
|
+
_res.headers.delete('set-cookie')
|
|
414
|
+
for (const cookie of cookies) {
|
|
415
|
+
_res.headers.append('set-cookie', cookie)
|
|
416
|
+
}
|
|
417
|
+
} else {
|
|
418
|
+
_res.headers.set(k, v)
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
this.#res = _res
|
|
423
|
+
this.finalized = true
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* `.render()` can create a response within a layout.
|
|
428
|
+
*
|
|
429
|
+
* @see {@link https://hono.dev/docs/api/context#render-setrenderer}
|
|
430
|
+
*
|
|
431
|
+
* @example
|
|
432
|
+
* ```ts
|
|
433
|
+
* app.get('/', (c) => {
|
|
434
|
+
* return c.render('Hello!')
|
|
435
|
+
* })
|
|
436
|
+
* ```
|
|
437
|
+
*/
|
|
438
|
+
render: Renderer = (...args) => {
|
|
439
|
+
this.#renderer ??= (content: string | Promise<string>) => this.html(content)
|
|
440
|
+
return this.#renderer(...args)
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Sets the layout for the response.
|
|
445
|
+
*
|
|
446
|
+
* @param layout - The layout to set.
|
|
447
|
+
* @returns The layout function.
|
|
448
|
+
*/
|
|
449
|
+
setLayout = (
|
|
450
|
+
layout: Layout<PropsForRenderer & { Layout: Layout }>
|
|
451
|
+
): Layout<
|
|
452
|
+
PropsForRenderer & {
|
|
453
|
+
Layout: Layout
|
|
454
|
+
}
|
|
455
|
+
> => (this.#layout = layout)
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Gets the current layout for the response.
|
|
459
|
+
*
|
|
460
|
+
* @returns The current layout function.
|
|
461
|
+
*/
|
|
462
|
+
getLayout = (): Layout<PropsForRenderer & { Layout: Layout }> | undefined => this.#layout
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* `.setRenderer()` can set the layout in the custom middleware.
|
|
466
|
+
*
|
|
467
|
+
* @see {@link https://hono.dev/docs/api/context#render-setrenderer}
|
|
468
|
+
*
|
|
469
|
+
* @example
|
|
470
|
+
* ```tsx
|
|
471
|
+
* app.use('*', async (c, next) => {
|
|
472
|
+
* c.setRenderer((content) => {
|
|
473
|
+
* return c.html(
|
|
474
|
+
* <html>
|
|
475
|
+
* <body>
|
|
476
|
+
* <p>{content}</p>
|
|
477
|
+
* </body>
|
|
478
|
+
* </html>
|
|
479
|
+
* )
|
|
480
|
+
* })
|
|
481
|
+
* await next()
|
|
482
|
+
* })
|
|
483
|
+
* ```
|
|
484
|
+
*/
|
|
485
|
+
setRenderer = (renderer: Renderer): void => {
|
|
486
|
+
this.#renderer = renderer
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* `.header()` can set headers.
|
|
491
|
+
*
|
|
492
|
+
* @see {@link https://hono.dev/docs/api/context#header}
|
|
493
|
+
*
|
|
494
|
+
* @example
|
|
495
|
+
* ```ts
|
|
496
|
+
* app.get('/welcome', (c) => {
|
|
497
|
+
* // Set headers
|
|
498
|
+
* c.header('X-Message', 'Hello!')
|
|
499
|
+
* c.header('Content-Type', 'text/plain')
|
|
500
|
+
*
|
|
501
|
+
* return c.body('Thank you for coming')
|
|
502
|
+
* })
|
|
503
|
+
* ```
|
|
504
|
+
*/
|
|
505
|
+
header: SetHeaders = (name, value, options): void => {
|
|
506
|
+
if (this.finalized) {
|
|
507
|
+
this.#res = new Response((this.#res as Response).body, this.#res)
|
|
508
|
+
}
|
|
509
|
+
const headers = this.#res ? this.#res.headers : (this.#preparedHeaders ??= new Headers())
|
|
510
|
+
if (value === undefined) {
|
|
511
|
+
headers.delete(name)
|
|
512
|
+
} else if (options?.append) {
|
|
513
|
+
headers.append(name, value)
|
|
514
|
+
} else {
|
|
515
|
+
headers.set(name, value)
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
status = (status: StatusCode): void => {
|
|
520
|
+
this.#status = status
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* `.set()` can set the value specified by the key.
|
|
525
|
+
*
|
|
526
|
+
* @see {@link https://hono.dev/docs/api/context#set-get}
|
|
527
|
+
*
|
|
528
|
+
* @example
|
|
529
|
+
* ```ts
|
|
530
|
+
* app.use('*', async (c, next) => {
|
|
531
|
+
* c.set('message', 'Hono is hot!!')
|
|
532
|
+
* await next()
|
|
533
|
+
* })
|
|
534
|
+
* ```
|
|
535
|
+
*/
|
|
536
|
+
set: Set<
|
|
537
|
+
IsAny<E> extends true
|
|
538
|
+
? {
|
|
539
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
540
|
+
Variables: ContextVariableMap & Record<string, any>
|
|
541
|
+
}
|
|
542
|
+
: E
|
|
543
|
+
> = (key: string, value: unknown) => {
|
|
544
|
+
this.#var ??= new Map()
|
|
545
|
+
this.#var.set(key, value)
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* `.get()` can use the value specified by the key.
|
|
550
|
+
*
|
|
551
|
+
* @see {@link https://hono.dev/docs/api/context#set-get}
|
|
552
|
+
*
|
|
553
|
+
* @example
|
|
554
|
+
* ```ts
|
|
555
|
+
* app.get('/', (c) => {
|
|
556
|
+
* const message = c.get('message')
|
|
557
|
+
* return c.text(`The message is "${message}"`)
|
|
558
|
+
* })
|
|
559
|
+
* ```
|
|
560
|
+
*/
|
|
561
|
+
get: Get<
|
|
562
|
+
IsAny<E> extends true
|
|
563
|
+
? {
|
|
564
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
565
|
+
Variables: ContextVariableMap & Record<string, any>
|
|
566
|
+
}
|
|
567
|
+
: E
|
|
568
|
+
> = (key: string) => {
|
|
569
|
+
return this.#var ? this.#var.get(key) : undefined
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* `.var` can access the value of a variable.
|
|
574
|
+
*
|
|
575
|
+
* @see {@link https://hono.dev/docs/api/context#var}
|
|
576
|
+
*
|
|
577
|
+
* @example
|
|
578
|
+
* ```ts
|
|
579
|
+
* const result = c.var.client.oneMethod()
|
|
580
|
+
* ```
|
|
581
|
+
*/
|
|
582
|
+
// c.var.propName is a read-only
|
|
583
|
+
get var(): Readonly<
|
|
584
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
585
|
+
ContextVariableMap & (IsAny<E['Variables']> extends true ? Record<string, any> : E['Variables'])
|
|
586
|
+
> {
|
|
587
|
+
if (!this.#var) {
|
|
588
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
589
|
+
return {} as any
|
|
590
|
+
}
|
|
591
|
+
return Object.fromEntries(this.#var)
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
#newResponse(
|
|
595
|
+
data: Data | null,
|
|
596
|
+
arg?: StatusCode | ResponseOrInit,
|
|
597
|
+
headers?: HeaderRecord
|
|
598
|
+
): Response {
|
|
599
|
+
const responseHeaders = this.#res
|
|
600
|
+
? new Headers(this.#res.headers)
|
|
601
|
+
: (this.#preparedHeaders ?? new Headers())
|
|
602
|
+
|
|
603
|
+
if (typeof arg === 'object' && 'headers' in arg) {
|
|
604
|
+
const argHeaders = arg.headers instanceof Headers ? arg.headers : new Headers(arg.headers)
|
|
605
|
+
for (const [key, value] of argHeaders) {
|
|
606
|
+
if (key.toLowerCase() === 'set-cookie') {
|
|
607
|
+
responseHeaders.append(key, value)
|
|
608
|
+
} else {
|
|
609
|
+
responseHeaders.set(key, value)
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
if (headers) {
|
|
615
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
616
|
+
if (typeof v === 'string') {
|
|
617
|
+
responseHeaders.set(k, v)
|
|
618
|
+
} else {
|
|
619
|
+
responseHeaders.delete(k)
|
|
620
|
+
for (const v2 of v) {
|
|
621
|
+
responseHeaders.append(k, v2)
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
const status = typeof arg === 'number' ? arg : (arg?.status ?? this.#status)
|
|
628
|
+
return new Response(data, { status, headers: responseHeaders })
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
newResponse: NewResponse = (...args) => this.#newResponse(...(args as Parameters<NewResponse>))
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* `.body()` can return the HTTP response.
|
|
635
|
+
* You can set headers with `.header()` and set HTTP status code with `.status`.
|
|
636
|
+
* This can also be set in `.text()`, `.json()` and so on.
|
|
637
|
+
*
|
|
638
|
+
* @see {@link https://hono.dev/docs/api/context#body}
|
|
639
|
+
*
|
|
640
|
+
* @example
|
|
641
|
+
* ```ts
|
|
642
|
+
* app.get('/welcome', (c) => {
|
|
643
|
+
* // Set headers
|
|
644
|
+
* c.header('X-Message', 'Hello!')
|
|
645
|
+
* c.header('Content-Type', 'text/plain')
|
|
646
|
+
* // Set HTTP status code
|
|
647
|
+
* c.status(201)
|
|
648
|
+
*
|
|
649
|
+
* // Return the response body
|
|
650
|
+
* return c.body('Thank you for coming')
|
|
651
|
+
* })
|
|
652
|
+
* ```
|
|
653
|
+
*/
|
|
654
|
+
body: BodyRespond = (
|
|
655
|
+
data: Data | null,
|
|
656
|
+
arg?: StatusCode | RequestInit,
|
|
657
|
+
headers?: HeaderRecord
|
|
658
|
+
): ReturnType<BodyRespond> => this.#newResponse(data, arg, headers) as ReturnType<BodyRespond>
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* `.text()` can render text as `Content-Type:text/plain`.
|
|
662
|
+
*
|
|
663
|
+
* @see {@link https://hono.dev/docs/api/context#text}
|
|
664
|
+
*
|
|
665
|
+
* @example
|
|
666
|
+
* ```ts
|
|
667
|
+
* app.get('/say', (c) => {
|
|
668
|
+
* return c.text('Hello!')
|
|
669
|
+
* })
|
|
670
|
+
* ```
|
|
671
|
+
*/
|
|
672
|
+
text: TextRespond = (
|
|
673
|
+
text: string,
|
|
674
|
+
arg?: ContentfulStatusCode | ResponseOrInit,
|
|
675
|
+
headers?: HeaderRecord
|
|
676
|
+
): ReturnType<TextRespond> => {
|
|
677
|
+
return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized
|
|
678
|
+
? (new Response(text) as ReturnType<TextRespond>)
|
|
679
|
+
: (this.#newResponse(
|
|
680
|
+
text,
|
|
681
|
+
arg,
|
|
682
|
+
setDefaultContentType(TEXT_PLAIN, headers)
|
|
683
|
+
) as ReturnType<TextRespond>)
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* `.json()` can render JSON as `Content-Type:application/json`.
|
|
688
|
+
*
|
|
689
|
+
* @see {@link https://hono.dev/docs/api/context#json}
|
|
690
|
+
*
|
|
691
|
+
* @example
|
|
692
|
+
* ```ts
|
|
693
|
+
* app.get('/api', (c) => {
|
|
694
|
+
* return c.json({ message: 'Hello!' })
|
|
695
|
+
* })
|
|
696
|
+
* ```
|
|
697
|
+
*/
|
|
698
|
+
json: JSONRespond = <
|
|
699
|
+
T extends JSONValue | {} | InvalidJSONValue,
|
|
700
|
+
U extends ContentfulStatusCode = ContentfulStatusCode,
|
|
701
|
+
>(
|
|
702
|
+
object: T,
|
|
703
|
+
arg?: U | ResponseOrInit<U>,
|
|
704
|
+
headers?: HeaderRecord
|
|
705
|
+
): JSONRespondReturn<T, U> => {
|
|
706
|
+
return this.#newResponse(
|
|
707
|
+
JSON.stringify(object),
|
|
708
|
+
arg,
|
|
709
|
+
setDefaultContentType('application/json', headers)
|
|
710
|
+
) /* eslint-disable @typescript-eslint/no-explicit-any */ as any
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
html: HTMLRespond = (
|
|
714
|
+
html: string | Promise<string>,
|
|
715
|
+
arg?: ContentfulStatusCode | ResponseOrInit<ContentfulStatusCode>,
|
|
716
|
+
headers?: HeaderRecord
|
|
717
|
+
): Response | Promise<Response> => {
|
|
718
|
+
const res = (html: string) =>
|
|
719
|
+
this.#newResponse(html, arg, setDefaultContentType('text/html; charset=UTF-8', headers))
|
|
720
|
+
return typeof html === 'object'
|
|
721
|
+
? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res)
|
|
722
|
+
: res(html)
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* `.redirect()` can Redirect, default status code is 302.
|
|
727
|
+
*
|
|
728
|
+
* @see {@link https://hono.dev/docs/api/context#redirect}
|
|
729
|
+
*
|
|
730
|
+
* @example
|
|
731
|
+
* ```ts
|
|
732
|
+
* app.get('/redirect', (c) => {
|
|
733
|
+
* return c.redirect('/')
|
|
734
|
+
* })
|
|
735
|
+
* app.get('/redirect-permanently', (c) => {
|
|
736
|
+
* return c.redirect('/', 301)
|
|
737
|
+
* })
|
|
738
|
+
* ```
|
|
739
|
+
*/
|
|
740
|
+
redirect = <T extends RedirectStatusCode = 302>(
|
|
741
|
+
location: string | URL,
|
|
742
|
+
status?: T
|
|
743
|
+
): Response & TypedResponse<undefined, T, 'redirect'> => {
|
|
744
|
+
const locationString = String(location)
|
|
745
|
+
this.header(
|
|
746
|
+
'Location',
|
|
747
|
+
// Multibyes should be encoded
|
|
748
|
+
// eslint-disable-next-line no-control-regex
|
|
749
|
+
!/[^\x00-\xFF]/.test(locationString) ? locationString : encodeURI(locationString)
|
|
750
|
+
)
|
|
751
|
+
return this.newResponse(null, status ?? 302) as any
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* `.notFound()` can return the Not Found Response.
|
|
756
|
+
*
|
|
757
|
+
* @see {@link https://hono.dev/docs/api/context#notfound}
|
|
758
|
+
*
|
|
759
|
+
* @example
|
|
760
|
+
* ```ts
|
|
761
|
+
* app.get('/notfound', (c) => {
|
|
762
|
+
* return c.notFound()
|
|
763
|
+
* })
|
|
764
|
+
* ```
|
|
765
|
+
*/
|
|
766
|
+
notFound = (): ReturnType<NotFoundHandler> => {
|
|
767
|
+
this.#notFoundHandler ??= () => new Response()
|
|
768
|
+
return this.#notFoundHandler(this)
|
|
769
|
+
}
|
|
770
|
+
}
|