Skip to content

Commit

Permalink
feat(dev-server): add loadModule option (#175)
Browse files Browse the repository at this point in the history
* feat(dev-server): add `loadModule` option

* add changeset
  • Loading branch information
yusukebe authored Sep 9, 2024
1 parent 1152a9a commit c44f939
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changeset/rare-cycles-tickle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hono/vite-dev-server': minor
---

feat: add `loadModule` option
33 changes: 22 additions & 11 deletions packages/dev-server/src/dev-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type http from 'http'
import { getRequestListener } from '@hono/node-server'
import { minimatch } from 'minimatch'
import type { Plugin as VitePlugin, ViteDevServer, Connect } from 'vite'
import type { Env, Fetch, EnvFunc, Adapter } from './types.js'
import type { Env, Fetch, EnvFunc, Adapter, LoadModule } from './types.js'

export type DevServerOptions = {
entry?: string
Expand All @@ -11,6 +11,7 @@ export type DevServerOptions = {
exclude?: (string | RegExp)[]
ignoreWatching?: (string | RegExp)[]
env?: Env | EnvFunc
loadModule?: LoadModule
/**
* This can be used to inject environment variables into the worker from your wrangler.toml for example,
* by making use of the helper function `getPlatformProxy` from `wrangler`.
Expand Down Expand Up @@ -42,7 +43,7 @@ export type DevServerOptions = {
adapter?: Adapter | Promise<Adapter> | (() => Adapter | Promise<Adapter>)
}

export const defaultOptions: Required<Omit<DevServerOptions, 'env' | 'adapter'>> = {
export const defaultOptions: Required<Omit<DevServerOptions, 'env' | 'adapter' | 'loadModule'>> = {
entry: './src/index.ts',
export: 'default',
injectClientScript: true,
Expand Down Expand Up @@ -83,19 +84,29 @@ export function devServer(options?: DevServerOptions): VitePlugin {
}
}
}
let appModule

try {
appModule = await server.ssrLoadModule(entry)
} catch (e) {
return next(e)
let loadModule: LoadModule

if (options?.loadModule) {
loadModule = options.loadModule
} else {
loadModule = async (server, entry) => {
const appModule = await server.ssrLoadModule(entry)
const exportName = options?.export ?? defaultOptions.export
const app = appModule[exportName] as { fetch: Fetch }
if (!app) {
throw new Error(`Failed to find a named export "${exportName}" from ${entry}`)
}
return app
}
}

const exportName = options?.export ?? defaultOptions.export
const app = appModule[exportName] as { fetch: Fetch }
let app: { fetch: Fetch }

if (!app) {
return next(new Error(`Failed to find a named export "${exportName}" from ${entry}`))
try {
app = await loadModule(server, entry)
} catch (e) {
return next(e)
}

getRequestListener(
Expand Down
4 changes: 4 additions & 0 deletions packages/dev-server/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { ViteDevServer } from 'vite'

export type Env = Record<string, unknown> | Promise<Record<string, unknown>>
export type EnvFunc = () => Env | Promise<Env>
export type GetEnv<Options> = (options: Options) => EnvFunc
Expand All @@ -12,6 +14,8 @@ export type Fetch = (
executionContext: ExecutionContext
) => Promise<Response>

export type LoadModule = (server: ViteDevServer, entry: string) => Promise<{ fetch: Fetch }>

export interface Adapter {
/**
* Environment variables to be injected into the worker
Expand Down

0 comments on commit c44f939

Please sign in to comment.