Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(types): Add DefaultEnv for zero runtime factory #3819

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions jsr.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@
"./deno": "./src/adapter/deno/index.ts",
"./bun": "./src/adapter/bun/index.ts",
"./aws-lambda": "./src/adapter/aws-lambda/index.ts",
"./aws-lambda/alb": "./src/adapter/aws-lambda/alb.ts",
"./aws-lambda/api-gateway":"./src/adapter/aws-lambda/api-gateway.ts",
"./aws-lambda/api-gateway-v2":"./src/adapter/aws-lambda/api-gateway-v2.ts",
"./vercel": "./src/adapter/vercel/index.ts",
"./netlify": "./src/adapter/netlify/index.ts",
"./lambda-edge": "./src/adapter/lambda-edge/index.ts",
Expand Down
24 changes: 24 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,21 @@
"import": "./dist/adapter/aws-lambda/index.js",
"require": "./dist/cjs/adapter/aws-lambda/index.js"
},
"./aws-lambda/alb": {
"types": "./dist/types/adapter/aws-lambda/alb.d.ts",
"import": "./dist/adapter/aws-lambda/alb.js",
"require": "./dist/cjs/adapter/aws-lambda/alb.js"
},
"./aws-lambda/api-gateway": {
"types": "./dist/types/adapter/aws-lambda/api-gateway.d.ts",
"import": "./dist/adapter/aws-lambda/api-gateway.js",
"require": "./dist/cjs/adapter/aws-lambda/api-gateway.js"
},
"./aws-lambda/api-gateway-v2": {
"types": "./dist/types/adapter/aws-lambda/api-gateway-v2.d.ts",
"import": "./dist/adapter/aws-lambda/api-gateway-v2.js",
"require": "./dist/cjs/adapter/aws-lambda/api-gateway-v2.js"
},
"./vercel": {
"types": "./dist/types/adapter/vercel/index.d.ts",
"import": "./dist/adapter/vercel/index.js",
Expand Down Expand Up @@ -575,6 +590,15 @@
"aws-lambda": [
"./dist/types/adapter/aws-lambda"
],
"aws-lambda/alb": [
"./dist/types/adapter/aws-lambda/alb.d.ts"
],
"aws-lambda/api-gateway":[
"./dist/types/adapter/aws-lambda/api-gateway.d.ts"
],
"aws-lambda/api-gateway-v2":[
"./dist/types/adapter/aws-lambda/api-gateway-v2.d.ts"
],
"vercel": [
"./dist/types/adapter/vercel"
],
Expand Down
24 changes: 24 additions & 0 deletions src/adapter/aws-lambda/alb.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @module
* AWS Lambda Adapter for Hono. Invoked by ALB Event.
*/

export { handle, streamHandle } from './handler'
export type { APIGatewayProxyResult, ALBProxyEvent } from './handler'
export type { ALBRequestContext, LambdaContext } from './types'

import type { ALBProxyEvent } from './handler'
import type { LambdaContext } from './types'

declare module '../../types' {

Check failure on line 13 in src/adapter/aws-lambda/alb.ts

View workflow job for this annotation

GitHub Actions / Checking if it's valid for JSR

found an ambient module, which is a global augmentation, which are not unsupported
interface DefaultEnv {
Bindings: DefaultBindings
}

interface DefaultBindings {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore On development, this line will raise an error because of interface merging.
event: ALBProxyEvent
lambdaContext: LambdaContext
}
}
24 changes: 24 additions & 0 deletions src/adapter/aws-lambda/api-gateway-v2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @module
* AWS Lambda Adapter for Hono. Invoked by AWS API Gateway Proxy Event V2.
*/

export { handle, streamHandle } from './handler'
export type { APIGatewayProxyResult, APIGatewayProxyEventV2 } from './handler'
export type { ApiGatewayRequestContext, LambdaContext } from './types'

import type { APIGatewayProxyEventV2 } from './handler'
import type { LambdaContext } from './types'

declare module '../../types' {

Check failure on line 13 in src/adapter/aws-lambda/api-gateway-v2.ts

View workflow job for this annotation

GitHub Actions / Checking if it's valid for JSR

found an ambient module, which is a global augmentation, which are not unsupported
interface DefaultEnv {
Bindings: DefaultBindings
}

interface DefaultBindings {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore On development, this line will raise an error because of interface merging.
event: APIGatewayProxyEventV2
lambdaContext: LambdaContext
}
}
24 changes: 24 additions & 0 deletions src/adapter/aws-lambda/api-gateway.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @module
* AWS Lambda Adapter for Hono. Invoked by AWS API Gateway Proxy Event.
*/

export { handle, streamHandle } from './handler'
export type { APIGatewayProxyResult, APIGatewayProxyEvent } from './handler'
export type { ApiGatewayRequestContextV2, LambdaContext } from './types'

import type { APIGatewayProxyEvent } from './handler'
import type { LambdaContext } from './types'

declare module '../../types' {

Check failure on line 13 in src/adapter/aws-lambda/api-gateway.ts

View workflow job for this annotation

GitHub Actions / Checking if it's valid for JSR

found an ambient module, which is a global augmentation, which are not unsupported
interface DefaultEnv {
Bindings: DefaultBindings
}

interface DefaultBindings {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore On development, this line will raise an error because of interface merging.
event: APIGatewayProxyEvent
lambdaContext: LambdaContext
}
}
10 changes: 7 additions & 3 deletions src/adapter/aws-lambda/handler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import crypto from 'node:crypto'
import type { Hono } from '../../hono'
import type { Env, Schema } from '../../types'
import type { DefaultEnv, Env, Schema } from '../../types'
import { decodeBase64, encodeBase64 } from '../../utils/encode'
import type {
ALBRequestContext,
Expand Down Expand Up @@ -106,7 +106,7 @@
}

export const streamHandle = <
E extends Env = Env,
E extends Env = DefaultEnv,
S extends Schema = {},
BasePath extends string = '/'
>(
Expand Down Expand Up @@ -165,7 +165,11 @@
/**
* Accepts events from API Gateway/ELB(`APIGatewayProxyEvent`) and directly through Function Url(`APIGatewayProxyEventV2`)
*/
export const handle = <E extends Env = Env, S extends Schema = {}, BasePath extends string = '/'>(
export const handle = <
E extends Env = DefaultEnv,
S extends Schema = {},
BasePath extends string = '/'
>(
app: Hono<E, S, BasePath>
): ((event: LambdaEvent, lambdaContext?: LambdaContext) => Promise<APIGatewayProxyResult>) => {
return async (event, lambdaContext?) => {
Expand Down Expand Up @@ -341,9 +345,9 @@

protected getCookies(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
event: Exclude<LambdaEvent, APIGatewayProxyEventV2>,

Check failure on line 348 in src/adapter/aws-lambda/handler.ts

View workflow job for this annotation

GitHub Actions / Main

'event' is declared but its value is never read.

Check failure on line 348 in src/adapter/aws-lambda/handler.ts

View workflow job for this annotation

GitHub Actions / Node.js v18.18.2

'event' is declared but its value is never read.

Check failure on line 348 in src/adapter/aws-lambda/handler.ts

View workflow job for this annotation

GitHub Actions / workerd

'event' is declared but its value is never read.

Check failure on line 348 in src/adapter/aws-lambda/handler.ts

View workflow job for this annotation

GitHub Actions / Node.js v20.x

'event' is declared but its value is never read.

Check failure on line 348 in src/adapter/aws-lambda/handler.ts

View workflow job for this annotation

GitHub Actions / Node.js v22.x

'event' is declared but its value is never read.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
headers: Headers

Check failure on line 350 in src/adapter/aws-lambda/handler.ts

View workflow job for this annotation

GitHub Actions / Main

'headers' is declared but its value is never read.

Check failure on line 350 in src/adapter/aws-lambda/handler.ts

View workflow job for this annotation

GitHub Actions / Node.js v18.18.2

'headers' is declared but its value is never read.

Check failure on line 350 in src/adapter/aws-lambda/handler.ts

View workflow job for this annotation

GitHub Actions / workerd

'headers' is declared but its value is never read.

Check failure on line 350 in src/adapter/aws-lambda/handler.ts

View workflow job for this annotation

GitHub Actions / Node.js v20.x

'headers' is declared but its value is never read.

Check failure on line 350 in src/adapter/aws-lambda/handler.ts

View workflow job for this annotation

GitHub Actions / Node.js v22.x

'headers' is declared but its value is never read.
): void {
// nop
}
Expand Down
8 changes: 4 additions & 4 deletions src/adapter/bun/serve-static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
import { stat } from 'node:fs/promises'
import { serveStatic as baseServeStatic } from '../../middleware/serve-static'
import type { ServeStaticOptions } from '../../middleware/serve-static'
import type { Env, MiddlewareHandler } from '../../types'
import type { DefaultEnv, Env, MiddlewareHandler } from '../../types'

export const serveStatic = <E extends Env = Env>(
export const serveStatic = <E extends Env = DefaultEnv>(
options: ServeStaticOptions<E>
): MiddlewareHandler => {
): MiddlewareHandler<E> => {
return async function serveStatic(c, next) {
const getContent = async (path: string) => {
path = path.startsWith('/') ? path : `./${path}`
Expand All @@ -25,7 +25,7 @@ export const serveStatic = <E extends Env = Env>(
} catch {}
return isDir
}
return baseServeStatic({
return baseServeStatic<E>({
...options,
getContent,
pathResolve,
Expand Down
2 changes: 1 addition & 1 deletion src/adapter/cloudflare-pages/handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ describe('Adapter for Cloudflare Pages', () => {
it('Should not use `basePath()` if path argument is not passed', async () => {
const request = new Request('http://localhost/api/error')
const eventContext = createEventContext({ request })
const app = new Hono().basePath('/api')
const app = new Hono<Env>().basePath('/api')

app.onError((e) => {
throw e
Expand Down
6 changes: 3 additions & 3 deletions src/adapter/cloudflare-pages/handler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Context } from '../../context'
import type { Hono } from '../../hono'
import { HTTPException } from '../../http-exception'
import type { BlankSchema, Env, Input, MiddlewareHandler, Schema } from '../../types'
import type { BlankSchema, DefaultEnv, Env, Input, MiddlewareHandler, Schema } from '../../types'

// Ref: https://github.com/cloudflare/workerd/blob/main/types/defines/pages.d.ts

Expand All @@ -28,7 +28,7 @@ declare type PagesFunction<
> = (context: EventContext<Env, Params, Data>) => Response | Promise<Response>

export const handle =
<E extends Env = Env, S extends Schema = BlankSchema, BasePath extends string = '/'>(
<E extends Env = DefaultEnv, S extends Schema = BlankSchema, BasePath extends string = '/'>(
app: Hono<E, S, BasePath>
): PagesFunction<E['Bindings']> =>
(eventContext) => {
Expand Down Expand Up @@ -110,7 +110,7 @@ declare abstract class FetcherLike {
*/
export const serveStatic = (): MiddlewareHandler => {
return async (c) => {
const env = c.env as { ASSETS: FetcherLike }
const env = c.env as unknown as { ASSETS: FetcherLike }
const res = await env.ASSETS.fetch(c.req.raw)
if (res.status === 404) {
return c.notFound()
Expand Down
12 changes: 12 additions & 0 deletions src/adapter/cloudflare-pages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,15 @@

export { handle, handleMiddleware, serveStatic } from './handler'
export type { EventContext } from './handler'
import type { EventContext } from './handler'

declare module '../../types' {

Check failure on line 10 in src/adapter/cloudflare-pages/index.ts

View workflow job for this annotation

GitHub Actions / Checking if it's valid for JSR

found an ambient module, which is a global augmentation, which are not unsupported
interface DefaultEnv {
Bindings: DefaultBindings
}

interface DefaultBindings {
eventContext: EventContext<DefaultEnv>
ASSETS: { fetch: typeof fetch }
}
}
6 changes: 3 additions & 3 deletions src/adapter/cloudflare-workers/serve-static-module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// For ES module mode
import type { Env, MiddlewareHandler } from '../../types'
import type { DefaultEnv, Env, MiddlewareHandler } from '../../types'
import type { ServeStaticOptions } from './serve-static'
import { serveStatic } from './serve-static'

const module = <E extends Env = Env>(
const module = <E extends Env = DefaultEnv>(
options: Omit<ServeStaticOptions<E>, 'namespace'>
): MiddlewareHandler => {
): MiddlewareHandler<E> => {
return serveStatic<E>(options)
}

Expand Down
13 changes: 7 additions & 6 deletions src/adapter/cloudflare-workers/serve-static.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { serveStatic as baseServeStatic } from '../../middleware/serve-static'
import type { ServeStaticOptions as BaseServeStaticOptions } from '../../middleware/serve-static'
import type { Env, MiddlewareHandler } from '../../types'
import type { DefaultEnv, Env, MiddlewareHandler } from '../../types'
import { getContentFromKVAsset } from './utils'

export type ServeStaticOptions<E extends Env = Env> = BaseServeStaticOptions<E> & {
export type ServeStaticOptions<E extends Env = DefaultEnv> = BaseServeStaticOptions<E> & {
// namespace is KVNamespace
namespace?: unknown
manifest: object | string
Expand All @@ -18,9 +18,9 @@ export type ServeStaticOptions<E extends Env = Env> = BaseServeStaticOptions<E>
* please consider using Cloudflare Pages. You can start to create the Cloudflare Pages
* application with the `npm create hono@latest` command.
*/
export const serveStatic = <E extends Env = Env>(
export const serveStatic = <E extends Env = DefaultEnv>(
options: ServeStaticOptions<E>
): MiddlewareHandler => {
): MiddlewareHandler<E> => {
return async function serveStatic(c, next) {
const getContent = async (path: string) => {
return getContentFromKVAsset(path, {
Expand All @@ -30,11 +30,12 @@ export const serveStatic = <E extends Env = Env>(
namespace: options.namespace
? options.namespace
: c.env
? c.env.__STATIC_CONTENT
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
(c.env as any).__STATIC_CONTENT
: undefined,
})
}
return baseServeStatic({
return baseServeStatic<E>({
...options,
getContent,
})(c, next)
Expand Down
8 changes: 4 additions & 4 deletions src/adapter/deno/serve-static.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { ServeStaticOptions } from '../../middleware/serve-static'
import { serveStatic as baseServeStatic } from '../../middleware/serve-static'
import type { Env, MiddlewareHandler } from '../../types'
import type { DefaultEnv, Env, MiddlewareHandler } from '../../types'

const { open, lstatSync, errors } = Deno

export const serveStatic = <E extends Env = Env>(
export const serveStatic = <E extends Env = DefaultEnv>(
options: ServeStaticOptions<E>
): MiddlewareHandler => {
): MiddlewareHandler<E> => {
return async function serveStatic(c, next) {
const getContent = async (path: string) => {
try {
Expand Down Expand Up @@ -35,7 +35,7 @@ export const serveStatic = <E extends Env = Env>(
return isDir
}

return baseServeStatic({
return baseServeStatic<E>({
...options,
getContent,
pathResolve,
Expand Down
25 changes: 25 additions & 0 deletions src/adapter/lambda-edge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,28 @@
CloudFrontResponse,
CloudFrontEdgeEvent,
} from './handler'

import type {
Callback,
CloudFrontConfig,
CloudFrontRequest,
CloudFrontResponse,
CloudFrontEdgeEvent,
} from './handler'

declare module '../../types' {

Check failure on line 24 in src/adapter/lambda-edge/index.ts

View workflow job for this annotation

GitHub Actions / Checking if it's valid for JSR

found an ambient module, which is a global augmentation, which are not unsupported
interface DefaultEnv {
Bindings: DefaultBindings
}

interface DefaultBindings {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore On development, this line will raise an error because of interface merging.
event: CloudFrontEdgeEvent
context?: {}
callback: Callback
config: CloudFrontConfig
request: CloudFrontRequest
response?: CloudFrontResponse
}
}
4 changes: 2 additions & 2 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ type ContextOptions<E extends Env> = {
* Handler for not found responses.
*/
notFoundHandler?: NotFoundHandler<E>
matchResult?: Result<[H, RouterRoute]>
matchResult?: Result<[H<E>, RouterRoute<E>]>
path?: string
}

Expand Down Expand Up @@ -339,7 +339,7 @@ export class Context<
#renderer: Renderer | undefined
#notFoundHandler: NotFoundHandler<E> | undefined

#matchResult: Result<[H, RouterRoute]> | undefined
#matchResult: Result<[H<E>, RouterRoute<E>]> | undefined
#path: string | undefined

/**
Expand Down
Loading
Loading