@kerebron/extension-server-hono 0.4.7 → 0.4.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/esm/HonoYjsMemAdapter.d.ts +0 -1
- package/esm/HonoYjsMemAdapter.d.ts.map +1 -1
- package/esm/HonoYjsMemAdapter.js +31 -79
- package/esm/deps/jsr.io/@hono/hono/4.10.7/src/context.js +309 -412
- package/esm/deps/jsr.io/@hono/hono/4.10.7/src/helper/websocket/index.js +9 -42
- package/esm/deps/jsr.io/@hono/hono/4.10.7/src/hono-base.js +192 -299
- package/esm/deps/jsr.io/@hono/hono/4.10.7/src/http-exception.js +2 -12
- package/esm/deps/jsr.io/@hono/hono/4.10.7/src/request.js +82 -125
- package/esm/mod.d.ts +0 -1
- package/esm/mod.d.ts.map +1 -1
- package/esm/mod.js +1 -1
- package/package.json +1 -1
- package/esm/_dnt.polyfills.d.ts +0 -7
- package/esm/_dnt.polyfills.d.ts.map +0 -1
- package/esm/_dnt.polyfills.js +0 -1
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
-
};
|
|
7
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
-
};
|
|
12
|
-
var _Context_instances, _Context_rawRequest, _Context_req, _Context_var, _Context_status, _Context_executionCtx, _Context_res, _Context_layout, _Context_renderer, _Context_notFoundHandler, _Context_preparedHeaders, _Context_matchResult, _Context_path, _Context_newResponse;
|
|
13
1
|
import { HonoRequest } from './request.js';
|
|
14
2
|
import { HtmlEscapedCallbackPhase, resolveCallback } from './utils/html.js';
|
|
15
3
|
export const TEXT_PLAIN = 'text/plain; charset=UTF-8';
|
|
@@ -20,6 +8,49 @@ const setDefaultContentType = (contentType, headers) => {
|
|
|
20
8
|
};
|
|
21
9
|
};
|
|
22
10
|
export class Context {
|
|
11
|
+
#rawRequest;
|
|
12
|
+
#req;
|
|
13
|
+
/**
|
|
14
|
+
* `.env` can get bindings (environment variables, secrets, KV namespaces, D1 database, R2 bucket etc.) in Cloudflare Workers.
|
|
15
|
+
*
|
|
16
|
+
* @see {@link https://hono.dev/docs/api/context#env}
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* // Environment object for Cloudflare Workers
|
|
21
|
+
* app.get('*', async c => {
|
|
22
|
+
* const counter = c.env.COUNTER
|
|
23
|
+
* })
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
env = {};
|
|
27
|
+
#var;
|
|
28
|
+
finalized = false;
|
|
29
|
+
/**
|
|
30
|
+
* `.error` can get the error object from the middleware if the Handler throws an error.
|
|
31
|
+
*
|
|
32
|
+
* @see {@link https://hono.dev/docs/api/context#error}
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* app.use('*', async (c, next) => {
|
|
37
|
+
* await next()
|
|
38
|
+
* if (c.error) {
|
|
39
|
+
* // do something...
|
|
40
|
+
* }
|
|
41
|
+
* })
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
error;
|
|
45
|
+
#status;
|
|
46
|
+
#executionCtx;
|
|
47
|
+
#res;
|
|
48
|
+
#layout;
|
|
49
|
+
#renderer;
|
|
50
|
+
#notFoundHandler;
|
|
51
|
+
#preparedHeaders;
|
|
52
|
+
#matchResult;
|
|
53
|
+
#path;
|
|
23
54
|
/**
|
|
24
55
|
* Creates an instance of the Context class.
|
|
25
56
|
*
|
|
@@ -27,375 +58,21 @@ export class Context {
|
|
|
27
58
|
* @param options - Optional configuration options for the context.
|
|
28
59
|
*/
|
|
29
60
|
constructor(req, options) {
|
|
30
|
-
|
|
31
|
-
_Context_rawRequest.set(this, void 0);
|
|
32
|
-
_Context_req.set(this, void 0);
|
|
33
|
-
/**
|
|
34
|
-
* `.env` can get bindings (environment variables, secrets, KV namespaces, D1 database, R2 bucket etc.) in Cloudflare Workers.
|
|
35
|
-
*
|
|
36
|
-
* @see {@link https://hono.dev/docs/api/context#env}
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```ts
|
|
40
|
-
* // Environment object for Cloudflare Workers
|
|
41
|
-
* app.get('*', async c => {
|
|
42
|
-
* const counter = c.env.COUNTER
|
|
43
|
-
* })
|
|
44
|
-
* ```
|
|
45
|
-
*/
|
|
46
|
-
Object.defineProperty(this, "env", {
|
|
47
|
-
enumerable: true,
|
|
48
|
-
configurable: true,
|
|
49
|
-
writable: true,
|
|
50
|
-
value: {}
|
|
51
|
-
});
|
|
52
|
-
_Context_var.set(this, void 0);
|
|
53
|
-
Object.defineProperty(this, "finalized", {
|
|
54
|
-
enumerable: true,
|
|
55
|
-
configurable: true,
|
|
56
|
-
writable: true,
|
|
57
|
-
value: false
|
|
58
|
-
});
|
|
59
|
-
/**
|
|
60
|
-
* `.error` can get the error object from the middleware if the Handler throws an error.
|
|
61
|
-
*
|
|
62
|
-
* @see {@link https://hono.dev/docs/api/context#error}
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
* ```ts
|
|
66
|
-
* app.use('*', async (c, next) => {
|
|
67
|
-
* await next()
|
|
68
|
-
* if (c.error) {
|
|
69
|
-
* // do something...
|
|
70
|
-
* }
|
|
71
|
-
* })
|
|
72
|
-
* ```
|
|
73
|
-
*/
|
|
74
|
-
Object.defineProperty(this, "error", {
|
|
75
|
-
enumerable: true,
|
|
76
|
-
configurable: true,
|
|
77
|
-
writable: true,
|
|
78
|
-
value: void 0
|
|
79
|
-
});
|
|
80
|
-
_Context_status.set(this, void 0);
|
|
81
|
-
_Context_executionCtx.set(this, void 0);
|
|
82
|
-
_Context_res.set(this, void 0);
|
|
83
|
-
_Context_layout.set(this, void 0);
|
|
84
|
-
_Context_renderer.set(this, void 0);
|
|
85
|
-
_Context_notFoundHandler.set(this, void 0);
|
|
86
|
-
_Context_preparedHeaders.set(this, void 0);
|
|
87
|
-
_Context_matchResult.set(this, void 0);
|
|
88
|
-
_Context_path.set(this, void 0);
|
|
89
|
-
/**
|
|
90
|
-
* `.render()` can create a response within a layout.
|
|
91
|
-
*
|
|
92
|
-
* @see {@link https://hono.dev/docs/api/context#render-setrenderer}
|
|
93
|
-
*
|
|
94
|
-
* @example
|
|
95
|
-
* ```ts
|
|
96
|
-
* app.get('/', (c) => {
|
|
97
|
-
* return c.render('Hello!')
|
|
98
|
-
* })
|
|
99
|
-
* ```
|
|
100
|
-
*/
|
|
101
|
-
Object.defineProperty(this, "render", {
|
|
102
|
-
enumerable: true,
|
|
103
|
-
configurable: true,
|
|
104
|
-
writable: true,
|
|
105
|
-
value: (...args) => {
|
|
106
|
-
__classPrivateFieldSet(this, _Context_renderer, __classPrivateFieldGet(this, _Context_renderer, "f") ?? ((content) => this.html(content)), "f");
|
|
107
|
-
return __classPrivateFieldGet(this, _Context_renderer, "f").call(this, ...args);
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
/**
|
|
111
|
-
* Sets the layout for the response.
|
|
112
|
-
*
|
|
113
|
-
* @param layout - The layout to set.
|
|
114
|
-
* @returns The layout function.
|
|
115
|
-
*/
|
|
116
|
-
Object.defineProperty(this, "setLayout", {
|
|
117
|
-
enumerable: true,
|
|
118
|
-
configurable: true,
|
|
119
|
-
writable: true,
|
|
120
|
-
value: (layout) => (__classPrivateFieldSet(this, _Context_layout, layout, "f"))
|
|
121
|
-
});
|
|
122
|
-
/**
|
|
123
|
-
* Gets the current layout for the response.
|
|
124
|
-
*
|
|
125
|
-
* @returns The current layout function.
|
|
126
|
-
*/
|
|
127
|
-
Object.defineProperty(this, "getLayout", {
|
|
128
|
-
enumerable: true,
|
|
129
|
-
configurable: true,
|
|
130
|
-
writable: true,
|
|
131
|
-
value: () => __classPrivateFieldGet(this, _Context_layout, "f")
|
|
132
|
-
});
|
|
133
|
-
/**
|
|
134
|
-
* `.setRenderer()` can set the layout in the custom middleware.
|
|
135
|
-
*
|
|
136
|
-
* @see {@link https://hono.dev/docs/api/context#render-setrenderer}
|
|
137
|
-
*
|
|
138
|
-
* @example
|
|
139
|
-
* ```tsx
|
|
140
|
-
* app.use('*', async (c, next) => {
|
|
141
|
-
* c.setRenderer((content) => {
|
|
142
|
-
* return c.html(
|
|
143
|
-
* <html>
|
|
144
|
-
* <body>
|
|
145
|
-
* <p>{content}</p>
|
|
146
|
-
* </body>
|
|
147
|
-
* </html>
|
|
148
|
-
* )
|
|
149
|
-
* })
|
|
150
|
-
* await next()
|
|
151
|
-
* })
|
|
152
|
-
* ```
|
|
153
|
-
*/
|
|
154
|
-
Object.defineProperty(this, "setRenderer", {
|
|
155
|
-
enumerable: true,
|
|
156
|
-
configurable: true,
|
|
157
|
-
writable: true,
|
|
158
|
-
value: (renderer) => {
|
|
159
|
-
__classPrivateFieldSet(this, _Context_renderer, renderer, "f");
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
/**
|
|
163
|
-
* `.header()` can set headers.
|
|
164
|
-
*
|
|
165
|
-
* @see {@link https://hono.dev/docs/api/context#header}
|
|
166
|
-
*
|
|
167
|
-
* @example
|
|
168
|
-
* ```ts
|
|
169
|
-
* app.get('/welcome', (c) => {
|
|
170
|
-
* // Set headers
|
|
171
|
-
* c.header('X-Message', 'Hello!')
|
|
172
|
-
* c.header('Content-Type', 'text/plain')
|
|
173
|
-
*
|
|
174
|
-
* return c.body('Thank you for coming')
|
|
175
|
-
* })
|
|
176
|
-
* ```
|
|
177
|
-
*/
|
|
178
|
-
Object.defineProperty(this, "header", {
|
|
179
|
-
enumerable: true,
|
|
180
|
-
configurable: true,
|
|
181
|
-
writable: true,
|
|
182
|
-
value: (name, value, options) => {
|
|
183
|
-
if (this.finalized) {
|
|
184
|
-
__classPrivateFieldSet(this, _Context_res, new Response(__classPrivateFieldGet(this, _Context_res, "f").body, __classPrivateFieldGet(this, _Context_res, "f")), "f");
|
|
185
|
-
}
|
|
186
|
-
const headers = __classPrivateFieldGet(this, _Context_res, "f") ? __classPrivateFieldGet(this, _Context_res, "f").headers : (__classPrivateFieldSet(this, _Context_preparedHeaders, __classPrivateFieldGet(this, _Context_preparedHeaders, "f") ?? new Headers(), "f"));
|
|
187
|
-
if (value === undefined) {
|
|
188
|
-
headers.delete(name);
|
|
189
|
-
}
|
|
190
|
-
else if (options?.append) {
|
|
191
|
-
headers.append(name, value);
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
headers.set(name, value);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
Object.defineProperty(this, "status", {
|
|
199
|
-
enumerable: true,
|
|
200
|
-
configurable: true,
|
|
201
|
-
writable: true,
|
|
202
|
-
value: (status) => {
|
|
203
|
-
__classPrivateFieldSet(this, _Context_status, status, "f");
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
/**
|
|
207
|
-
* `.set()` can set the value specified by the key.
|
|
208
|
-
*
|
|
209
|
-
* @see {@link https://hono.dev/docs/api/context#set-get}
|
|
210
|
-
*
|
|
211
|
-
* @example
|
|
212
|
-
* ```ts
|
|
213
|
-
* app.use('*', async (c, next) => {
|
|
214
|
-
* c.set('message', 'Hono is hot!!')
|
|
215
|
-
* await next()
|
|
216
|
-
* })
|
|
217
|
-
* ```
|
|
218
|
-
*/
|
|
219
|
-
Object.defineProperty(this, "set", {
|
|
220
|
-
enumerable: true,
|
|
221
|
-
configurable: true,
|
|
222
|
-
writable: true,
|
|
223
|
-
value: (key, value) => {
|
|
224
|
-
__classPrivateFieldSet(this, _Context_var, __classPrivateFieldGet(this, _Context_var, "f") ?? new Map(), "f");
|
|
225
|
-
__classPrivateFieldGet(this, _Context_var, "f").set(key, value);
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
/**
|
|
229
|
-
* `.get()` can use the value specified by the key.
|
|
230
|
-
*
|
|
231
|
-
* @see {@link https://hono.dev/docs/api/context#set-get}
|
|
232
|
-
*
|
|
233
|
-
* @example
|
|
234
|
-
* ```ts
|
|
235
|
-
* app.get('/', (c) => {
|
|
236
|
-
* const message = c.get('message')
|
|
237
|
-
* return c.text(`The message is "${message}"`)
|
|
238
|
-
* })
|
|
239
|
-
* ```
|
|
240
|
-
*/
|
|
241
|
-
Object.defineProperty(this, "get", {
|
|
242
|
-
enumerable: true,
|
|
243
|
-
configurable: true,
|
|
244
|
-
writable: true,
|
|
245
|
-
value: (key) => {
|
|
246
|
-
return __classPrivateFieldGet(this, _Context_var, "f") ? __classPrivateFieldGet(this, _Context_var, "f").get(key) : undefined;
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
Object.defineProperty(this, "newResponse", {
|
|
250
|
-
enumerable: true,
|
|
251
|
-
configurable: true,
|
|
252
|
-
writable: true,
|
|
253
|
-
value: (...args) => __classPrivateFieldGet(this, _Context_instances, "m", _Context_newResponse).call(this, ...args)
|
|
254
|
-
});
|
|
255
|
-
/**
|
|
256
|
-
* `.body()` can return the HTTP response.
|
|
257
|
-
* You can set headers with `.header()` and set HTTP status code with `.status`.
|
|
258
|
-
* This can also be set in `.text()`, `.json()` and so on.
|
|
259
|
-
*
|
|
260
|
-
* @see {@link https://hono.dev/docs/api/context#body}
|
|
261
|
-
*
|
|
262
|
-
* @example
|
|
263
|
-
* ```ts
|
|
264
|
-
* app.get('/welcome', (c) => {
|
|
265
|
-
* // Set headers
|
|
266
|
-
* c.header('X-Message', 'Hello!')
|
|
267
|
-
* c.header('Content-Type', 'text/plain')
|
|
268
|
-
* // Set HTTP status code
|
|
269
|
-
* c.status(201)
|
|
270
|
-
*
|
|
271
|
-
* // Return the response body
|
|
272
|
-
* return c.body('Thank you for coming')
|
|
273
|
-
* })
|
|
274
|
-
* ```
|
|
275
|
-
*/
|
|
276
|
-
Object.defineProperty(this, "body", {
|
|
277
|
-
enumerable: true,
|
|
278
|
-
configurable: true,
|
|
279
|
-
writable: true,
|
|
280
|
-
value: (data, arg, headers) => __classPrivateFieldGet(this, _Context_instances, "m", _Context_newResponse).call(this, data, arg, headers)
|
|
281
|
-
});
|
|
282
|
-
/**
|
|
283
|
-
* `.text()` can render text as `Content-Type:text/plain`.
|
|
284
|
-
*
|
|
285
|
-
* @see {@link https://hono.dev/docs/api/context#text}
|
|
286
|
-
*
|
|
287
|
-
* @example
|
|
288
|
-
* ```ts
|
|
289
|
-
* app.get('/say', (c) => {
|
|
290
|
-
* return c.text('Hello!')
|
|
291
|
-
* })
|
|
292
|
-
* ```
|
|
293
|
-
*/
|
|
294
|
-
Object.defineProperty(this, "text", {
|
|
295
|
-
enumerable: true,
|
|
296
|
-
configurable: true,
|
|
297
|
-
writable: true,
|
|
298
|
-
value: (text, arg, headers) => {
|
|
299
|
-
return !__classPrivateFieldGet(this, _Context_preparedHeaders, "f") && !__classPrivateFieldGet(this, _Context_status, "f") && !arg && !headers && !this.finalized
|
|
300
|
-
? new Response(text)
|
|
301
|
-
: __classPrivateFieldGet(this, _Context_instances, "m", _Context_newResponse).call(this, text, arg, setDefaultContentType(TEXT_PLAIN, headers));
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
/**
|
|
305
|
-
* `.json()` can render JSON as `Content-Type:application/json`.
|
|
306
|
-
*
|
|
307
|
-
* @see {@link https://hono.dev/docs/api/context#json}
|
|
308
|
-
*
|
|
309
|
-
* @example
|
|
310
|
-
* ```ts
|
|
311
|
-
* app.get('/api', (c) => {
|
|
312
|
-
* return c.json({ message: 'Hello!' })
|
|
313
|
-
* })
|
|
314
|
-
* ```
|
|
315
|
-
*/
|
|
316
|
-
Object.defineProperty(this, "json", {
|
|
317
|
-
enumerable: true,
|
|
318
|
-
configurable: true,
|
|
319
|
-
writable: true,
|
|
320
|
-
value: (object, arg, headers) => {
|
|
321
|
-
return __classPrivateFieldGet(this, _Context_instances, "m", _Context_newResponse).call(this, JSON.stringify(object), arg, setDefaultContentType('application/json', headers)) /* eslint-disable @typescript-eslint/no-explicit-any */;
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
Object.defineProperty(this, "html", {
|
|
325
|
-
enumerable: true,
|
|
326
|
-
configurable: true,
|
|
327
|
-
writable: true,
|
|
328
|
-
value: (html, arg, headers) => {
|
|
329
|
-
const res = (html) => __classPrivateFieldGet(this, _Context_instances, "m", _Context_newResponse).call(this, html, arg, setDefaultContentType('text/html; charset=UTF-8', headers));
|
|
330
|
-
return typeof html === 'object'
|
|
331
|
-
? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res)
|
|
332
|
-
: res(html);
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
/**
|
|
336
|
-
* `.redirect()` can Redirect, default status code is 302.
|
|
337
|
-
*
|
|
338
|
-
* @see {@link https://hono.dev/docs/api/context#redirect}
|
|
339
|
-
*
|
|
340
|
-
* @example
|
|
341
|
-
* ```ts
|
|
342
|
-
* app.get('/redirect', (c) => {
|
|
343
|
-
* return c.redirect('/')
|
|
344
|
-
* })
|
|
345
|
-
* app.get('/redirect-permanently', (c) => {
|
|
346
|
-
* return c.redirect('/', 301)
|
|
347
|
-
* })
|
|
348
|
-
* ```
|
|
349
|
-
*/
|
|
350
|
-
Object.defineProperty(this, "redirect", {
|
|
351
|
-
enumerable: true,
|
|
352
|
-
configurable: true,
|
|
353
|
-
writable: true,
|
|
354
|
-
value: (location, status) => {
|
|
355
|
-
const locationString = String(location);
|
|
356
|
-
this.header('Location',
|
|
357
|
-
// Multibyes should be encoded
|
|
358
|
-
// eslint-disable-next-line no-control-regex
|
|
359
|
-
!/[^\x00-\xFF]/.test(locationString) ? locationString : encodeURI(locationString));
|
|
360
|
-
return this.newResponse(null, status ?? 302);
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
/**
|
|
364
|
-
* `.notFound()` can return the Not Found Response.
|
|
365
|
-
*
|
|
366
|
-
* @see {@link https://hono.dev/docs/api/context#notfound}
|
|
367
|
-
*
|
|
368
|
-
* @example
|
|
369
|
-
* ```ts
|
|
370
|
-
* app.get('/notfound', (c) => {
|
|
371
|
-
* return c.notFound()
|
|
372
|
-
* })
|
|
373
|
-
* ```
|
|
374
|
-
*/
|
|
375
|
-
Object.defineProperty(this, "notFound", {
|
|
376
|
-
enumerable: true,
|
|
377
|
-
configurable: true,
|
|
378
|
-
writable: true,
|
|
379
|
-
value: () => {
|
|
380
|
-
__classPrivateFieldSet(this, _Context_notFoundHandler, __classPrivateFieldGet(this, _Context_notFoundHandler, "f") ?? (() => new Response()), "f");
|
|
381
|
-
return __classPrivateFieldGet(this, _Context_notFoundHandler, "f").call(this, this);
|
|
382
|
-
}
|
|
383
|
-
});
|
|
384
|
-
__classPrivateFieldSet(this, _Context_rawRequest, req, "f");
|
|
61
|
+
this.#rawRequest = req;
|
|
385
62
|
if (options) {
|
|
386
|
-
|
|
63
|
+
this.#executionCtx = options.executionCtx;
|
|
387
64
|
this.env = options.env;
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
65
|
+
this.#notFoundHandler = options.notFoundHandler;
|
|
66
|
+
this.#path = options.path;
|
|
67
|
+
this.#matchResult = options.matchResult;
|
|
391
68
|
}
|
|
392
69
|
}
|
|
393
70
|
/**
|
|
394
71
|
* `.req` is the instance of {@link HonoRequest}.
|
|
395
72
|
*/
|
|
396
73
|
get req() {
|
|
397
|
-
|
|
398
|
-
return
|
|
74
|
+
this.#req ??= new HonoRequest(this.#rawRequest, this.#path, this.#matchResult);
|
|
75
|
+
return this.#req;
|
|
399
76
|
}
|
|
400
77
|
/**
|
|
401
78
|
* @see {@link https://hono.dev/docs/api/context#event}
|
|
@@ -404,8 +81,8 @@ export class Context {
|
|
|
404
81
|
* @throws Will throw an error if the context does not have a FetchEvent.
|
|
405
82
|
*/
|
|
406
83
|
get event() {
|
|
407
|
-
if (
|
|
408
|
-
return
|
|
84
|
+
if (this.#executionCtx && 'respondWith' in this.#executionCtx) {
|
|
85
|
+
return this.#executionCtx;
|
|
409
86
|
}
|
|
410
87
|
else {
|
|
411
88
|
throw Error('This context has no FetchEvent');
|
|
@@ -418,8 +95,8 @@ export class Context {
|
|
|
418
95
|
* @throws Will throw an error if the context does not have an ExecutionContext.
|
|
419
96
|
*/
|
|
420
97
|
get executionCtx() {
|
|
421
|
-
if (
|
|
422
|
-
return
|
|
98
|
+
if (this.#executionCtx) {
|
|
99
|
+
return this.#executionCtx;
|
|
423
100
|
}
|
|
424
101
|
else {
|
|
425
102
|
throw Error('This context has no ExecutionContext');
|
|
@@ -430,9 +107,9 @@ export class Context {
|
|
|
430
107
|
* The Response object for the current request.
|
|
431
108
|
*/
|
|
432
109
|
get res() {
|
|
433
|
-
return (
|
|
434
|
-
headers: (
|
|
435
|
-
})
|
|
110
|
+
return (this.#res ||= new Response(null, {
|
|
111
|
+
headers: (this.#preparedHeaders ??= new Headers()),
|
|
112
|
+
}));
|
|
436
113
|
}
|
|
437
114
|
/**
|
|
438
115
|
* Sets the Response object for the current request.
|
|
@@ -440,14 +117,14 @@ export class Context {
|
|
|
440
117
|
* @param _res - The Response object to set.
|
|
441
118
|
*/
|
|
442
119
|
set res(_res) {
|
|
443
|
-
if (
|
|
120
|
+
if (this.#res && _res) {
|
|
444
121
|
_res = new Response(_res.body, _res);
|
|
445
|
-
for (const [k, v] of
|
|
122
|
+
for (const [k, v] of this.#res.headers.entries()) {
|
|
446
123
|
if (k === 'content-type') {
|
|
447
124
|
continue;
|
|
448
125
|
}
|
|
449
126
|
if (k === 'set-cookie') {
|
|
450
|
-
const cookies =
|
|
127
|
+
const cookies = this.#res.headers.getSetCookie();
|
|
451
128
|
_res.headers.delete('set-cookie');
|
|
452
129
|
for (const cookie of cookies) {
|
|
453
130
|
_res.headers.append('set-cookie', cookie);
|
|
@@ -458,9 +135,129 @@ export class Context {
|
|
|
458
135
|
}
|
|
459
136
|
}
|
|
460
137
|
}
|
|
461
|
-
|
|
138
|
+
this.#res = _res;
|
|
462
139
|
this.finalized = true;
|
|
463
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* `.render()` can create a response within a layout.
|
|
143
|
+
*
|
|
144
|
+
* @see {@link https://hono.dev/docs/api/context#render-setrenderer}
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* app.get('/', (c) => {
|
|
149
|
+
* return c.render('Hello!')
|
|
150
|
+
* })
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
render = (...args) => {
|
|
154
|
+
this.#renderer ??= (content) => this.html(content);
|
|
155
|
+
return this.#renderer(...args);
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Sets the layout for the response.
|
|
159
|
+
*
|
|
160
|
+
* @param layout - The layout to set.
|
|
161
|
+
* @returns The layout function.
|
|
162
|
+
*/
|
|
163
|
+
setLayout = (layout) => (this.#layout = layout);
|
|
164
|
+
/**
|
|
165
|
+
* Gets the current layout for the response.
|
|
166
|
+
*
|
|
167
|
+
* @returns The current layout function.
|
|
168
|
+
*/
|
|
169
|
+
getLayout = () => this.#layout;
|
|
170
|
+
/**
|
|
171
|
+
* `.setRenderer()` can set the layout in the custom middleware.
|
|
172
|
+
*
|
|
173
|
+
* @see {@link https://hono.dev/docs/api/context#render-setrenderer}
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```tsx
|
|
177
|
+
* app.use('*', async (c, next) => {
|
|
178
|
+
* c.setRenderer((content) => {
|
|
179
|
+
* return c.html(
|
|
180
|
+
* <html>
|
|
181
|
+
* <body>
|
|
182
|
+
* <p>{content}</p>
|
|
183
|
+
* </body>
|
|
184
|
+
* </html>
|
|
185
|
+
* )
|
|
186
|
+
* })
|
|
187
|
+
* await next()
|
|
188
|
+
* })
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
setRenderer = (renderer) => {
|
|
192
|
+
this.#renderer = renderer;
|
|
193
|
+
};
|
|
194
|
+
/**
|
|
195
|
+
* `.header()` can set headers.
|
|
196
|
+
*
|
|
197
|
+
* @see {@link https://hono.dev/docs/api/context#header}
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```ts
|
|
201
|
+
* app.get('/welcome', (c) => {
|
|
202
|
+
* // Set headers
|
|
203
|
+
* c.header('X-Message', 'Hello!')
|
|
204
|
+
* c.header('Content-Type', 'text/plain')
|
|
205
|
+
*
|
|
206
|
+
* return c.body('Thank you for coming')
|
|
207
|
+
* })
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
header = (name, value, options) => {
|
|
211
|
+
if (this.finalized) {
|
|
212
|
+
this.#res = new Response(this.#res.body, this.#res);
|
|
213
|
+
}
|
|
214
|
+
const headers = this.#res ? this.#res.headers : (this.#preparedHeaders ??= new Headers());
|
|
215
|
+
if (value === undefined) {
|
|
216
|
+
headers.delete(name);
|
|
217
|
+
}
|
|
218
|
+
else if (options?.append) {
|
|
219
|
+
headers.append(name, value);
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
headers.set(name, value);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
status = (status) => {
|
|
226
|
+
this.#status = status;
|
|
227
|
+
};
|
|
228
|
+
/**
|
|
229
|
+
* `.set()` can set the value specified by the key.
|
|
230
|
+
*
|
|
231
|
+
* @see {@link https://hono.dev/docs/api/context#set-get}
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* app.use('*', async (c, next) => {
|
|
236
|
+
* c.set('message', 'Hono is hot!!')
|
|
237
|
+
* await next()
|
|
238
|
+
* })
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
set = (key, value) => {
|
|
242
|
+
this.#var ??= new Map();
|
|
243
|
+
this.#var.set(key, value);
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* `.get()` can use the value specified by the key.
|
|
247
|
+
*
|
|
248
|
+
* @see {@link https://hono.dev/docs/api/context#set-get}
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```ts
|
|
252
|
+
* app.get('/', (c) => {
|
|
253
|
+
* const message = c.get('message')
|
|
254
|
+
* return c.text(`The message is "${message}"`)
|
|
255
|
+
* })
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
get = (key) => {
|
|
259
|
+
return this.#var ? this.#var.get(key) : undefined;
|
|
260
|
+
};
|
|
464
261
|
/**
|
|
465
262
|
* `.var` can access the value of a variable.
|
|
466
263
|
*
|
|
@@ -473,41 +270,141 @@ export class Context {
|
|
|
473
270
|
*/
|
|
474
271
|
// c.var.propName is a read-only
|
|
475
272
|
get var() {
|
|
476
|
-
if (!
|
|
273
|
+
if (!this.#var) {
|
|
477
274
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
478
275
|
return {};
|
|
479
276
|
}
|
|
480
|
-
return Object.fromEntries(
|
|
277
|
+
return Object.fromEntries(this.#var);
|
|
481
278
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
279
|
+
#newResponse(data, arg, headers) {
|
|
280
|
+
const responseHeaders = this.#res
|
|
281
|
+
? new Headers(this.#res.headers)
|
|
282
|
+
: this.#preparedHeaders ?? new Headers();
|
|
283
|
+
if (typeof arg === 'object' && 'headers' in arg) {
|
|
284
|
+
const argHeaders = arg.headers instanceof Headers ? arg.headers : new Headers(arg.headers);
|
|
285
|
+
for (const [key, value] of argHeaders) {
|
|
286
|
+
if (key.toLowerCase() === 'set-cookie') {
|
|
287
|
+
responseHeaders.append(key, value);
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
responseHeaders.set(key, value);
|
|
291
|
+
}
|
|
495
292
|
}
|
|
496
293
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
294
|
+
if (headers) {
|
|
295
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
296
|
+
if (typeof v === 'string') {
|
|
297
|
+
responseHeaders.set(k, v);
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
responseHeaders.delete(k);
|
|
301
|
+
for (const v2 of v) {
|
|
302
|
+
responseHeaders.append(k, v2);
|
|
303
|
+
}
|
|
507
304
|
}
|
|
508
305
|
}
|
|
509
306
|
}
|
|
307
|
+
const status = typeof arg === 'number' ? arg : arg?.status ?? this.#status;
|
|
308
|
+
return new Response(data, { status, headers: responseHeaders });
|
|
510
309
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
310
|
+
newResponse = (...args) => this.#newResponse(...args);
|
|
311
|
+
/**
|
|
312
|
+
* `.body()` can return the HTTP response.
|
|
313
|
+
* You can set headers with `.header()` and set HTTP status code with `.status`.
|
|
314
|
+
* This can also be set in `.text()`, `.json()` and so on.
|
|
315
|
+
*
|
|
316
|
+
* @see {@link https://hono.dev/docs/api/context#body}
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* ```ts
|
|
320
|
+
* app.get('/welcome', (c) => {
|
|
321
|
+
* // Set headers
|
|
322
|
+
* c.header('X-Message', 'Hello!')
|
|
323
|
+
* c.header('Content-Type', 'text/plain')
|
|
324
|
+
* // Set HTTP status code
|
|
325
|
+
* c.status(201)
|
|
326
|
+
*
|
|
327
|
+
* // Return the response body
|
|
328
|
+
* return c.body('Thank you for coming')
|
|
329
|
+
* })
|
|
330
|
+
* ```
|
|
331
|
+
*/
|
|
332
|
+
body = (data, arg, headers) => this.#newResponse(data, arg, headers);
|
|
333
|
+
/**
|
|
334
|
+
* `.text()` can render text as `Content-Type:text/plain`.
|
|
335
|
+
*
|
|
336
|
+
* @see {@link https://hono.dev/docs/api/context#text}
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* ```ts
|
|
340
|
+
* app.get('/say', (c) => {
|
|
341
|
+
* return c.text('Hello!')
|
|
342
|
+
* })
|
|
343
|
+
* ```
|
|
344
|
+
*/
|
|
345
|
+
text = (text, arg, headers) => {
|
|
346
|
+
return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized
|
|
347
|
+
? new Response(text)
|
|
348
|
+
: this.#newResponse(text, arg, setDefaultContentType(TEXT_PLAIN, headers));
|
|
349
|
+
};
|
|
350
|
+
/**
|
|
351
|
+
* `.json()` can render JSON as `Content-Type:application/json`.
|
|
352
|
+
*
|
|
353
|
+
* @see {@link https://hono.dev/docs/api/context#json}
|
|
354
|
+
*
|
|
355
|
+
* @example
|
|
356
|
+
* ```ts
|
|
357
|
+
* app.get('/api', (c) => {
|
|
358
|
+
* return c.json({ message: 'Hello!' })
|
|
359
|
+
* })
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
362
|
+
json = (object, arg, headers) => {
|
|
363
|
+
return this.#newResponse(JSON.stringify(object), arg, setDefaultContentType('application/json', headers)) /* eslint-disable @typescript-eslint/no-explicit-any */;
|
|
364
|
+
};
|
|
365
|
+
html = (html, arg, headers) => {
|
|
366
|
+
const res = (html) => this.#newResponse(html, arg, setDefaultContentType('text/html; charset=UTF-8', headers));
|
|
367
|
+
return typeof html === 'object'
|
|
368
|
+
? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res)
|
|
369
|
+
: res(html);
|
|
370
|
+
};
|
|
371
|
+
/**
|
|
372
|
+
* `.redirect()` can Redirect, default status code is 302.
|
|
373
|
+
*
|
|
374
|
+
* @see {@link https://hono.dev/docs/api/context#redirect}
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* ```ts
|
|
378
|
+
* app.get('/redirect', (c) => {
|
|
379
|
+
* return c.redirect('/')
|
|
380
|
+
* })
|
|
381
|
+
* app.get('/redirect-permanently', (c) => {
|
|
382
|
+
* return c.redirect('/', 301)
|
|
383
|
+
* })
|
|
384
|
+
* ```
|
|
385
|
+
*/
|
|
386
|
+
redirect = (location, status) => {
|
|
387
|
+
const locationString = String(location);
|
|
388
|
+
this.header('Location',
|
|
389
|
+
// Multibyes should be encoded
|
|
390
|
+
// eslint-disable-next-line no-control-regex
|
|
391
|
+
!/[^\x00-\xFF]/.test(locationString) ? locationString : encodeURI(locationString));
|
|
392
|
+
return this.newResponse(null, status ?? 302);
|
|
393
|
+
};
|
|
394
|
+
/**
|
|
395
|
+
* `.notFound()` can return the Not Found Response.
|
|
396
|
+
*
|
|
397
|
+
* @see {@link https://hono.dev/docs/api/context#notfound}
|
|
398
|
+
*
|
|
399
|
+
* @example
|
|
400
|
+
* ```ts
|
|
401
|
+
* app.get('/notfound', (c) => {
|
|
402
|
+
* return c.notFound()
|
|
403
|
+
* })
|
|
404
|
+
* ```
|
|
405
|
+
*/
|
|
406
|
+
notFound = () => {
|
|
407
|
+
this.#notFoundHandler ??= () => new Response();
|
|
408
|
+
return this.#notFoundHandler(this);
|
|
409
|
+
};
|
|
410
|
+
}
|