Skip to content

Commit

Permalink
fix(bun-transpiler): Apply headers when using serveStatic; Improvemen…
Browse files Browse the repository at this point in the history
…t: 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
  • Loading branch information
floriankapaun authored Jan 11, 2024
1 parent 935560f commit b6e59dd
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 24 deletions.
5 changes: 5 additions & 0 deletions .changeset/little-plants-chew.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hono/bun-transpiler': minor
---

Fix: Apply headers when using serveStatic middleware; Improvement: Make options optional;
5 changes: 5 additions & 0 deletions .changeset/loud-boats-fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hono/bun-transpiler': minor
---

Export defaultOptions
11 changes: 11 additions & 0 deletions packages/bun-transpiler/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Hono } from 'hono'
import { serveStatic } from 'hono/bun'
import { bunTranspiler } from '.'

const HOST = 'http://localhost'
Expand All @@ -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()
Expand Down Expand Up @@ -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')
})
})
44 changes: 20 additions & 24 deletions packages/bun-transpiler/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,48 @@ 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 = {
...headers,
'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)
}
}
})
Expand Down

0 comments on commit b6e59dd

Please sign in to comment.