2023-08-19 09:20:08 +02:00
|
|
|
import type { HonoRequest } from './request.ts'
|
2023-06-29 09:48:00 +02:00
|
|
|
import { FetchEventLike } from './types.ts'
|
|
|
|
import type { Env, NotFoundHandler, Input, TypedResponse } from './types.ts'
|
2022-07-10 17:17:29 +02:00
|
|
|
import type { CookieOptions } from './utils/cookie.ts'
|
|
|
|
import { serialize } from './utils/cookie.ts'
|
2022-07-02 08:09:45 +02:00
|
|
|
import type { StatusCode } from './utils/http-status.ts'
|
2023-06-06 03:23:09 +02:00
|
|
|
import type { JSONValue, InterfaceToType } from './utils/types.ts'
|
2022-07-02 08:09:45 +02:00
|
|
|
|
2023-01-29 06:47:35 +01:00
|
|
|
type Runtime = 'node' | 'deno' | 'bun' | 'workerd' | 'fastly' | 'edge-light' | 'lagon' | 'other'
|
2023-01-04 16:01:46 +01:00
|
|
|
type HeaderRecord = Record<string, string | string[]>
|
2022-12-28 03:25:48 +01:00
|
|
|
type Data = string | ArrayBuffer | ReadableStream
|
|
|
|
|
|
|
|
export interface ExecutionContext {
|
2023-03-05 15:37:02 +01:00
|
|
|
waitUntil(promise: Promise<unknown>): void
|
2022-12-28 03:25:48 +01:00
|
|
|
passThroughOnException(): void
|
|
|
|
}
|
2023-09-05 09:01:58 +02:00
|
|
|
|
2022-12-28 03:25:48 +01:00
|
|
|
export interface ContextVariableMap {}
|
2022-07-02 08:09:45 +02:00
|
|
|
|
2023-09-05 09:01:58 +02:00
|
|
|
export interface ContextRenderer {}
|
|
|
|
interface DefaultRenderer {
|
|
|
|
(content: string): Response | Promise<Response>
|
|
|
|
}
|
|
|
|
type Renderer = ContextRenderer extends Function ? ContextRenderer : DefaultRenderer
|
|
|
|
|
2023-05-09 14:55:40 +02:00
|
|
|
interface Get<E extends Env> {
|
|
|
|
<Key extends keyof ContextVariableMap>(key: Key): ContextVariableMap[Key]
|
|
|
|
<Key extends keyof E['Variables']>(key: Key): E['Variables'][Key]
|
|
|
|
}
|
|
|
|
|
|
|
|
interface Set<E extends Env> {
|
|
|
|
<Key extends keyof ContextVariableMap>(key: Key, value: ContextVariableMap[Key]): void
|
|
|
|
<Key extends keyof E['Variables']>(key: Key, value: E['Variables'][Key]): void
|
|
|
|
}
|
|
|
|
|
2023-03-09 15:54:47 +01:00
|
|
|
interface NewResponse {
|
|
|
|
(data: Data | null, status?: StatusCode, headers?: HeaderRecord): Response
|
|
|
|
(data: Data | null, init?: ResponseInit): Response
|
|
|
|
}
|
|
|
|
|
|
|
|
interface BodyRespond extends NewResponse {}
|
|
|
|
|
|
|
|
interface TextRespond {
|
|
|
|
(text: string, status?: StatusCode, headers?: HeaderRecord): Response
|
|
|
|
(text: string, init?: ResponseInit): Response
|
|
|
|
}
|
|
|
|
|
|
|
|
interface JSONRespond {
|
|
|
|
<T = JSONValue>(object: T, status?: StatusCode, headers?: HeaderRecord): Response
|
|
|
|
<T = JSONValue>(object: T, init?: ResponseInit): Response
|
|
|
|
}
|
|
|
|
|
|
|
|
interface JSONTRespond {
|
2023-06-06 03:23:09 +02:00
|
|
|
<T>(
|
|
|
|
object: InterfaceToType<T> extends JSONValue ? T : JSONValue,
|
|
|
|
status?: StatusCode,
|
|
|
|
headers?: HeaderRecord
|
|
|
|
): TypedResponse<
|
|
|
|
InterfaceToType<T> extends JSONValue
|
|
|
|
? JSONValue extends InterfaceToType<T>
|
|
|
|
? never
|
|
|
|
: T
|
|
|
|
: never
|
|
|
|
>
|
|
|
|
<T>(
|
|
|
|
object: InterfaceToType<T> extends JSONValue ? T : JSONValue,
|
|
|
|
init?: ResponseInit
|
|
|
|
): TypedResponse<
|
|
|
|
InterfaceToType<T> extends JSONValue
|
|
|
|
? JSONValue extends InterfaceToType<T>
|
|
|
|
? never
|
|
|
|
: T
|
|
|
|
: never
|
2023-03-09 15:54:47 +01:00
|
|
|
>
|
|
|
|
}
|
|
|
|
|
|
|
|
interface HTMLRespond {
|
|
|
|
(html: string, status?: StatusCode, headers?: HeaderRecord): Response
|
|
|
|
(html: string, init?: ResponseInit): Response
|
|
|
|
}
|
|
|
|
|
2023-01-16 14:57:47 +01:00
|
|
|
type ContextOptions<E extends Env> = {
|
|
|
|
env: E['Bindings']
|
2023-06-29 09:48:00 +02:00
|
|
|
executionCtx?: FetchEventLike | ExecutionContext | undefined
|
2023-01-16 14:57:47 +01:00
|
|
|
notFoundHandler?: NotFoundHandler<E>
|
2022-12-20 23:05:00 +01:00
|
|
|
}
|
|
|
|
|
2022-11-03 07:53:41 +01:00
|
|
|
export class Context<
|
2022-12-10 08:37:14 +01:00
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2023-01-16 14:57:47 +01:00
|
|
|
E extends Env = any,
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2023-01-31 22:36:48 +01:00
|
|
|
P extends string = any,
|
|
|
|
I extends Input = {}
|
2022-08-23 13:53:25 +02:00
|
|
|
> {
|
2023-08-19 09:20:08 +02:00
|
|
|
req: HonoRequest<P, I['out']>
|
2022-12-20 23:05:00 +01:00
|
|
|
env: E['Bindings'] = {}
|
|
|
|
finalized: boolean = false
|
2022-10-02 08:44:54 +02:00
|
|
|
error: Error | undefined = undefined
|
2022-07-10 16:44:23 +02:00
|
|
|
|
2022-11-23 10:42:24 +01:00
|
|
|
private _status: StatusCode = 200
|
2023-06-29 09:48:00 +02:00
|
|
|
private _exCtx: FetchEventLike | ExecutionContext | undefined // _executionCtx
|
2022-10-23 01:10:00 +02:00
|
|
|
private _map: Record<string, unknown> | undefined
|
2023-04-30 14:07:00 +02:00
|
|
|
private _h: Headers | undefined = undefined // _headers
|
|
|
|
private _pH: Record<string, string> | undefined = undefined // _preparedHeaders
|
2022-07-02 08:09:45 +02:00
|
|
|
private _res: Response | undefined
|
2023-08-03 17:09:12 +02:00
|
|
|
private _init = true
|
2023-09-05 09:01:58 +02:00
|
|
|
private _renderer: Renderer = (content: string) => this.html(content)
|
2023-01-16 14:57:47 +01:00
|
|
|
private notFoundHandler: NotFoundHandler<E> = () => new Response()
|
2022-12-20 23:05:00 +01:00
|
|
|
|
2023-08-19 09:20:08 +02:00
|
|
|
constructor(req: HonoRequest<P, I['out']>, options?: ContextOptions<E>) {
|
|
|
|
this.req = req
|
2022-12-20 23:05:00 +01:00
|
|
|
if (options) {
|
2023-04-30 14:07:00 +02:00
|
|
|
this._exCtx = options.executionCtx
|
2022-12-20 23:05:00 +01:00
|
|
|
this.env = options.env
|
|
|
|
if (options.notFoundHandler) {
|
|
|
|
this.notFoundHandler = options.notFoundHandler
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-29 09:48:00 +02:00
|
|
|
get event(): FetchEventLike {
|
|
|
|
if (this._exCtx instanceof FetchEventLike) {
|
2023-04-30 14:07:00 +02:00
|
|
|
return this._exCtx
|
2022-07-02 08:09:45 +02:00
|
|
|
} else {
|
2022-07-17 11:11:09 +02:00
|
|
|
throw Error('This context has no FetchEvent')
|
2022-07-02 08:09:45 +02:00
|
|
|
}
|
2022-07-17 11:11:09 +02:00
|
|
|
}
|
2022-07-02 08:09:45 +02:00
|
|
|
|
2022-07-17 11:11:09 +02:00
|
|
|
get executionCtx(): ExecutionContext {
|
2023-04-30 14:07:00 +02:00
|
|
|
if (this._exCtx) {
|
|
|
|
return this._exCtx as ExecutionContext
|
2022-07-17 11:11:09 +02:00
|
|
|
} else {
|
|
|
|
throw Error('This context has no ExecutionContext')
|
|
|
|
}
|
2022-07-02 08:09:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
get res(): Response {
|
2023-08-03 17:09:12 +02:00
|
|
|
this._init = false
|
2022-09-21 16:05:26 +02:00
|
|
|
return (this._res ||= new Response('404 Not Found', { status: 404 }))
|
2022-07-02 08:09:45 +02:00
|
|
|
}
|
|
|
|
|
2023-03-13 14:08:16 +01:00
|
|
|
set res(_res: Response | undefined) {
|
2023-08-03 17:09:12 +02:00
|
|
|
this._init = false
|
2023-03-13 14:08:16 +01:00
|
|
|
if (this._res && _res) {
|
2023-01-24 00:53:31 +01:00
|
|
|
this._res.headers.delete('content-type')
|
2023-01-23 00:35:14 +01:00
|
|
|
this._res.headers.forEach((v, k) => {
|
|
|
|
_res.headers.set(k, v)
|
|
|
|
})
|
|
|
|
}
|
2022-07-02 08:09:45 +02:00
|
|
|
this._res = _res
|
|
|
|
this.finalized = true
|
|
|
|
}
|
|
|
|
|
2023-09-05 09:01:58 +02:00
|
|
|
/**
|
|
|
|
* @experimental
|
|
|
|
* `c.render()` is an experimental feature.
|
|
|
|
* The API might be changed.
|
|
|
|
*/
|
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
|
|
// @ts-ignore
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
render: Renderer = (...args: any[]) => this._renderer(...args)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @experimental
|
|
|
|
* `c.setRenderer()` is an experimental feature.
|
|
|
|
* The API might be changed.
|
|
|
|
*/
|
|
|
|
setRenderer = (renderer: Renderer) => {
|
|
|
|
this._renderer = renderer
|
|
|
|
}
|
|
|
|
|
2023-05-05 04:46:10 +02:00
|
|
|
header = (name: string, value: string | undefined, options?: { append?: boolean }): void => {
|
|
|
|
// Clear the header
|
|
|
|
if (value === undefined) {
|
|
|
|
if (this._h) {
|
|
|
|
this._h.delete(name)
|
|
|
|
} else if (this._pH) {
|
|
|
|
delete this._pH[name.toLocaleLowerCase()]
|
|
|
|
}
|
|
|
|
if (this.finalized) {
|
|
|
|
this.res.headers.delete(name)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-01-04 16:01:46 +01:00
|
|
|
if (options?.append) {
|
2023-04-30 14:07:00 +02:00
|
|
|
if (!this._h) {
|
2023-08-03 17:09:12 +02:00
|
|
|
this._init = false
|
2023-04-30 14:07:00 +02:00
|
|
|
this._h = new Headers(this._pH)
|
|
|
|
this._pH = {}
|
2022-09-20 14:41:45 +02:00
|
|
|
}
|
2023-04-30 14:07:00 +02:00
|
|
|
this._h.append(name, value)
|
2022-09-20 14:41:45 +02:00
|
|
|
} else {
|
2023-04-30 14:07:00 +02:00
|
|
|
if (this._h) {
|
|
|
|
this._h.set(name, value)
|
2023-01-04 16:01:46 +01:00
|
|
|
} else {
|
2023-04-30 14:07:00 +02:00
|
|
|
this._pH ??= {}
|
|
|
|
this._pH[name.toLowerCase()] = value
|
2023-01-04 16:01:46 +01:00
|
|
|
}
|
2022-09-20 14:41:45 +02:00
|
|
|
}
|
|
|
|
|
2022-07-02 08:09:45 +02:00
|
|
|
if (this.finalized) {
|
2023-01-04 16:01:46 +01:00
|
|
|
if (options?.append) {
|
2022-09-20 14:41:45 +02:00
|
|
|
this.res.headers.append(name, value)
|
|
|
|
} else {
|
|
|
|
this.res.headers.set(name, value)
|
|
|
|
}
|
2022-07-02 08:09:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-18 00:23:58 +01:00
|
|
|
status = (status: StatusCode): void => {
|
2022-07-02 08:09:45 +02:00
|
|
|
this._status = status
|
|
|
|
}
|
|
|
|
|
2023-05-09 14:55:40 +02:00
|
|
|
set: Set<E> = (key: string, value: unknown) => {
|
2022-07-02 08:09:45 +02:00
|
|
|
this._map ||= {}
|
2023-01-03 14:00:29 +01:00
|
|
|
this._map[key as string] = value
|
2022-07-02 08:09:45 +02:00
|
|
|
}
|
|
|
|
|
2023-05-09 14:55:40 +02:00
|
|
|
get: Get<E> = (key: string) => {
|
|
|
|
return this._map ? this._map[key] : undefined
|
2022-07-02 08:09:45 +02:00
|
|
|
}
|
|
|
|
|
2023-03-09 15:54:47 +01:00
|
|
|
newResponse: NewResponse = (
|
|
|
|
data: Data | null,
|
|
|
|
arg?: StatusCode | ResponseInit,
|
|
|
|
headers?: HeaderRecord
|
|
|
|
): Response => {
|
2023-01-17 10:30:02 +01:00
|
|
|
// Optimized
|
2023-08-03 17:09:12 +02:00
|
|
|
if (this._init && !headers && !arg && this._status === 200) {
|
2023-01-04 16:01:46 +01:00
|
|
|
return new Response(data, {
|
2023-04-30 14:07:00 +02:00
|
|
|
headers: this._pH,
|
2023-01-04 16:01:46 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-08-20 17:23:05 +02:00
|
|
|
// Return Response immediately if arg is ResponseInit.
|
2023-03-09 15:54:47 +01:00
|
|
|
if (arg && typeof arg !== 'number') {
|
|
|
|
const res = new Response(data, arg)
|
2023-04-30 14:07:00 +02:00
|
|
|
const contentType = this._pH?.['content-type']
|
2023-03-09 15:54:47 +01:00
|
|
|
if (contentType) {
|
|
|
|
res.headers.set('content-type', contentType)
|
|
|
|
}
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
const status = arg ?? this._status
|
2023-04-30 14:07:00 +02:00
|
|
|
this._pH ??= {}
|
2023-01-04 16:01:46 +01:00
|
|
|
|
2023-04-30 14:07:00 +02:00
|
|
|
this._h ??= new Headers()
|
|
|
|
for (const [k, v] of Object.entries(this._pH)) {
|
|
|
|
this._h.set(k, v)
|
2023-01-04 16:01:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this._res) {
|
|
|
|
this._res.headers.forEach((v, k) => {
|
2023-04-30 14:07:00 +02:00
|
|
|
this._h?.set(k, v)
|
2023-01-04 16:01:46 +01:00
|
|
|
})
|
2023-04-30 14:07:00 +02:00
|
|
|
for (const [k, v] of Object.entries(this._pH)) {
|
|
|
|
this._h.set(k, v)
|
2023-01-04 16:01:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
headers ??= {}
|
|
|
|
for (const [k, v] of Object.entries(headers)) {
|
|
|
|
if (typeof v === 'string') {
|
2023-04-30 14:07:00 +02:00
|
|
|
this._h.set(k, v)
|
2023-01-04 16:01:46 +01:00
|
|
|
} else {
|
2023-04-30 14:07:00 +02:00
|
|
|
this._h.delete(k)
|
2023-01-04 16:01:46 +01:00
|
|
|
for (const v2 of v) {
|
2023-04-30 14:07:00 +02:00
|
|
|
this._h.append(k, v2)
|
2023-01-04 16:01:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-20 14:41:45 +02:00
|
|
|
return new Response(data, {
|
2022-11-23 10:42:24 +01:00
|
|
|
status,
|
2023-04-30 14:07:00 +02:00
|
|
|
headers: this._h,
|
2022-09-20 14:41:45 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-03-09 15:54:47 +01:00
|
|
|
body: BodyRespond = (
|
2023-01-18 00:42:23 +01:00
|
|
|
data: Data | null,
|
2023-08-20 17:23:05 +02:00
|
|
|
arg?: StatusCode | ResponseInit,
|
2023-01-18 00:42:23 +01:00
|
|
|
headers?: HeaderRecord
|
|
|
|
): Response => {
|
2023-03-09 15:54:47 +01:00
|
|
|
return typeof arg === 'number'
|
|
|
|
? this.newResponse(data, arg, headers)
|
|
|
|
: this.newResponse(data, arg)
|
2023-01-04 16:01:46 +01:00
|
|
|
}
|
|
|
|
|
2023-03-09 15:54:47 +01:00
|
|
|
text: TextRespond = (
|
|
|
|
text: string,
|
2023-08-20 17:23:05 +02:00
|
|
|
arg?: StatusCode | ResponseInit,
|
2023-03-09 15:54:47 +01:00
|
|
|
headers?: HeaderRecord
|
|
|
|
): Response => {
|
2022-12-14 14:03:02 +01:00
|
|
|
// If the header is empty, return Response immediately.
|
|
|
|
// Content-Type will be added automatically as `text/plain`.
|
2023-04-30 14:07:00 +02:00
|
|
|
if (!this._pH) {
|
2023-08-03 17:09:12 +02:00
|
|
|
if (this._init && !headers && !arg) {
|
2023-01-17 10:30:02 +01:00
|
|
|
return new Response(text)
|
|
|
|
}
|
2023-04-30 14:07:00 +02:00
|
|
|
this._pH = {}
|
2022-12-14 14:03:02 +01:00
|
|
|
}
|
2023-01-17 10:30:02 +01:00
|
|
|
// If Content-Type is not set, we don't have to set `text/plain`.
|
|
|
|
// Fewer the header values, it will be faster.
|
2023-04-30 14:07:00 +02:00
|
|
|
if (this._pH['content-type']) {
|
2023-05-10 01:27:40 +02:00
|
|
|
this._pH['content-type'] = 'text/plain; charset=UTF-8'
|
2023-01-17 10:30:02 +01:00
|
|
|
}
|
2023-03-09 15:54:47 +01:00
|
|
|
return typeof arg === 'number'
|
|
|
|
? this.newResponse(text, arg, headers)
|
|
|
|
: this.newResponse(text, arg)
|
2022-07-02 08:09:45 +02:00
|
|
|
}
|
|
|
|
|
2023-03-09 15:54:47 +01:00
|
|
|
json: JSONRespond = <T = {}>(
|
2023-02-01 16:25:58 +01:00
|
|
|
object: T,
|
2023-08-20 17:23:05 +02:00
|
|
|
arg?: StatusCode | ResponseInit,
|
2023-02-01 16:25:58 +01:00
|
|
|
headers?: HeaderRecord
|
2023-03-09 15:54:47 +01:00
|
|
|
) => {
|
2023-08-05 11:13:39 +02:00
|
|
|
const body = JSON.stringify(object)
|
2023-04-30 14:07:00 +02:00
|
|
|
this._pH ??= {}
|
|
|
|
this._pH['content-type'] = 'application/json; charset=UTF-8'
|
2023-03-09 15:54:47 +01:00
|
|
|
return typeof arg === 'number'
|
|
|
|
? this.newResponse(body, arg, headers)
|
|
|
|
: this.newResponse(body, arg)
|
2022-07-02 08:09:45 +02:00
|
|
|
}
|
|
|
|
|
2023-03-09 15:54:47 +01:00
|
|
|
jsonT: JSONTRespond = <T>(
|
2023-06-06 03:23:09 +02:00
|
|
|
object: InterfaceToType<T> extends JSONValue ? T : JSONValue,
|
2023-08-20 17:23:05 +02:00
|
|
|
arg?: StatusCode | ResponseInit,
|
2023-01-18 00:42:23 +01:00
|
|
|
headers?: HeaderRecord
|
2023-06-06 03:23:09 +02:00
|
|
|
): TypedResponse<
|
|
|
|
InterfaceToType<T> extends JSONValue
|
|
|
|
? JSONValue extends InterfaceToType<T>
|
|
|
|
? never
|
|
|
|
: T
|
|
|
|
: never
|
|
|
|
> => {
|
2023-09-05 08:58:43 +02:00
|
|
|
const response =
|
|
|
|
typeof arg === 'number' ? this.json(object, arg, headers) : this.json(object, arg)
|
|
|
|
|
2022-12-28 03:25:48 +01:00
|
|
|
return {
|
2023-09-05 08:58:43 +02:00
|
|
|
response,
|
2023-03-02 00:56:13 +01:00
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
data: object as any,
|
2022-12-28 03:25:48 +01:00
|
|
|
format: 'json',
|
2023-09-05 08:58:43 +02:00
|
|
|
status: response.status,
|
2022-12-28 03:25:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-09 15:54:47 +01:00
|
|
|
html: HTMLRespond = (
|
|
|
|
html: string,
|
2023-08-20 17:23:05 +02:00
|
|
|
arg?: StatusCode | ResponseInit,
|
2023-03-09 15:54:47 +01:00
|
|
|
headers?: HeaderRecord
|
|
|
|
): Response => {
|
2023-04-30 14:07:00 +02:00
|
|
|
this._pH ??= {}
|
|
|
|
this._pH['content-type'] = 'text/html; charset=UTF-8'
|
2023-03-09 15:54:47 +01:00
|
|
|
return typeof arg === 'number'
|
|
|
|
? this.newResponse(html, arg, headers)
|
|
|
|
: this.newResponse(html, arg)
|
2023-01-04 16:01:46 +01:00
|
|
|
}
|
|
|
|
|
2023-01-18 00:42:23 +01:00
|
|
|
redirect = (location: string, status: StatusCode = 302): Response => {
|
2023-04-30 14:07:00 +02:00
|
|
|
this._h ??= new Headers()
|
|
|
|
this._h.set('Location', location)
|
2023-01-04 16:01:46 +01:00
|
|
|
return this.newResponse(null, status)
|
2022-07-02 08:09:45 +02:00
|
|
|
}
|
|
|
|
|
2023-05-05 04:08:03 +02:00
|
|
|
/** @deprecated
|
|
|
|
* Use Cookie Middleware instead of `c.cookie()`. The `c.cookie()` will be removed in v4.
|
|
|
|
*
|
|
|
|
* @example
|
|
|
|
*
|
|
|
|
* import { setCookie } from 'hono/cookie'
|
|
|
|
* // ...
|
|
|
|
* app.get('/', (c) => {
|
|
|
|
* setCookie(c, 'key', 'value')
|
|
|
|
* //...
|
|
|
|
* })
|
|
|
|
*/
|
2023-01-18 00:23:58 +01:00
|
|
|
cookie = (name: string, value: string, opt?: CookieOptions): void => {
|
2022-07-10 17:17:29 +02:00
|
|
|
const cookie = serialize(name, value, opt)
|
2022-09-20 14:41:45 +02:00
|
|
|
this.header('set-cookie', cookie, { append: true })
|
2022-07-10 17:17:29 +02:00
|
|
|
}
|
|
|
|
|
2023-01-18 00:42:23 +01:00
|
|
|
notFound = (): Response | Promise<Response> => {
|
2023-01-16 14:57:47 +01:00
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
|
|
// @ts-ignore
|
2022-12-28 03:25:48 +01:00
|
|
|
return this.notFoundHandler(this)
|
2022-07-02 08:09:45 +02:00
|
|
|
}
|
2022-11-03 07:35:23 +01:00
|
|
|
|
2023-08-21 08:22:37 +02:00
|
|
|
/** @deprecated
|
|
|
|
* Use `getRuntimeKey()` exported from `hono/adapter` instead of `c.runtime()`. The `c.runtime()` will be removed in v4.
|
|
|
|
*
|
|
|
|
* @example
|
|
|
|
*
|
|
|
|
* import { getRuntimeKey } from 'hono/adapter'
|
|
|
|
* // ...
|
|
|
|
* app.get('/', (c) => {
|
|
|
|
* const key = getRuntimeKey()
|
|
|
|
* //...
|
|
|
|
* })
|
|
|
|
*/
|
2022-11-03 07:35:23 +01:00
|
|
|
get runtime(): Runtime {
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
const global = globalThis as any
|
|
|
|
|
|
|
|
if (global?.Deno !== undefined) {
|
|
|
|
return 'deno'
|
|
|
|
}
|
|
|
|
|
|
|
|
if (global?.Bun !== undefined) {
|
|
|
|
return 'bun'
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof global?.WebSocketPair === 'function') {
|
2023-01-29 06:47:35 +01:00
|
|
|
return 'workerd'
|
2022-11-03 07:35:23 +01:00
|
|
|
}
|
|
|
|
|
2022-12-02 03:28:49 +01:00
|
|
|
if (typeof global?.EdgeRuntime === 'string') {
|
2023-01-29 06:47:35 +01:00
|
|
|
return 'edge-light'
|
2022-11-03 07:35:23 +01:00
|
|
|
}
|
|
|
|
|
2023-05-02 09:26:39 +02:00
|
|
|
if (global?.fastly !== undefined) {
|
2023-01-08 01:05:49 +01:00
|
|
|
return 'fastly'
|
2022-11-03 23:14:57 +01:00
|
|
|
}
|
|
|
|
|
2022-12-24 17:42:59 +01:00
|
|
|
if (global?.__lagon__ !== undefined) {
|
|
|
|
return 'lagon'
|
|
|
|
}
|
|
|
|
|
2023-01-08 01:05:49 +01:00
|
|
|
if (global?.process?.release?.name === 'node') {
|
|
|
|
return 'node'
|
|
|
|
}
|
|
|
|
|
2022-11-03 07:35:23 +01:00
|
|
|
return 'other'
|
|
|
|
}
|
2022-07-02 08:09:45 +02:00
|
|
|
}
|