fix(bun-transpiler): Apply headers when using serveStatic; Improvement: Make options optional; (#349)

*  Add failing serveStatic test (headers not applied)

* 🐛 Fix: Apply headers when using serveStatic

* 🚸 Make options optional

* 🔖 Add changeset

* ✏️ Fix naming in comment

* 🚸 Export defaultOptions

* 🏷️ Improve Typing of defaultOptions
pull/350/head
floriankapaun 2024-01-11 21:03:13 +01:00 committed by GitHub
parent 935560f677
commit b6e59dd19c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 24 deletions

View File

@ -0,0 +1,5 @@
---
'@hono/bun-transpiler': minor
---
Fix: Apply headers when using serveStatic middleware; Improvement: Make options optional;

View File

@ -0,0 +1,5 @@
---
'@hono/bun-transpiler': minor
---
Export defaultOptions

View File

@ -1,4 +1,5 @@
import { Hono } from 'hono'
import { serveStatic } from 'hono/bun'
import { bunTranspiler } from '.'
const HOST = 'http://localhost'
@ -20,6 +21,9 @@ describe('Bun Transpiler middleware', () => {
app.get('/script.tsx', (c) => c.text(TSX))
app.get('/bad.ts', (c) => c.text(BAD))
// serve middleware script to test compliance with serveStatic
app.get('/index.ts', serveStatic({ root: './src' }))
it('Should ignore non typescript content paths', async () => {
const res = await app.request(`${HOST}/script.js`)
expect(res).not.toBeNull()
@ -50,4 +54,11 @@ describe('Bun Transpiler middleware', () => {
expect(await res.text()).toBe('Parse error')
expect(res.headers.get('content-type')).toBe('text/plain')
})
it('Should apply headers when serveStatic is used', async () => {
const res = await app.request(`${HOST}/index.ts`)
expect(res).not.toBeNull()
expect(res.status).toBe(200)
expect(res.headers.get('content-type')).toBe('application/javascript')
})
})

View File

@ -2,36 +2,38 @@ import Bun from 'bun'
import { createMiddleware } from 'hono/factory'
type BunTranspilerOptions = {
extensions: string[]
headers: HeadersInit
transpilerOptions: Bun.TranspilerOptions
extensions?: string[]
headers?: Record<string, string | string[]>
transpilerOptions?: Bun.TranspilerOptions
}
export const bunTranspiler = (
options: BunTranspilerOptions = {
extensions: ['.ts', '.tsx'],
headers: { 'content-type': 'application/javascript' },
transpilerOptions: {
minifyWhitespace: true,
target: 'browser',
},
}
) => {
export const defaultOptions: Required<BunTranspilerOptions> = {
extensions: ['.ts', '.tsx'],
headers: { 'content-type': 'application/javascript' },
transpilerOptions: {
minifyWhitespace: true,
target: 'browser',
},
}
export const bunTranspiler = (options?: BunTranspilerOptions) => {
return createMiddleware(async (c, next) => {
await next()
const url = new URL(c.req.url)
const { extensions, headers, transpilerOptions } = options
const extensions = options?.extensions ?? defaultOptions.extensions
const headers = options?.headers ?? defaultOptions.headers
if (extensions.every((ext) => !url.pathname.endsWith(ext))) return
if (extensions?.every((ext) => !url.pathname.endsWith(ext))) return
try {
const loader = url.pathname.split('.').pop() as Bun.TranspilerOptions['loader']
const transpilerOptions = options?.transpilerOptions ?? defaultOptions.transpilerOptions
const transpiler = new Bun.Transpiler({
loader,
...transpilerOptions,
})
const transpiledCode = await transpiler.transformSync(await c.res.text())
c.res = c.newResponse(transpiledCode, { headers })
c.res = c.newResponse(transpiledCode, 200, headers)
} catch (error) {
console.warn(`Error transpiling ${url.pathname}: ${error}`)
const errorHeaders = {
@ -39,15 +41,9 @@ export const bunTranspiler = (
'content-type': 'text/plain',
}
if (error instanceof Error) {
c.res = c.newResponse(error.message, {
status: 500,
headers: errorHeaders,
})
c.res = c.newResponse(error.message, 500, errorHeaders)
} else {
c.res = c.newResponse('Malformed Input', {
status: 500,
headers: errorHeaders,
})
c.res = c.newResponse('Malformed Input', 500, errorHeaders)
}
}
})