diff --git a/.changeset/fuzzy-books-agree.md b/.changeset/fuzzy-books-agree.md new file mode 100644 index 0000000..8906f83 --- /dev/null +++ b/.changeset/fuzzy-books-agree.md @@ -0,0 +1,5 @@ +--- +'@hono/vite-build': minor +--- + +feat: Node.js adapter supports `port` option diff --git a/packages/build/README.md b/packages/build/README.md index a7272e1..3f60c5c 100644 --- a/packages/build/README.md +++ b/packages/build/README.md @@ -42,6 +42,8 @@ export default defineConfig({ build({ // Defaults are `src/index.ts`,`./src/index.tsx`,`./app/server.ts` entry: './src/index.tsx', + // port option is only for Node.js adapter. Default is 3000 + port: 3001, }), ], }) diff --git a/packages/build/src/adapter/node/index.ts b/packages/build/src/adapter/node/index.ts index 4c6b338..4202548 100644 --- a/packages/build/src/adapter/node/index.ts +++ b/packages/build/src/adapter/node/index.ts @@ -5,9 +5,11 @@ import { serveStaticHook } from '../../entry/serve-static.js' export type NodeBuildOptions = { staticRoot?: string | undefined + port?: number | undefined } & BuildOptions const nodeBuildPlugin = (pluginOptions?: NodeBuildOptions): Plugin => { + const port = pluginOptions?.port ?? 3000 return { ...buildPlugin({ ...{ @@ -26,7 +28,7 @@ const nodeBuildPlugin = (pluginOptions?: NodeBuildOptions): Plugin => { async (appName) => { // eslint-disable-next-line quotes let code = "import { serve } from '@hono/node-server'\n" - code += `serve(${appName})` + code += `serve({ fetch: ${appName}.fetch, port: ${port.toString()} })` return code }, ], diff --git a/packages/build/test/adapter.test.ts b/packages/build/test/adapter.test.ts index e036da0..a000fb1 100644 --- a/packages/build/test/adapter.test.ts +++ b/packages/build/test/adapter.test.ts @@ -3,6 +3,7 @@ import { existsSync, readFileSync, rmSync } from 'node:fs' import bunBuildPlugin from '../src/adapter/bun' import cloudflarePagesPlugin from '../src/adapter/cloudflare-pages' import denoBuildPlugin from '../src/adapter/deno' +import nodeBuildPlugin from '../src/adapter/node' describe('Build Plugin with Bun Adapter', () => { const testDir = './test/mocks/app-static-files' @@ -157,3 +158,42 @@ describe('Build Plugin with Deno Adapter', () => { expect(outputJsClientJs).toContain("console.log('foo')") }) }) + +describe('Build Plugin with Node.js Adapter', () => { + const testDir = './test/mocks/app-static-files' + const entry = './src/server.ts' + + afterEach(() => { + rmSync(`${testDir}/dist`, { recursive: true, force: true }) + }) + + it('Should build the project correctly with the plugin', async () => { + const outputFile = `${testDir}/dist/index.js` + + await build({ + root: testDir, + plugins: [ + nodeBuildPlugin({ + entry, + port: 3001, + minify: false, + }), + ], + }) + + expect(existsSync(outputFile)).toBe(true) + + const output = readFileSync(outputFile, 'utf-8') + expect(output).toContain('Hello World') + expect(output).toContain('use("/foo.txt"') + expect(output).toContain('use("/js/*"') + expect(output).toContain('serve({ fetch: mainApp.fetch, port: 3001 })') + + const outputFooTxt = readFileSync(`${testDir}/dist/foo.txt`, 'utf-8') + expect(outputFooTxt).toContain('foo') + + const outputJsClientJs = readFileSync(`${testDir}/dist/js/client.js`, 'utf-8') + // eslint-disable-next-line quotes + expect(outputJsClientJs).toContain("console.log('foo')") + }) +})