mirror of
https://github.com/honojs/hono.git
synced 2024-11-28 00:26:24 +01:00
feat: Introduce Service Worker Adapter (#3062)
* feat: Intoroduce service worker adapter * test: add test * chore: format code * refactor: handler.ts * chore: remove unused import * fix: add webworker to jsr.json * fix: triple slash directives to tsconfig.json * feat: add types.ts to define worker types
This commit is contained in:
parent
4a4e851d50
commit
c2698fa2e0
1
jsr.json
1
jsr.json
@ -71,6 +71,7 @@
|
||||
"./vercel": "./src/adapter/vercel/index.ts",
|
||||
"./netlify": "./src/adapter/netlify/index.ts",
|
||||
"./lambda-edge": "./src/adapter/lambda-edge/index.ts",
|
||||
"./service-worker": "./src/adapter/service-worker/index.ts",
|
||||
"./testing": "./src/helper/testing/index.ts",
|
||||
"./dev": "./src/helper/dev/index.ts",
|
||||
"./ws": "./src/helper/websocket/index.ts",
|
||||
|
@ -343,6 +343,11 @@
|
||||
"import": "./dist/adapter/lambda-edge/index.js",
|
||||
"require": "./dist/cjs/adapter/lambda-edge/index.js"
|
||||
},
|
||||
"./service-worker": {
|
||||
"types": "./dist/types/adapter/service-worker/index.d.ts",
|
||||
"import": "./dist/adapter/service-worker/index.js",
|
||||
"require": "./dist/cjs/adapter/service-worker/index.js"
|
||||
},
|
||||
"./testing": {
|
||||
"types": "./dist/types/helper/testing/index.d.ts",
|
||||
"import": "./dist/helper/testing/index.js",
|
||||
@ -543,6 +548,9 @@
|
||||
"lambda-edge": [
|
||||
"./dist/types/adapter/lambda-edge"
|
||||
],
|
||||
"service-worker": [
|
||||
"./dist/types/adapter/service-worker"
|
||||
],
|
||||
"testing": [
|
||||
"./dist/types/helper/testing"
|
||||
],
|
||||
|
57
src/adapter/service-worker/handler.test.ts
Normal file
57
src/adapter/service-worker/handler.test.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import { Hono } from '../../hono'
|
||||
import { handle } from './handler'
|
||||
import type { FetchEvent } from './types'
|
||||
|
||||
describe('handle', () => {
|
||||
it('Success to fetch', async () => {
|
||||
const app = new Hono()
|
||||
app.get('/', (c) => {
|
||||
return c.json({ hello: 'world' })
|
||||
})
|
||||
const handler = handle(app)
|
||||
const json = await new Promise<Response>((resolve) => {
|
||||
handler({
|
||||
request: new Request('http://localhost/'),
|
||||
respondWith(res) {
|
||||
resolve(res)
|
||||
},
|
||||
} as FetchEvent)
|
||||
}).then((res) => res.json())
|
||||
expect(json).toStrictEqual({ hello: 'world' })
|
||||
})
|
||||
it('Fallback 404', async () => {
|
||||
const app = new Hono()
|
||||
const handler = handle(app, {
|
||||
async fetch() {
|
||||
return new Response('hello world')
|
||||
},
|
||||
})
|
||||
const text = await new Promise<Response>((resolve) => {
|
||||
handler({
|
||||
request: new Request('http://localhost/'),
|
||||
respondWith(res) {
|
||||
resolve(res)
|
||||
},
|
||||
} as FetchEvent)
|
||||
}).then((res) => res.text())
|
||||
expect(text).toBe('hello world')
|
||||
})
|
||||
it('Do not fallback 404 when fetch is undefined', async () => {
|
||||
const app = new Hono()
|
||||
app.get('/', (c) => c.text('Not found', 404))
|
||||
const handler = handle(app, {
|
||||
fetch: undefined,
|
||||
})
|
||||
const result = await new Promise<Response>((resolve) =>
|
||||
handler({
|
||||
request: new Request('https://localhost/'),
|
||||
respondWith(r) {
|
||||
resolve(r)
|
||||
},
|
||||
} as FetchEvent)
|
||||
)
|
||||
|
||||
expect(result.status).toBe(404)
|
||||
expect(await result.text()).toBe('Not found')
|
||||
})
|
||||
})
|
33
src/adapter/service-worker/handler.ts
Normal file
33
src/adapter/service-worker/handler.ts
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Handler for Service Worker
|
||||
* @module
|
||||
*/
|
||||
|
||||
import type { Hono } from '../../hono'
|
||||
import type { FetchEvent } from './types'
|
||||
|
||||
type Handler = (evt: FetchEvent) => void
|
||||
|
||||
/**
|
||||
* Adapter for Service Worker
|
||||
*/
|
||||
export const handle = (
|
||||
app: Hono,
|
||||
opts: {
|
||||
fetch?: typeof fetch
|
||||
} = {
|
||||
fetch: fetch,
|
||||
}
|
||||
): Handler => {
|
||||
return (evt) => {
|
||||
evt.respondWith(
|
||||
(async () => {
|
||||
const res = await app.fetch(evt.request)
|
||||
if (opts.fetch && res.status === 404) {
|
||||
return await opts.fetch(evt.request)
|
||||
}
|
||||
return res
|
||||
})()
|
||||
)
|
||||
}
|
||||
}
|
5
src/adapter/service-worker/index.ts
Normal file
5
src/adapter/service-worker/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Cloudflare Workers Adapter for Hono.
|
||||
* @module
|
||||
*/
|
||||
export { handle } from './handler'
|
14
src/adapter/service-worker/types.ts
Normal file
14
src/adapter/service-worker/types.ts
Normal file
@ -0,0 +1,14 @@
|
||||
interface ExtendableEvent extends Event {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
waitUntil(f: Promise<any>): void
|
||||
}
|
||||
|
||||
export interface FetchEvent extends ExtendableEvent {
|
||||
readonly clientId: string
|
||||
readonly handled: Promise<undefined>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
readonly preloadResponse: Promise<any>
|
||||
readonly request: Request
|
||||
readonly resultingClientId: string
|
||||
respondWith(r: Response | PromiseLike<Response>): void
|
||||
}
|
Loading…
Reference in New Issue
Block a user