diff --git a/packages/vike-node/README.md b/packages/vike-node/README.md index ff45871..7bc0679 100644 --- a/packages/vike-node/README.md +++ b/packages/vike-node/README.md @@ -211,6 +211,24 @@ function startServer() { } ``` +Elysia (Bun): + +```js +// server/index.js + +import { Elysia } from 'elysia' +import vike from 'vike-node/elysia' + +startServer() + +function startServer() { + const app = new Elysia() + app.use(vike()) + const port = +(process.env.PORT || 3000) + app.listen(port, () => console.log(`Server running at http://localhost:${port}`)) +} +``` + ## Migration guide: ```diff diff --git a/packages/vike-node/package.json b/packages/vike-node/package.json index 73f51bb..962fd75 100644 --- a/packages/vike-node/package.json +++ b/packages/vike-node/package.json @@ -6,6 +6,7 @@ "./connect": "./dist/connect.js", "./fastify": "./dist/fastify.js", "./hono": "./dist/hono.js", + "./elysia": "./dist/elysia.js", "./plugin": "./dist/plugin/index.js" }, "scripts": { @@ -31,6 +32,7 @@ "@types/node": "^20.14.12", "fastify": "^4.28.1", "hono": "^4.5.1", + "elysia": "^1.1.4", "typescript": "^5.5.4", "vike": "^0.4.181", "vite": "^5.3.5" @@ -46,6 +48,9 @@ "hono": [ "./dist/hono.d.ts" ], + "elysia": [ + "./dist/elysia.d.ts" + ], "plugin": [ "./dist/plugin/index.d.ts" ] diff --git a/packages/vike-node/src/elysia.ts b/packages/vike-node/src/elysia.ts new file mode 100644 index 0000000..a5a013c --- /dev/null +++ b/packages/vike-node/src/elysia.ts @@ -0,0 +1 @@ +export { vike, vike as default } from './runtime/frameworks/elysia.js' diff --git a/packages/vike-node/src/runtime/frameworks/elysia.ts b/packages/vike-node/src/runtime/frameworks/elysia.ts new file mode 100644 index 0000000..b9878b4 --- /dev/null +++ b/packages/vike-node/src/runtime/frameworks/elysia.ts @@ -0,0 +1,52 @@ +export { vike } + +import { Elysia, NotFoundError } from 'elysia' +import { connectToWeb } from '../adapters/connectToWeb.js' +import { createHandler } from '../handler.js' +import type { VikeOptions } from '../types.js' + +/** + * Creates an Elysia plugin to handle Vike requests. + * + * @param {VikeOptions} [options] - Configuration options for Vike. + * + * @returns {Elysia} An Elysia plugin that handles all GET requests and processes them with Vike. + * + * @description + * The plugin: + * 1. Sets up a catch-all GET route handler that processes requests using Vike's handler. + * 2. Throws a NotFoundError if Vike doesn't handle the request, allowing Elysia to manage 404 responses. + * + * @example + * ```js + * import { Elysia } from 'elysia' + * import { vike } from 'vike-node/elysia' + * + * const app = new Elysia() + * app.use(vike()) + * app.listen(3000) + * ``` + * + * @throws {NotFoundError} Thrown when Vike doesn't handle the request, allowing Elysia to manage 404 responses. + */ +function vike(options?: VikeOptions): Elysia { + const handler = createHandler(options) + return new Elysia({ + name: 'vike-node:elysia' + }).get('*', async (ctx) => { + const response = await connectToWeb((req, res, next) => + handler({ + req, + res, + next, + platformRequest: ctx.request + }) + )(ctx.request) + + if (response) { + return response + } + + throw new NotFoundError() + }) +} diff --git a/packages/vike-node/src/runtime/frameworks/hono.ts b/packages/vike-node/src/runtime/frameworks/hono.ts index a6d0d61..cdbb1d6 100644 --- a/packages/vike-node/src/runtime/frameworks/hono.ts +++ b/packages/vike-node/src/runtime/frameworks/hono.ts @@ -33,8 +33,8 @@ import type { VikeOptions } from '../types.js' * ``` * */ -function vike(options?: VikeOptions): MiddlewareHandler { - const handler = createHandler(options) +function vike(options?: VikeOptions): MiddlewareHandler { + const handler = createHandler(options) return async function middleware(ctx, next) { const req = ctx.env.incoming as IncomingMessage globalStore.setupHMRProxy(req) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3bd2a62..9215c92 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -81,6 +81,9 @@ importers: '@types/node': specifier: ^20.14.12 version: 20.14.12 + elysia: + specifier: ^1.1.4 + version: 1.1.4(@sinclair/typebox@0.32.35)(typescript@5.5.4) fastify: specifier: ^4.28.1 version: 4.28.1 @@ -126,6 +129,9 @@ importers: cross-env: specifier: ^7.0.3 version: 7.0.3 + elysia: + specifier: ^1.1.4 + version: 1.1.4(@sinclair/typebox@0.32.35)(typescript@5.5.4) express: specifier: ^4.19.2 version: 4.19.2 @@ -1130,6 +1136,9 @@ packages: cpu: [x64] os: [win32] + '@sinclair/typebox@0.32.35': + resolution: {integrity: sha512-Ul3YyOTU++to8cgNkttakC0dWvpERr6RYoHO2W47DLbFvrwBDJUY31B1sImH6JZSYc4Kt4PyHtoPNu+vL2r2dA==} + '@ts-morph/common@0.20.0': resolution: {integrity: sha512-7uKjByfbPpwuzkstL3L5MQyuXPSKdoNG93Fmi2JoDcTf3pEP731JdRFAduRVkOs8oqxPsXKA+ScrWkdQ8t/I+Q==} @@ -1556,6 +1565,18 @@ packages: electron-to-chromium@1.5.2: resolution: {integrity: sha512-kc4r3U3V3WLaaZqThjYz/Y6z8tJe+7K0bbjUVo3i+LWIypVdMx5nXCkwRe6SWbY6ILqLdc1rKcKmr3HoH7wjSQ==} + elysia@1.1.4: + resolution: {integrity: sha512-1axwwKig+plmUH/Rwd+lvJvgutis+6eoF+RnB76fGtgNCfhQ8yh4pNb3MIo39YHwyEA+j6A5a/vn8U+UPkRt2A==} + peerDependencies: + '@sinclair/typebox': '>= 0.32.0' + openapi-types: '>= 12.0.0' + typescript: '>= 5.0.0' + peerDependenciesMeta: + openapi-types: + optional: true + typescript: + optional: true + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -3361,6 +3382,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.19.0': optional: true + '@sinclair/typebox@0.32.35': {} + '@ts-morph/common@0.20.0': dependencies: fast-glob: 3.3.2 @@ -3825,6 +3848,14 @@ snapshots: electron-to-chromium@1.5.2: {} + elysia@1.1.4(@sinclair/typebox@0.32.35)(typescript@5.5.4): + dependencies: + '@sinclair/typebox': 0.32.35 + cookie: 0.6.0 + fast-decode-uri-component: 1.0.1 + optionalDependencies: + typescript: 5.5.4 + emoji-regex@8.0.0: {} encodeurl@1.0.2: {} diff --git a/test/vike-node/package.json b/test/vike-node/package.json index bc5321c..0eacf58 100644 --- a/test/vike-node/package.json +++ b/test/vike-node/package.json @@ -18,6 +18,7 @@ "express": "^4.19.2", "fastify": "^4.28.1", "hono": "^4.5.1", + "elysia": "^1.1.4", "prisma": "^5.17.0", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/test/vike-node/server/index-elysia.ts b/test/vike-node/server/index-elysia.ts new file mode 100644 index 0000000..4fcecd3 --- /dev/null +++ b/test/vike-node/server/index-elysia.ts @@ -0,0 +1,31 @@ +import { Elysia } from 'elysia' +import { telefunc } from 'telefunc' +import vike from 'vike-node/elysia' +import { init } from '../database/todoItems' + +startServer() + +async function startServer() { + await init() + const app = new Elysia() + + const port = process.env.PORT || 3000 + app.post('/_telefunc', async (ctx) => { + const context = {} + const httpResponse = await telefunc({ + url: ctx.request.url, + method: ctx.request.method, + body: await ctx.request.text(), + context + }) + const { body, statusCode, contentType } = httpResponse + return new Response(body, { headers: { 'content-type': contentType }, status: statusCode }) + }) + + app.onAfterHandle((ctx) => { + ctx.set.headers['x-test'] = 'test' + }) + + app.use(vike()) + app.listen(+port, () => console.log(`Server running at http://localhost:${port}`)) +}