- : never
-
-type PathToChain<
- Path extends string,
- E extends Schema,
- Original extends string = ''
-> = Path extends `/${infer P}`
- ? PathToChain
- : Path extends `${infer P}/${infer R}`
- ? { [K in P]: PathToChain }
- : {
- [K in Path extends '' ? 'index' : Path]: ClientRequest<
- E extends Record ? E[Original] : never
- >
- }
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-export type Client = T extends Hono
- ? S extends Record
- ? K extends string
- ? PathToChain
- : never
- : never
- : never
-
-export type Callback = (opts: CallbackOptions) => unknown
-
-interface CallbackOptions {
- path: string[]
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- args: any[]
-}
-
-export type ObjectType = {
- [key: string]: T
-}
diff --git a/deno_dist/client/utils.ts b/deno_dist/client/utils.ts
deleted file mode 100644
index c9b43bcbba..0000000000
--- a/deno_dist/client/utils.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import type { ObjectType } from './types.ts'
-
-export const mergePath = (base: string, path: string) => {
- base = base.replace(/\/+$/, '')
- base = base + '/'
- path = path.replace(/^\/+/, '')
- return base + path
-}
-
-export const replaceUrlParam = (urlString: string, params: Record) => {
- for (const [k, v] of Object.entries(params)) {
- const reg = new RegExp('/:' + k + '(?:{[^/]+})?')
- urlString = urlString.replace(reg, `/${v}`)
- }
- return urlString
-}
-
-export const replaceUrlProtocol = (urlString: string, protocol: 'ws' | 'http') => {
- switch (protocol) {
- case 'ws':
- return urlString.replace(/^http/, 'ws')
- case 'http':
- return urlString.replace(/^ws/, 'http')
- }
-}
-
-export const removeIndexString = (urlSting: string) => {
- if (/^https?:\/\/[^\/]+?\/index$/.test(urlSting)) {
- return urlSting.replace(/\/index$/, '/')
- }
- return urlSting.replace(/\/index$/, '')
-}
-
-function isObject(item: unknown): item is ObjectType {
- return typeof item === 'object' && item !== null && !Array.isArray(item)
-}
-
-export function deepMerge(target: T, source: Record): T {
- if (!isObject(target) && !isObject(source)) {
- return source as T
- }
- const merged = { ...target } as ObjectType
-
- for (const key in source) {
- const value = source[key]
- if (isObject(merged[key]) && isObject(value)) {
- merged[key] = deepMerge(merged[key], value)
- } else {
- merged[key] = value as T[keyof T] & T
- }
- }
-
- return merged as T
-}
diff --git a/deno_dist/compose.ts b/deno_dist/compose.ts
deleted file mode 100644
index b03903a23d..0000000000
--- a/deno_dist/compose.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { Context } from './context.ts'
-import type { ParamIndexMap, Params } from './router.ts'
-import type { Env, NotFoundHandler, ErrorHandler } from './types.ts'
-
-interface ComposeContext {
- finalized: boolean
- res: unknown
-}
-
-// Based on the code in the MIT licensed `koa-compose` package.
-export const compose = (
- middleware: [[Function, unknown], ParamIndexMap | Params][],
- onError?: ErrorHandler,
- onNotFound?: NotFoundHandler
-) => {
- return (context: C, next?: Function) => {
- let index = -1
- return dispatch(0)
-
- async function dispatch(i: number): Promise {
- if (i <= index) {
- throw new Error('next() called multiple times')
- }
- index = i
-
- let res
- let isError = false
- let handler
-
- if (middleware[i]) {
- handler = middleware[i][0][0]
- if (context instanceof Context) {
- context.req.routeIndex = i
- }
- } else {
- handler = (i === middleware.length && next) || undefined
- }
-
- if (!handler) {
- if (context instanceof Context && context.finalized === false && onNotFound) {
- res = await onNotFound(context)
- }
- } else {
- try {
- res = await handler(context, () => {
- return dispatch(i + 1)
- })
- } catch (err) {
- if (err instanceof Error && context instanceof Context && onError) {
- context.error = err
- res = await onError(err, context)
- isError = true
- } else {
- throw err
- }
- }
- }
-
- if (res && (context.finalized === false || isError)) {
- context.res = res
- }
- return context
- }
- }
-}
diff --git a/deno_dist/context.ts b/deno_dist/context.ts
deleted file mode 100644
index ce647e4cfa..0000000000
--- a/deno_dist/context.ts
+++ /dev/null
@@ -1,572 +0,0 @@
-import type { HonoRequest } from './request.ts'
-import type { Env, FetchEventLike, Input, NotFoundHandler, TypedResponse } from './types.ts'
-import { HtmlEscapedCallbackPhase, resolveCallback } from './utils/html.ts'
-import type { RedirectStatusCode, StatusCode } from './utils/http-status.ts'
-import type { JSONValue, JSONParsed, IsAny, Simplify } from './utils/types.ts'
-
-type HeaderRecord = Record
-export type Data = string | ArrayBuffer | ReadableStream
-
-export interface ExecutionContext {
- waitUntil(promise: Promise): void
- passThroughOnException(): void
-}
-
-export interface ContextVariableMap {}
-
-export interface ContextRenderer {}
-interface DefaultRenderer {
- (content: string | Promise): Response | Promise
-}
-
-export type Renderer = ContextRenderer extends Function ? ContextRenderer : DefaultRenderer
-export type PropsForRenderer = [...Required>] extends [unknown, infer Props]
- ? Props
- : unknown
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-export type Layout> = (props: T) => any
-
-interface Get {
- (key: Key): ContextVariableMap[Key]
- (key: Key): E['Variables'][Key]
-}
-
-interface Set {
- (key: Key, value: ContextVariableMap[Key]): void
- (key: Key, value: E['Variables'][Key]): void
-}
-
-interface NewResponse {
- (data: Data | null, status?: StatusCode, headers?: HeaderRecord): Response
- (data: Data | null, init?: ResponseInit): Response
-}
-
-interface BodyRespond extends NewResponse {}
-
-interface TextRespond {
- (text: T, status?: U, headers?: HeaderRecord): Response &
- TypedResponse
- (text: T, init?: ResponseInit): Response &
- TypedResponse
-}
-
-interface JSONRespond {
- , U extends StatusCode>(
- object: T,
- status?: U,
- headers?: HeaderRecord
- ): Response &
- TypedResponse<
- Simplify extends JSONValue
- ? JSONValue extends Simplify
- ? never
- : JSONParsed
- : never,
- U,
- 'json'
- >
- , U extends StatusCode>(
- object: Simplify extends JSONValue ? T : Simplify,
- init?: ResponseInit
- ): Response &
- TypedResponse<
- Simplify extends JSONValue
- ? JSONValue extends Simplify
- ? never
- : JSONParsed
- : never,
- U,
- 'json'
- >
-}
-
-interface HTMLRespond {
- (html: string | Promise, status?: StatusCode, headers?: HeaderRecord):
- | Response
- | Promise
- (html: string | Promise, init?: ResponseInit): Response | Promise
-}
-
-type ContextOptions = {
- env: E['Bindings']
- executionCtx?: FetchEventLike | ExecutionContext | undefined
- notFoundHandler?: NotFoundHandler
-}
-
-export const TEXT_PLAIN = 'text/plain; charset=UTF-8'
-
-const setHeaders = (headers: Headers, map: Record = {}) => {
- Object.entries(map).forEach(([key, value]) => headers.set(key, value))
- return headers
-}
-
-export class Context<
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- E extends Env = any,
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- P extends string = any,
- I extends Input = {}
-> {
- /**
- * `.req` is the instance of {@link HonoRequest}.
- */
- req: HonoRequest
- /**
- * `.env` can get bindings (environment variables, secrets, KV namespaces, D1 database, R2 bucket etc.) in Cloudflare Workers.
- * @example
- * ```ts
- * // Environment object for Cloudflare Workers
- * app.get('*', async c => {
- * const counter = c.env.COUNTER
- * })
- * ```
- * @see https://hono.dev/api/context#env
- */
- env: E['Bindings'] = {}
- private _var: E['Variables'] = {}
- finalized: boolean = false
- /**
- * `.error` can get the error object from the middleware if the Handler throws an error.
- * @example
- * ```ts
- * app.use('*', async (c, next) => {
- * await next()
- * if (c.error) {
- * // do something...
- * }
- * })
- * ```
- * @see https://hono.dev/api/context#error
- */
- error: Error | undefined = undefined
-
- #status: StatusCode = 200
- #executionCtx: FetchEventLike | ExecutionContext | undefined
- #headers: Headers | undefined = undefined
- #preparedHeaders: Record | undefined = undefined
- #res: Response | undefined
- #isFresh = true
- private layout: Layout | undefined = undefined
- private renderer: Renderer = (content: string | Promise) => this.html(content)
- private notFoundHandler: NotFoundHandler = () => new Response()
-
- constructor(req: HonoRequest, options?: ContextOptions) {
- this.req = req
- if (options) {
- this.#executionCtx = options.executionCtx
- this.env = options.env
- if (options.notFoundHandler) {
- this.notFoundHandler = options.notFoundHandler
- }
- }
- }
-
- /**
- * @see https://hono.dev/api/context#event
- */
- get event(): FetchEventLike {
- if (this.#executionCtx && 'respondWith' in this.#executionCtx) {
- return this.#executionCtx
- } else {
- throw Error('This context has no FetchEvent')
- }
- }
-
- /**
- * @see https://hono.dev/api/context#executionctx
- */
- get executionCtx(): ExecutionContext {
- if (this.#executionCtx) {
- return this.#executionCtx as ExecutionContext
- } else {
- throw Error('This context has no ExecutionContext')
- }
- }
-
- /**
- * @see https://hono.dev/api/context#res
- */
- get res(): Response {
- this.#isFresh = false
- return (this.#res ||= new Response('404 Not Found', { status: 404 }))
- }
-
- set res(_res: Response | undefined) {
- this.#isFresh = false
- if (this.#res && _res) {
- this.#res.headers.delete('content-type')
- for (const [k, v] of this.#res.headers.entries()) {
- if (k === 'set-cookie') {
- const cookies = this.#res.headers.getSetCookie()
- _res.headers.delete('set-cookie')
- for (const cookie of cookies) {
- _res.headers.append('set-cookie', cookie)
- }
- } else {
- _res.headers.set(k, v)
- }
- }
- }
- this.#res = _res
- this.finalized = true
- }
-
- /**
- * `.render()` can create a response within a layout.
- * @example
- * ```ts
- * app.get('/', (c) => {
- * return c.render('Hello!')
- * })
- * ```
- * @see https://hono.dev/api/context#render-setrenderer
- */
- render: Renderer = (...args) => this.renderer(...args)
-
- setLayout = (
- layout: Layout
- ): Layout<
- PropsForRenderer & {
- Layout: Layout
- }
- > => (this.layout = layout)
-
- getLayout = () => this.layout
-
- /**
- * `.setRenderer()` can set the layout in the custom middleware.
- * @example
- * ```tsx
- * app.use('*', async (c, next) => {
- * c.setRenderer((content) => {
- * return c.html(
- *
- *
- * {content}
- *
- *
- * )
- * })
- * await next()
- * })
- * ```
- * @see https://hono.dev/api/context#render-setrenderer
- */
- setRenderer = (renderer: Renderer) => {
- this.renderer = renderer
- }
-
- /**
- * `.header()` can set headers.
- * @example
- * ```ts
- * app.get('/welcome', (c) => {
- * // Set headers
- * c.header('X-Message', 'Hello!')
- * c.header('Content-Type', 'text/plain')
- *
- * return c.body('Thank you for coming')
- * })
- * ```
- * @see https://hono.dev/api/context#body
- */
- header = (name: string, value: string | undefined, options?: { append?: boolean }): void => {
- // Clear the header
- if (value === undefined) {
- if (this.#headers) {
- this.#headers.delete(name)
- } else if (this.#preparedHeaders) {
- delete this.#preparedHeaders[name.toLocaleLowerCase()]
- }
- if (this.finalized) {
- this.res.headers.delete(name)
- }
- return
- }
-
- if (options?.append) {
- if (!this.#headers) {
- this.#isFresh = false
- this.#headers = new Headers(this.#preparedHeaders)
- this.#preparedHeaders = {}
- }
- this.#headers.append(name, value)
- } else {
- if (this.#headers) {
- this.#headers.set(name, value)
- } else {
- this.#preparedHeaders ??= {}
- this.#preparedHeaders[name.toLowerCase()] = value
- }
- }
-
- if (this.finalized) {
- if (options?.append) {
- this.res.headers.append(name, value)
- } else {
- this.res.headers.set(name, value)
- }
- }
- }
-
- status = (status: StatusCode): void => {
- this.#isFresh = false
- this.#status = status
- }
-
- /**
- * `.set()` can set the value specified by the key.
- * @example
- * ```ts
- * app.use('*', async (c, next) => {
- * c.set('message', 'Hono is cool!!')
- * await next()
- * })
- * ```
- * @see https://hono.dev/api/context#set-get
-```
- */
- set: Set = (key: string, value: unknown) => {
- this._var ??= {}
- this._var[key as string] = value
- }
-
- /**
- * `.get()` can use the value specified by the key.
- * @example
- * ```ts
- * app.get('/', (c) => {
- * const message = c.get('message')
- * return c.text(`The message is "${message}"`)
- * })
- * ```
- * @see https://hono.dev/api/context#set-get
- */
- get: Get = (key: string) => {
- return this._var ? this._var[key] : undefined
- }
-
- /**
- * `.var` can access the value of a variable.
- * @example
- * ```ts
- * const result = c.var.client.oneMethod()
- * ```
- * @see https://hono.dev/api/context#var
- */
- // c.var.propName is a read-only
- get var(): Readonly<
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ContextVariableMap & (IsAny extends true ? Record : E['Variables'])
- > {
- return { ...this._var } as never
- }
-
- newResponse: NewResponse = (
- data: Data | null,
- arg?: StatusCode | ResponseInit,
- headers?: HeaderRecord
- ): Response => {
- // Optimized
- if (this.#isFresh && !headers && !arg && this.#status === 200) {
- return new Response(data, {
- headers: this.#preparedHeaders,
- })
- }
-
- if (arg && typeof arg !== 'number') {
- const header = new Headers(arg.headers)
- if (this.#headers) {
- // If the header is set by c.header() and arg.headers, c.header() will be prioritized.
- this.#headers.forEach((v, k) => {
- header.set(k, v)
- })
- }
- const headers = setHeaders(header, this.#preparedHeaders)
- return new Response(data, {
- headers,
- status: arg.status ?? this.#status,
- })
- }
-
- const status = typeof arg === 'number' ? arg : this.#status
- this.#preparedHeaders ??= {}
-
- this.#headers ??= new Headers()
- setHeaders(this.#headers, this.#preparedHeaders)
-
- if (this.#res) {
- this.#res.headers.forEach((v, k) => {
- if (k === 'set-cookie') {
- this.#headers?.append(k, v)
- } else {
- this.#headers?.set(k, v)
- }
- })
- setHeaders(this.#headers, this.#preparedHeaders)
- }
-
- headers ??= {}
- for (const [k, v] of Object.entries(headers)) {
- if (typeof v === 'string') {
- this.#headers.set(k, v)
- } else {
- this.#headers.delete(k)
- for (const v2 of v) {
- this.#headers.append(k, v2)
- }
- }
- }
-
- return new Response(data, {
- status,
- headers: this.#headers,
- })
- }
-
- /**
- * `.body()` can return the HTTP response.
- * You can set headers with `.header()` and set HTTP status code with `.status`.
- * This can also be set in `.text()`, `.json()` and so on.
- * @example
- * ```ts
- * app.get('/welcome', (c) => {
- * // Set headers
- * c.header('X-Message', 'Hello!')
- * c.header('Content-Type', 'text/plain')
- * // Set HTTP status code
- * c.status(201)
- *
- * // Return the response body
- * return c.body('Thank you for coming')
- * })
- * ```
- * @see https://hono.dev/api/context#body
- */
- body: BodyRespond = (
- data: Data | null,
- arg?: StatusCode | ResponseInit,
- headers?: HeaderRecord
- ): Response => {
- return typeof arg === 'number'
- ? this.newResponse(data, arg, headers)
- : this.newResponse(data, arg)
- }
-
- /**
- * `.text()` can render text as `Content-Type:text/plain`.
- * @example
- * ```ts
- * app.get('/say', (c) => {
- * return c.text('Hello!')
- * })
- * ```
- * @see https://hono.dev/api/context#text
- */
- text: TextRespond = (
- text: string,
- arg?: StatusCode | ResponseInit,
- headers?: HeaderRecord
- ): ReturnType => {
- // If the header is empty, return Response immediately.
- // Content-Type will be added automatically as `text/plain`.
- if (!this.#preparedHeaders) {
- if (this.#isFresh && !headers && !arg) {
- // @ts-expect-error `Response` due to missing some types-only keys
- return new Response(text)
- }
- this.#preparedHeaders = {}
- }
- this.#preparedHeaders['content-type'] = TEXT_PLAIN
- // @ts-expect-error `Response` due to missing some types-only keys
- return typeof arg === 'number'
- ? this.newResponse(text, arg, headers)
- : this.newResponse(text, arg)
- }
-
- /**
- * `.json()` can render JSON as `Content-Type:application/json`.
- * @example
- * ```ts
- * app.get('/api', (c) => {
- * return c.json({ message: 'Hello!' })
- * })
- * ```
- * @see https://hono.dev/api/context#json
- */
- json: JSONRespond = , U extends StatusCode>(
- object: T,
- arg?: U | ResponseInit,
- headers?: HeaderRecord
- ): ReturnType => {
- const body = JSON.stringify(object)
- this.#preparedHeaders ??= {}
- this.#preparedHeaders['content-type'] = 'application/json; charset=UTF-8'
- /* eslint-disable @typescript-eslint/no-explicit-any */
- return (
- typeof arg === 'number' ? this.newResponse(body, arg, headers) : this.newResponse(body, arg)
- ) as any
- }
-
- html: HTMLRespond = (
- html: string | Promise,
- arg?: StatusCode | ResponseInit,
- headers?: HeaderRecord
- ): Response | Promise => {
- this.#preparedHeaders ??= {}
- this.#preparedHeaders['content-type'] = 'text/html; charset=UTF-8'
-
- if (typeof html === 'object') {
- if (!(html instanceof Promise)) {
- html = (html as string).toString() // HtmlEscapedString object to string
- }
- if ((html as string | Promise) instanceof Promise) {
- return (html as unknown as Promise)
- .then((html) => resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}))
- .then((html) => {
- return typeof arg === 'number'
- ? this.newResponse(html, arg, headers)
- : this.newResponse(html, arg)
- })
- }
- }
-
- return typeof arg === 'number'
- ? this.newResponse(html as string, arg, headers)
- : this.newResponse(html as string, arg)
- }
-
- /**
- * `.redirect()` can Redirect, default status code is 302.
- * @example
- * ```ts
- * app.get('/redirect', (c) => {
- * return c.redirect('/')
- * })
- * app.get('/redirect-permanently', (c) => {
- * return c.redirect('/', 301)
- * })
- * ```
- * @see https://hono.dev/api/context#redirect
- */
- redirect = (location: string, status: RedirectStatusCode = 302): Response => {
- this.#headers ??= new Headers()
- this.#headers.set('Location', location)
- return this.newResponse(null, status)
- }
-
- /**
- * `.notFound()` can return the Not Found Response.
- * @example
- * ```ts
- * app.get('/notfound', (c) => {
- * return c.notFound()
- * })
- * ```
- * @see https://hono.dev/api/context#notfound
- */
- notFound = (): Response | Promise => {
- return this.notFoundHandler(this)
- }
-}
diff --git a/deno_dist/helper.ts b/deno_dist/helper.ts
deleted file mode 100644
index a3dd6d265c..0000000000
--- a/deno_dist/helper.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// This file is for Deno to import helpers from `hono/helper.ts`.
-export * from './helper/accepts/index.ts'
-export * from './helper/adapter/index.ts'
-export * from './helper/cookie/index.ts'
-export * from './helper/css/index.ts'
-export * from './helper/factory/index.ts'
-export * from './helper/html/index.ts'
-export * from './helper/streaming/index.ts'
-export * from './helper/testing/index.ts'
-export * from './helper/dev/index.ts'
-export * from './adapter/deno/ssg.ts'
-export * from './adapter/deno/websocket.ts'
-export { decode as jwtDecode, sign as jwtSign, verify as jwtVerify } from './middleware/jwt/index.ts'
diff --git a/deno_dist/helper/accepts/accepts.ts b/deno_dist/helper/accepts/accepts.ts
deleted file mode 100644
index bdf64fd934..0000000000
--- a/deno_dist/helper/accepts/accepts.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import type { Context } from '../../context.ts'
-
-export type AcceptHeader =
- | 'Accept'
- | 'Accept-Charset'
- | 'Accept-Encoding'
- | 'Accept-Language'
- | 'Accept-Patch'
- | 'Accept-Post'
- | 'Accept-Ranges'
-
-export interface Accept {
- type: string
- params: Record
- q: number
-}
-
-export interface acceptsConfig {
- header: AcceptHeader
- supports: string[]
- default: string
-}
-
-export interface acceptsOptions extends acceptsConfig {
- match?: (accepts: Accept[], config: acceptsConfig) => string
-}
-
-export const parseAccept = (acceptHeader: string): Accept[] => {
- // Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
- const accepts = acceptHeader.split(',') // ['text/html', 'application/xhtml+xml', 'application/xml;q=0.9', 'image/webp', '*/*;q=0.8']
- return accepts.map((accept) => {
- const [type, ...params] = accept.trim().split(';') // ['application/xml', 'q=0.9']
- const q = params.find((param) => param.startsWith('q=')) // 'q=0.9'
- return {
- type,
- params: params.reduce((acc, param) => {
- const [key, value] = param.split('=')
- return { ...acc, [key.trim()]: value.trim() }
- }, {}),
- q: q ? parseFloat(q.split('=')[1]) : 1,
- }
- })
-}
-
-export const defaultMatch = (accepts: Accept[], config: acceptsConfig): string => {
- const { supports, default: defaultSupport } = config
- const accept = accepts.sort((a, b) => b.q - a.q).find((accept) => supports.includes(accept.type))
- return accept ? accept.type : defaultSupport
-}
-
-/**
- * Match the accept header with the given options.
- * @example
- * ```ts
- * app.get('/users', (c) => {
- * const lang = accepts(c, {
- * header: 'Accept-Language',
- * supports: ['en', 'zh'],
- * default: 'en',
- * })
- * })
- * ```
- */
-export const accepts = (c: Context, options: acceptsOptions): string => {
- const acceptHeader = c.req.header(options.header)
- if (!acceptHeader) {
- return options.default
- }
- const accepts = parseAccept(acceptHeader)
- const match = options.match || defaultMatch
-
- return match(accepts, options)
-}
diff --git a/deno_dist/helper/accepts/index.ts b/deno_dist/helper/accepts/index.ts
deleted file mode 100644
index e7723d2af6..0000000000
--- a/deno_dist/helper/accepts/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { accepts } from './accepts.ts'
diff --git a/deno_dist/helper/adapter/index.ts b/deno_dist/helper/adapter/index.ts
deleted file mode 100644
index c9e46833a0..0000000000
--- a/deno_dist/helper/adapter/index.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import type { Context } from '../../context.ts'
-
-export type Runtime = 'node' | 'deno' | 'bun' | 'workerd' | 'fastly' | 'edge-light' | 'other'
-
-export const env = , C extends Context = Context<{}>>(
- c: C,
- runtime?: Runtime
-): T & C['env'] => {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const global = globalThis as any
- const globalEnv = global?.process?.env as T
-
- runtime ??= getRuntimeKey()
-
- const runtimeEnvHandlers: Record T> = {
- bun: () => globalEnv,
- node: () => globalEnv,
- 'edge-light': () => globalEnv,
- deno: () => {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- return Deno.env.toObject() as T
- },
- workerd: () => c.env,
- // On Fastly Compute, you can use the ConfigStore to manage user-defined data.
- fastly: () => ({} as T),
- other: () => ({} as T),
- }
-
- return runtimeEnvHandlers[runtime]()
-}
-
-export const getRuntimeKey = (): 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') {
- return 'workerd'
- }
- if (typeof global?.EdgeRuntime === 'string') {
- return 'edge-light'
- }
- if (global?.fastly !== undefined) {
- return 'fastly'
- }
- if (global?.process?.release?.name === 'node') {
- return 'node'
- }
-
- return 'other'
-}
diff --git a/deno_dist/helper/cookie/index.ts b/deno_dist/helper/cookie/index.ts
deleted file mode 100644
index 7c3840fac4..0000000000
--- a/deno_dist/helper/cookie/index.ts
+++ /dev/null
@@ -1,125 +0,0 @@
-import type { Context } from '../../context.ts'
-import { parse, parseSigned, serialize, serializeSigned } from '../../utils/cookie.ts'
-import type { CookieOptions, Cookie, SignedCookie, CookiePrefixOptions } from '../../utils/cookie.ts'
-
-interface GetCookie {
- (c: Context, key: string): string | undefined
- (c: Context): Cookie
- (c: Context, key: string, prefixOptions: CookiePrefixOptions): string | undefined
-}
-
-interface GetSignedCookie {
- (c: Context, secret: string | BufferSource, key: string): Promise
- (c: Context, secret: string): Promise
- (
- c: Context,
- secret: string | BufferSource,
- key: string,
- prefixOptions: CookiePrefixOptions
- ): Promise
-}
-
-export const getCookie: GetCookie = (c, key?, prefix?: CookiePrefixOptions) => {
- const cookie = c.req.raw.headers.get('Cookie')
- if (typeof key === 'string') {
- if (!cookie) {
- return undefined
- }
- let finalKey = key
- if (prefix === 'secure') {
- finalKey = '__Secure-' + key
- } else if (prefix === 'host') {
- finalKey = '__Host-' + key
- }
- const obj = parse(cookie, finalKey)
- return obj[finalKey]
- }
- if (!cookie) {
- return {}
- }
- const obj = parse(cookie)
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- return obj as any
-}
-
-export const getSignedCookie: GetSignedCookie = async (
- c,
- secret,
- key?,
- prefix?: CookiePrefixOptions
-) => {
- const cookie = c.req.raw.headers.get('Cookie')
- if (typeof key === 'string') {
- if (!cookie) {
- return undefined
- }
- let finalKey = key
- if (prefix === 'secure') {
- finalKey = '__Secure-' + key
- } else if (prefix === 'host') {
- finalKey = '__Host-' + key
- }
- const obj = await parseSigned(cookie, secret, finalKey)
- return obj[finalKey]
- }
- if (!cookie) {
- return {}
- }
- const obj = await parseSigned(cookie, secret)
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- return obj as any
-}
-
-export const setCookie = (c: Context, name: string, value: string, opt?: CookieOptions): void => {
- // Cookie names prefixed with __Secure- can be used only if they are set with the secure attribute.
- // Cookie names prefixed with __Host- can be used only if they are set with the secure attribute, must have a path of / (meaning any path at the host)
- // and must not have a Domain attribute.
- // Read more at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#cookie_prefixes'
- let cookie
- if (opt?.prefix === 'secure') {
- cookie = serialize('__Secure-' + name, value, { path: '/', ...opt, secure: true })
- } else if (opt?.prefix === 'host') {
- cookie = serialize('__Host-' + name, value, {
- ...opt,
- path: '/',
- secure: true,
- domain: undefined,
- })
- } else {
- cookie = serialize(name, value, { path: '/', ...opt })
- }
- c.header('set-cookie', cookie, { append: true })
-}
-
-export const setSignedCookie = async (
- c: Context,
- name: string,
- value: string,
- secret: string | BufferSource,
- opt?: CookieOptions
-): Promise => {
- let cookie
- if (opt?.prefix === 'secure') {
- cookie = await serializeSigned('__Secure-' + name, value, secret, {
- path: '/',
- ...opt,
- secure: true,
- })
- } else if (opt?.prefix === 'host') {
- cookie = await serializeSigned('__Host-' + name, value, secret, {
- ...opt,
- path: '/',
- secure: true,
- domain: undefined,
- })
- } else {
- cookie = await serializeSigned(name, value, secret, { path: '/', ...opt })
- }
- c.header('set-cookie', cookie, { append: true })
-}
-
-export const deleteCookie = (c: Context, name: string, opt?: CookieOptions): string | undefined => {
- const deletedCookie = getCookie(c, name)
- setCookie(c, name, '', { ...opt, maxAge: 0 })
- return deletedCookie
-}
diff --git a/deno_dist/helper/css/common.ts b/deno_dist/helper/css/common.ts
deleted file mode 100644
index aff38a2806..0000000000
--- a/deno_dist/helper/css/common.ts
+++ /dev/null
@@ -1,243 +0,0 @@
-// provide utility functions for css helper both on server and client
-export const PSEUDO_GLOBAL_SELECTOR = ':-hono-global'
-export const isPseudoGlobalSelectorRe = new RegExp(`^${PSEUDO_GLOBAL_SELECTOR}{(.*)}$`)
-export const DEFAULT_STYLE_ID = 'hono-css'
-
-export const SELECTOR: unique symbol = Symbol()
-export const CLASS_NAME: unique symbol = Symbol()
-export const STYLE_STRING: unique symbol = Symbol()
-export const SELECTORS: unique symbol = Symbol()
-export const EXTERNAL_CLASS_NAMES: unique symbol = Symbol()
-const CSS_ESCAPED: unique symbol = Symbol()
-
-export interface CssClassName {
- [SELECTOR]: string
- [CLASS_NAME]: string
- [STYLE_STRING]: string
- [SELECTORS]: CssClassName[]
- [EXTERNAL_CLASS_NAMES]: string[]
-}
-
-export const IS_CSS_ESCAPED = Symbol()
-
-interface CssEscapedString {
- [CSS_ESCAPED]: string
-}
-
-/**
- * @experimental
- * `rawCssString` is an experimental feature.
- * The API might be changed.
- */
-export const rawCssString = (value: string): CssEscapedString => {
- return {
- [CSS_ESCAPED]: value,
- }
-}
-
-/**
- * Used the goober'code as a reference:
- * https://github.com/cristianbote/goober/blob/master/src/core/to-hash.js
- * MIT License, Copyright (c) 2019 Cristian Bote
- */
-const toHash = (str: string): string => {
- let i = 0,
- out = 11
- while (i < str.length) {
- out = (101 * out + str.charCodeAt(i++)) >>> 0
- }
- return 'css-' + out
-}
-
-const cssStringReStr: string = [
- '"(?:(?:\\\\[\\s\\S]|[^"\\\\])*)"', // double quoted string
- // eslint-disable-next-line quotes
- "'(?:(?:\\\\[\\s\\S]|[^'\\\\])*)'", // single quoted string
-].join('|')
-const minifyCssRe: RegExp = new RegExp(
- [
- '(' + cssStringReStr + ')', // $1: quoted string
-
- '(?:' +
- [
- '^\\s+', // head whitespace
- '\\/\\*.*?\\*\\/\\s*', // multi-line comment
- '\\/\\/.*\\n\\s*', // single-line comment
- '\\s+$', // tail whitespace
- ].join('|') +
- ')',
-
- '\\s*;\\s*(}|$)\\s*', // $2: trailing semicolon
- '\\s*([{};:,])\\s*', // $3: whitespace around { } : , ;
- '(\\s)\\s+', // $4: 2+ spaces
- ].join('|'),
- 'g'
-)
-
-export const minify = (css: string): string => {
- return css.replace(minifyCssRe, (_, $1, $2, $3, $4) => $1 || $2 || $3 || $4 || '')
-}
-
-type CssVariableBasicType =
- | CssClassName
- | CssEscapedString
- | string
- | number
- | boolean
- | null
- | undefined
-type CssVariableAsyncType = Promise
-type CssVariableArrayType = (CssVariableBasicType | CssVariableAsyncType)[]
-export type CssVariableType = CssVariableBasicType | CssVariableAsyncType | CssVariableArrayType
-
-export const buildStyleString = (
- strings: TemplateStringsArray,
- values: CssVariableType[]
-): [string, string, CssClassName[], string[]] => {
- const selectors: CssClassName[] = []
- const externalClassNames: string[] = []
-
- const label = strings[0].match(/^\s*\/\*(.*?)\*\//)?.[1] || ''
- let styleString = ''
- for (let i = 0, len = strings.length; i < len; i++) {
- styleString += strings[i]
- let vArray = values[i]
- if (typeof vArray === 'boolean' || vArray === null || vArray === undefined) {
- continue
- }
-
- if (!Array.isArray(vArray)) {
- vArray = [vArray]
- }
- for (let j = 0, len = vArray.length; j < len; j++) {
- let value = vArray[j]
- if (typeof value === 'boolean' || value === null || value === undefined) {
- continue
- }
- if (typeof value === 'string') {
- if (/([\\"'\/])/.test(value)) {
- styleString += value.replace(/([\\"']|(?<=<)\/)/g, '\\$1')
- } else {
- styleString += value
- }
- } else if (typeof value === 'number') {
- styleString += value
- } else if ((value as CssEscapedString)[CSS_ESCAPED]) {
- styleString += (value as CssEscapedString)[CSS_ESCAPED]
- } else if ((value as CssClassName)[CLASS_NAME].startsWith('@keyframes ')) {
- selectors.push(value as CssClassName)
- styleString += ` ${(value as CssClassName)[CLASS_NAME].substring(11)} `
- } else {
- if (strings[i + 1]?.match(/^\s*{/)) {
- // assume this value is a class name
- selectors.push(value as CssClassName)
- value = `.${(value as CssClassName)[CLASS_NAME]}`
- } else {
- selectors.push(...(value as CssClassName)[SELECTORS])
- externalClassNames.push(...(value as CssClassName)[EXTERNAL_CLASS_NAMES])
- value = (value as CssClassName)[STYLE_STRING]
- const valueLen = value.length
- if (valueLen > 0) {
- const lastChar = value[valueLen - 1]
- if (lastChar !== ';' && lastChar !== '}') {
- value += ';'
- }
- }
- }
- styleString += `${value || ''}`
- }
- }
- }
-
- return [label, minify(styleString), selectors, externalClassNames]
-}
-
-export const cssCommon = (
- strings: TemplateStringsArray,
- values: CssVariableType[]
-): CssClassName => {
- let [label, thisStyleString, selectors, externalClassNames] = buildStyleString(strings, values)
- const isPseudoGlobal = isPseudoGlobalSelectorRe.exec(thisStyleString)
- if (isPseudoGlobal) {
- thisStyleString = isPseudoGlobal[1]
- }
- const selector = (isPseudoGlobal ? PSEUDO_GLOBAL_SELECTOR : '') + toHash(label + thisStyleString)
- const className = (
- isPseudoGlobal ? selectors.map((s) => s[CLASS_NAME]) : [selector, ...externalClassNames]
- ).join(' ')
-
- return {
- [SELECTOR]: selector,
- [CLASS_NAME]: className,
- [STYLE_STRING]: thisStyleString,
- [SELECTORS]: selectors,
- [EXTERNAL_CLASS_NAMES]: externalClassNames,
- }
-}
-
-export const cxCommon = (
- args: (string | boolean | null | undefined | CssClassName)[]
-): (string | boolean | null | undefined | CssClassName)[] => {
- for (let i = 0, len = args.length; i < len; i++) {
- const arg = args[i]
- if (typeof arg === 'string') {
- args[i] = {
- [SELECTOR]: '',
- [CLASS_NAME]: '',
- [STYLE_STRING]: '',
- [SELECTORS]: [],
- [EXTERNAL_CLASS_NAMES]: [arg],
- }
- }
- }
-
- return args
-}
-
-export const keyframesCommon = (
- strings: TemplateStringsArray,
- ...values: CssVariableType[]
-): CssClassName => {
- const [label, styleString] = buildStyleString(strings, values)
- return {
- [SELECTOR]: '',
- [CLASS_NAME]: `@keyframes ${toHash(label + styleString)}`,
- [STYLE_STRING]: styleString,
- [SELECTORS]: [],
- [EXTERNAL_CLASS_NAMES]: [],
- }
-}
-
-type ViewTransitionType = {
- (strings: TemplateStringsArray, values: CssVariableType[]): CssClassName
- (content: CssClassName): CssClassName
- (): CssClassName
-}
-
-let viewTransitionNameIndex = 0
-export const viewTransitionCommon: ViewTransitionType = ((
- strings: TemplateStringsArray | CssClassName | undefined,
- values: CssVariableType[]
-): CssClassName => {
- if (!strings) {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- strings = [`/* h-v-t ${viewTransitionNameIndex++} */`] as any
- }
- const content = Array.isArray(strings)
- ? cssCommon(strings as TemplateStringsArray, values)
- : (strings as CssClassName)
-
- const transitionName = content[CLASS_NAME]
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const res = cssCommon(['view-transition-name:', ''] as any, [transitionName])
-
- content[CLASS_NAME] = PSEUDO_GLOBAL_SELECTOR + content[CLASS_NAME]
- content[STYLE_STRING] = content[STYLE_STRING].replace(
- /(?<=::view-transition(?:[a-z-]*)\()(?=\))/g,
- transitionName
- )
- res[CLASS_NAME] = res[SELECTOR] = transitionName
- res[SELECTORS] = [...content[SELECTORS], content]
-
- return res
-}) as ViewTransitionType
diff --git a/deno_dist/helper/css/index.ts b/deno_dist/helper/css/index.ts
deleted file mode 100644
index 33d53e6199..0000000000
--- a/deno_dist/helper/css/index.ts
+++ /dev/null
@@ -1,215 +0,0 @@
-import { raw } from '../../helper/html/index.ts'
-import { DOM_RENDERER } from '../../jsx/constants.ts'
-import { createCssJsxDomObjects } from '../../jsx/dom/css.ts'
-import type { HtmlEscapedCallback, HtmlEscapedString } from '../../utils/html.ts'
-import type { CssClassName as CssClassNameCommon, CssVariableType } from './common.ts'
-import {
- SELECTOR,
- CLASS_NAME,
- STYLE_STRING,
- SELECTORS,
- PSEUDO_GLOBAL_SELECTOR,
- DEFAULT_STYLE_ID,
- cssCommon,
- cxCommon,
- keyframesCommon,
- viewTransitionCommon,
-} from './common.ts'
-export { rawCssString } from './common.ts'
-
-type CssClassName = HtmlEscapedString & CssClassNameCommon
-
-type usedClassNameData = [
- Record, // class name to add
- Record // class name already added
-]
-
-interface CssType {
- (strings: TemplateStringsArray, ...values: CssVariableType[]): Promise
-}
-
-interface CxType {
- (
- ...args: (CssClassName | Promise | string | boolean | null | undefined)[]
- ): Promise
-}
-
-interface KeyframesType {
- (strings: TemplateStringsArray, ...values: CssVariableType[]): CssClassNameCommon
-}
-
-interface ViewTransitionType {
- (strings: TemplateStringsArray, ...values: CssVariableType[]): Promise
- (content: Promise): Promise
- (): Promise
-}
-
-interface StyleType {
- (args?: { children?: Promise }): HtmlEscapedString
-}
-
-/**
- * @experimental
- * `createCssContext` is an experimental feature.
- * The API might be changed.
- */
-export const createCssContext = ({ id }: { id: Readonly }): DefaultContextType => {
- const [cssJsxDomObject, StyleRenderToDom] = createCssJsxDomObjects({ id })
-
- const contextMap: WeakMap = new WeakMap()
-
- const replaceStyleRe = new RegExp(`()`)
-
- const newCssClassNameObject = (cssClassName: CssClassNameCommon): Promise => {
- const appendStyle: HtmlEscapedCallback = ({ buffer, context }): Promise | undefined => {
- const [toAdd, added] = contextMap.get(context) as usedClassNameData
- const names = Object.keys(toAdd)
-
- if (!names.length) {
- return
- }
-
- let stylesStr = ''
- names.forEach((className) => {
- added[className] = true
- stylesStr += className.startsWith(PSEUDO_GLOBAL_SELECTOR)
- ? toAdd[className]
- : `${className[0] === '@' ? '' : '.'}${className}{${toAdd[className]}}`
- })
- contextMap.set(context, [{}, added])
-
- if (buffer && replaceStyleRe.test(buffer[0])) {
- buffer[0] = buffer[0].replace(replaceStyleRe, (_, pre, post) => `${pre}${stylesStr}${post}`)
- return
- }
-
- const appendStyleScript = ``
- if (buffer) {
- buffer[0] = `${appendStyleScript}${buffer[0]}`
- return
- }
-
- return Promise.resolve(appendStyleScript)
- }
-
- const addClassNameToContext: HtmlEscapedCallback = ({ context }) => {
- if (!contextMap.get(context)) {
- contextMap.set(context, [{}, {}])
- }
- const [toAdd, added] = contextMap.get(context) as usedClassNameData
- let allAdded = true
- if (!added[cssClassName[SELECTOR]]) {
- allAdded = false
- toAdd[cssClassName[SELECTOR]] = cssClassName[STYLE_STRING]
- }
- cssClassName[SELECTORS].forEach(
- ({ [CLASS_NAME]: className, [STYLE_STRING]: styleString }) => {
- if (!added[className]) {
- allAdded = false
- toAdd[className] = styleString
- }
- }
- )
- if (allAdded) {
- return
- }
-
- return Promise.resolve(raw('', [appendStyle]))
- }
-
- const className = new String(cssClassName[CLASS_NAME]) as CssClassName
- Object.assign(className, cssClassName)
- ;(className as HtmlEscapedString).isEscaped = true
- ;(className as HtmlEscapedString).callbacks = [addClassNameToContext]
- const promise = Promise.resolve(className)
- Object.assign(promise, cssClassName)
- // eslint-disable-next-line @typescript-eslint/unbound-method
- promise.toString = cssJsxDomObject.toString
- return promise
- }
-
- const css: CssType = (strings, ...values) => {
- return newCssClassNameObject(cssCommon(strings, values))
- }
-
- const cx: CxType = (...args) => {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- args = cxCommon(args as any) as any
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- return css(Array(args.length).fill('') as any, ...args)
- }
-
- const keyframes = keyframesCommon
-
- const viewTransition: ViewTransitionType = ((
- strings: TemplateStringsArray | Promise | undefined,
- ...values: CssVariableType[]
- ) => {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- return newCssClassNameObject(viewTransitionCommon(strings as any, values))
- }) as ViewTransitionType
-
- const Style: StyleType = ({ children } = {}) =>
- children
- ? raw(``)
- : raw(``)
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ;(Style as any)[DOM_RENDERER] = StyleRenderToDom
-
- return {
- css,
- cx,
- keyframes,
- viewTransition: viewTransition as ViewTransitionType,
- Style,
- }
-}
-
-interface DefaultContextType {
- css: CssType
- cx: CxType
- keyframes: KeyframesType
- viewTransition: ViewTransitionType
- Style: StyleType
-}
-
-const defaultContext: DefaultContextType = createCssContext({
- id: DEFAULT_STYLE_ID,
-})
-
-/**
- * @experimental
- * `css` is an experimental feature.
- * The API might be changed.
- */
-export const css = defaultContext.css
-
-/**
- * @experimental
- * `cx` is an experimental feature.
- * The API might be changed.
- */
-export const cx = defaultContext.cx
-
-/**
- * @experimental
- * `keyframes` is an experimental feature.
- * The API might be changed.
- */
-export const keyframes = defaultContext.keyframes
-
-/**
- * @experimental
- * `viewTransition` is an experimental feature.
- * The API might be changed.
- */
-export const viewTransition = defaultContext.viewTransition
-
-/**
- * @experimental
- * `Style` is an experimental feature.
- * The API might be changed.
- */
-export const Style = defaultContext.Style
diff --git a/deno_dist/helper/dev/index.ts b/deno_dist/helper/dev/index.ts
deleted file mode 100644
index 7ba8613ee3..0000000000
--- a/deno_dist/helper/dev/index.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import type { Hono } from '../../hono.ts'
-import type { Env, RouterRoute } from '../../types.ts'
-import { getColorEnabled } from '../../utils/color.ts'
-import { findTargetHandler, isMiddleware } from '../../utils/handler.ts'
-
-interface ShowRoutesOptions {
- verbose?: boolean
- colorize?: boolean
-}
-
-interface RouteData {
- path: string
- method: string
- name: string
- isMiddleware: boolean
-}
-
-const handlerName = (handler: Function): string => {
- return handler.name || (isMiddleware(handler) ? '[middleware]' : '[handler]')
-}
-
-export const inspectRoutes = (hono: Hono): RouteData[] => {
- return hono.routes.map(({ path, method, handler }: RouterRoute) => {
- const targetHandler = findTargetHandler(handler)
- return {
- path,
- method,
- name: handlerName(targetHandler),
- isMiddleware: isMiddleware(targetHandler),
- }
- })
-}
-
-export const showRoutes = (hono: Hono, opts?: ShowRoutesOptions) => {
- const colorEnabled = opts?.colorize ?? getColorEnabled()
- const routeData: Record = {}
- let maxMethodLength = 0
- let maxPathLength = 0
-
- inspectRoutes(hono)
- .filter(({ isMiddleware }) => opts?.verbose || !isMiddleware)
- .map((route) => {
- const key = `${route.method}-${route.path}`
- ;(routeData[key] ||= []).push(route)
- if (routeData[key].length > 1) {
- return
- }
- maxMethodLength = Math.max(maxMethodLength, route.method.length)
- maxPathLength = Math.max(maxPathLength, route.path.length)
- return { method: route.method, path: route.path, routes: routeData[key] }
- })
- .forEach((data) => {
- if (!data) {
- return
- }
- const { method, path, routes } = data
-
- const methodStr = colorEnabled ? `\x1b[32m${method}\x1b[0m` : method
- console.log(`${methodStr} ${' '.repeat(maxMethodLength - method.length)} ${path}`)
-
- if (!opts?.verbose) {
- return
- }
-
- routes.forEach(({ name }) => {
- console.log(`${' '.repeat(maxMethodLength + 3)} ${name}`)
- })
- })
-}
-
-export const getRouterName = (app: Hono): string => {
- app.router.match('GET', '/')
- return app.router.name
-}
diff --git a/deno_dist/helper/factory/index.ts b/deno_dist/helper/factory/index.ts
deleted file mode 100644
index 2478031a72..0000000000
--- a/deno_dist/helper/factory/index.ts
+++ /dev/null
@@ -1,241 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import { Hono } from '../../hono.ts'
-import type { Env, H, HandlerResponse, Input, MiddlewareHandler } from '../../types.ts'
-
-type InitApp = (app: Hono) => void
-
-interface CreateHandlersInterface {
- = any>(handler1: H): [
- H
- ]
- // handler x2
- = any>(
- handler1: H,
- handler2: H
- ): [H, H]
-
- // handler x3
- <
- I extends Input = {},
- I2 extends Input = I,
- I3 extends Input = I & I2,
- R extends HandlerResponse = any
- >(
- handler1: H,
- handler2: H,
- handler3: H
- ): [H, H, H]
-
- // handler x4
- <
- I extends Input = {},
- I2 extends Input = I,
- I3 extends Input = I & I2,
- I4 extends Input = I & I2 & I3,
- R extends HandlerResponse = any
- >(
- handler1: H,
- handler2: H,
- handler3: H,
- handler4: H
- ): [H, H, H, H]
-
- // handler x5
- <
- I extends Input = {},
- I2 extends Input = I,
- I3 extends Input = I & I2,
- I4 extends Input = I & I2 & I3,
- I5 extends Input = I & I2 & I3 & I4,
- R extends HandlerResponse = any
- >(
- handler1: H,
- handler2: H,
- handler3: H,
- handler4: H,
- handler5: H
- ): [H, H, H, H, H]
-
- // handler x6
- <
- I extends Input = {},
- I2 extends Input = I,
- I3 extends Input = I & I2,
- I4 extends Input = I & I2 & I3,
- I5 extends Input = I & I2 & I3 & I4,
- I6 extends Input = I & I2 & I3 & I4 & I5,
- R extends HandlerResponse = any
- >(
- handler1: H,
- handler2: H,
- handler3: H,
- handler4: H,
- handler5: H,
- handler6: H
- ): [H, H, H, H, H, H]
-
- // handler x7
- <
- I extends Input = {},
- I2 extends Input = I,
- I3 extends Input = I & I2,
- I4 extends Input = I & I2 & I3,
- I5 extends Input = I & I2 & I3 & I4,
- I6 extends Input = I & I2 & I3 & I4 & I5,
- I7 extends Input = I & I2 & I3 & I4 & I5 & I6,
- R extends HandlerResponse = any
- >(
- handler1: H,
- handler2: H,
- handler3: H,
- handler4: H,
- handler5: H,
- handler6: H,
- handler7: H
- ): [
- H,
- H,
- H,
- H,
- H,
- H,
- H
- ]
-
- // handler x8
- <
- I extends Input = {},
- I2 extends Input = I,
- I3 extends Input = I & I2,
- I4 extends Input = I & I2 & I3,
- I5 extends Input = I & I2 & I3 & I4,
- I6 extends Input = I & I2 & I3 & I4 & I5,
- I7 extends Input = I & I2 & I3 & I4 & I5 & I6,
- I8 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7,
- R extends HandlerResponse = any
- >(
- handler1: H,
- handler2: H,
- handler3: H,
- handler4: H,
- handler5: H,
- handler6: H,
- handler7: H,
- handler8: H
- ): [
- H,
- H,
- H,
- H,
- H,
- H,
- H,
- H
- ]
-
- // handler x9
- <
- I extends Input = {},
- I2 extends Input = I,
- I3 extends Input = I & I2,
- I4 extends Input = I & I2 & I3,
- I5 extends Input = I & I2 & I3 & I4,
- I6 extends Input = I & I2 & I3 & I4 & I5,
- I7 extends Input = I & I2 & I3 & I4 & I5 & I6,
- I8 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7,
- I9 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7 & I8,
- R extends HandlerResponse = any
- >(
- handler1: H,
- handler2: H,
- handler3: H,
- handler4: H,
- handler5: H,
- handler6: H,
- handler7: H,
- handler8: H,
- handler9: H
- ): [
- H,
- H,
- H,
- H,
- H,
- H,
- H,
- H,
- H
- ]
-
- // handler x10
- <
- I extends Input = {},
- I2 extends Input = I,
- I3 extends Input = I & I2,
- I4 extends Input = I & I2 & I3,
- I5 extends Input = I & I2 & I3 & I4,
- I6 extends Input = I & I2 & I3 & I4 & I5,
- I7 extends Input = I & I2 & I3 & I4 & I5 & I6,
- I8 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7,
- I9 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7 & I8,
- I10 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7 & I8 & I9,
- R extends HandlerResponse = any
- >(
- handler1: H