vite-elysia-forge 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +175 -11
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +3 -3
- package/dist/index.cjs +5 -2
- package/dist/index.d.cts +29 -1
- package/dist/index.d.ts +29 -1
- package/dist/index.js +5 -2
- package/dist/production.js +394 -2
- package/package.json +8 -5
package/README.md
CHANGED
|
@@ -57,11 +57,35 @@ Run Vite as usual and access your API at `/api/*` routes. The plugin will automa
|
|
|
57
57
|
bun run dev
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
## 3.
|
|
60
|
+
## 3. Configuration Options
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
### 3.1 Plugin Options
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
You can configure the plugin by passing an object with the following options:
|
|
65
|
+
|
|
66
|
+
| Option Key | Required | Default | Description |
|
|
67
|
+
| :-------------- | :------: | :----------------- | :--------------------------------------------------------------------- |
|
|
68
|
+
| `serverFile` | No | `"/server/api.ts"` | Path to your Elysia API module (relative to project root). |
|
|
69
|
+
| `ws` | No | `false` | Enable WebSocket support. Runs API as a separate process + Vite proxy. |
|
|
70
|
+
| `apiPrefix` | No | `"/api"` | Path prefix for API routes. Used for proxying in `ws` mode. |
|
|
71
|
+
| `backendPort` | No | `3001` | Port for the backend API server in `ws` mode. |
|
|
72
|
+
| `MAX_BODY_SIZE` | No | `1048576` (1MB) | Maximum allowed size for request bodies in bytes. |
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
elysiaPlugin({
|
|
76
|
+
serverFile: "/server/api.ts",
|
|
77
|
+
ws: true,
|
|
78
|
+
apiPrefix: "/api",
|
|
79
|
+
backendPort: 3001,
|
|
80
|
+
MAX_BODY_SIZE: 1024 * 1024, // 1MB
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 4. API Module Requirements
|
|
85
|
+
|
|
86
|
+
Your API module must export an Elysia instance as `api`.
|
|
87
|
+
|
|
88
|
+
### 4.1 Basic Example
|
|
65
89
|
|
|
66
90
|
```ts
|
|
67
91
|
import { Elysia } from "elysia";
|
|
@@ -76,7 +100,53 @@ api.get("/users", () => ["user1", "user2"]);
|
|
|
76
100
|
export default api;
|
|
77
101
|
```
|
|
78
102
|
|
|
79
|
-
|
|
103
|
+
### 4.2 WebSocket Example
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
import { Elysia } from "elysia";
|
|
107
|
+
|
|
108
|
+
export const api = new Elysia({
|
|
109
|
+
prefix: "/api",
|
|
110
|
+
})
|
|
111
|
+
.get("/", () => "hello from elysia")
|
|
112
|
+
.ws("/ws", {
|
|
113
|
+
message(ws, message) {
|
|
114
|
+
ws.send(`Echo: ${message}`);
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
export default api;
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## 5. WebSocket Support
|
|
122
|
+
|
|
123
|
+
By default, the plugin runs your API as middleware inside Vite's dev server. This works great for HTTP routes but **does not support WebSockets** (Elysia's `.ws()` routes).
|
|
124
|
+
|
|
125
|
+
To enable WebSocket support, set `ws: true`:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
elysiaPlugin({
|
|
129
|
+
serverFile: "./src/server/api.ts",
|
|
130
|
+
ws: true, // Enable WebSocket support
|
|
131
|
+
backendPort: 3001, // API runs on this port (default: 3001)
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 5.1 How WS Mode Works
|
|
136
|
+
|
|
137
|
+
When `ws: true`:
|
|
138
|
+
|
|
139
|
+
1. The plugin spawns a **separate Bun process** that runs your API with `api.listen(backendPort)`.
|
|
140
|
+
2. Vite is configured to **proxy** `/api` requests (including WebSocket upgrades) to that backend.
|
|
141
|
+
3. On file changes, the backend process is **automatically restarted**.
|
|
142
|
+
|
|
143
|
+
This ensures full Bun runtime support for WebSockets, even if Vite itself runs under Node.js.
|
|
144
|
+
|
|
145
|
+
### 5.2 Production
|
|
146
|
+
|
|
147
|
+
In production, the built server (`dist/server.js` or the compiled binary) runs your Elysia app directly with full WebSocket support—no proxy needed.
|
|
148
|
+
|
|
149
|
+
## 6. Integration with @elysiajs/openapi
|
|
80
150
|
|
|
81
151
|
To use the [@elysiajs/openapi plugin](https://elysiajs.com/patterns/openapi), add the following to your `tsconfig.json`:
|
|
82
152
|
|
|
@@ -89,7 +159,7 @@ To use the [@elysiajs/openapi plugin](https://elysiajs.com/patterns/openapi), ad
|
|
|
89
159
|
}
|
|
90
160
|
```
|
|
91
161
|
|
|
92
|
-
###
|
|
162
|
+
### 6.1 Example with `fromTypes`
|
|
93
163
|
|
|
94
164
|
It is recommended to pre-generate the declaration file (`.d.ts`) to provide type declaration to the generator.
|
|
95
165
|
|
|
@@ -104,12 +174,16 @@ const app = new Elysia().use(
|
|
|
104
174
|
);
|
|
105
175
|
```
|
|
106
176
|
|
|
107
|
-
##
|
|
177
|
+
## 7. Production Deployment
|
|
108
178
|
|
|
109
|
-
###
|
|
179
|
+
### 7.1 Build Configuration
|
|
110
180
|
|
|
111
181
|
Update your `package.json` scripts:
|
|
112
182
|
|
|
183
|
+
Pick **one** build mode.
|
|
184
|
+
|
|
185
|
+
Option A: build to `dist/server.js` (run with Bun):
|
|
186
|
+
|
|
113
187
|
```json
|
|
114
188
|
{
|
|
115
189
|
"scripts": {
|
|
@@ -120,13 +194,25 @@ Update your `package.json` scripts:
|
|
|
120
194
|
}
|
|
121
195
|
```
|
|
122
196
|
|
|
197
|
+
Option B: build + compile to a standalone binary `dist/server`:
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"scripts": {
|
|
202
|
+
"dev": "vite",
|
|
203
|
+
"build": "vite-elysia-forge build-compile",
|
|
204
|
+
"start": "./dist/server"
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
123
209
|
If your API is located elsewhere, specify the path:
|
|
124
210
|
|
|
125
211
|
```bash
|
|
126
212
|
vite-elysia-forge build src/my-api.ts
|
|
127
213
|
```
|
|
128
214
|
|
|
129
|
-
###
|
|
215
|
+
### 7.2 Building for Production
|
|
130
216
|
|
|
131
217
|
Run the build command:
|
|
132
218
|
|
|
@@ -140,7 +226,17 @@ This command performs the following steps:
|
|
|
140
226
|
2. Automatically generates a temporary entry file that imports your API from `src/server/api.ts`
|
|
141
227
|
3. Bundles the server into a single file at `dist/server.js`
|
|
142
228
|
|
|
143
|
-
###
|
|
229
|
+
### 7.3 Building a Standalone Binary
|
|
230
|
+
|
|
231
|
+
If you want a single executable (no Bun runtime required on the target machine), set your `build` script to `vite-elysia-forge build-compile` (Option B above) and run:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
bun run build
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
This runs the normal build and then compiles `dist/server.js` into a standalone binary at `dist/server`.
|
|
238
|
+
|
|
239
|
+
### 7.4 Starting the Production Server
|
|
144
240
|
|
|
145
241
|
Start the server with:
|
|
146
242
|
|
|
@@ -148,10 +244,78 @@ Start the server with:
|
|
|
148
244
|
bun start
|
|
149
245
|
```
|
|
150
246
|
|
|
151
|
-
##
|
|
247
|
+
## 8. Troubleshooting
|
|
248
|
+
|
|
249
|
+
### 8.1 "Bun is not defined" Error
|
|
250
|
+
|
|
251
|
+
If you encounter this error, ensure you are running Vite with the Bun runtime:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
bunx --bun vite
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Or update your `dev` script in `package.json`:
|
|
258
|
+
|
|
259
|
+
```json
|
|
260
|
+
"scripts": {
|
|
261
|
+
"dev": "bunx --bun vite"
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**Benefits:**
|
|
266
|
+
|
|
267
|
+
- **Access to Bun APIs:** You can use `Bun.file`, `Bun.env`, `bun:sqlite`, and other native Bun features directly in your server code.
|
|
268
|
+
- **Performance:** Vite often starts faster and uses less memory when running under Bun.
|
|
269
|
+
|
|
270
|
+
**Caveats:**
|
|
271
|
+
|
|
272
|
+
- **Node.js Compatibility:** While Bun has excellent Node.js compatibility, some Vite plugins that rely on obscure Node.js internals might behave unexpectedly.
|
|
273
|
+
- **Performance:** Running Vite under Bun is generally faster, but you might encounter edge cases where optimization differs from Node.js.
|
|
274
|
+
|
|
275
|
+
### 8.2 Hot Reload Not Working
|
|
276
|
+
|
|
277
|
+
Check that your file changes are within the dependency graph of your API module. The plugin uses Vite's dependency tracking to determine when to reload.
|
|
278
|
+
|
|
279
|
+
### 8.3 WebSocket "adapter doesn't support" Error
|
|
280
|
+
|
|
281
|
+
If you see `Current adapter doesn't support WebSocket`, you need to enable WS mode:
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
elysiaPlugin({
|
|
285
|
+
serverFile: "./src/server/api.ts",
|
|
286
|
+
ws: true,
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
This spawns your API as a separate Bun process with full WebSocket support.
|
|
291
|
+
|
|
292
|
+
### 8.4 "ReferenceError: process is not defined" with OpenAPI
|
|
293
|
+
|
|
294
|
+
If you use `@elysiajs/openapi` with `fromTypes` and see this error in the browser console:
|
|
295
|
+
|
|
296
|
+
\`\`\`
|
|
297
|
+
Uncaught ReferenceError: process is not defined
|
|
298
|
+
at fromTypes ...
|
|
299
|
+
\`\`\`
|
|
300
|
+
|
|
301
|
+
This happens because \`fromTypes\` relies on Node.js/Bun APIs that don't exist in the browser. It usually means you are importing your server file as a value in client-side code.
|
|
302
|
+
|
|
303
|
+
**Solution:** Use \`import type\` when importing your API instance for Eden Treaty.
|
|
304
|
+
|
|
305
|
+
\`\`\`ts
|
|
306
|
+
// ❌ Incorrect
|
|
307
|
+
import { api } from './server/api'
|
|
308
|
+
const client = treaty(api)
|
|
309
|
+
|
|
310
|
+
// ✅ Correct
|
|
311
|
+
import type { api } from './server/api'
|
|
312
|
+
const client = treaty<typeof api>('localhost:3000')
|
|
313
|
+
\`\`\`
|
|
314
|
+
|
|
315
|
+
## 9. Authors
|
|
152
316
|
|
|
153
317
|
- Chijioke Udokporo ([@chijiokeudokporo](https://github.com/chijioke-udokporo))
|
|
154
318
|
|
|
155
|
-
##
|
|
319
|
+
## 10. License
|
|
156
320
|
|
|
157
321
|
MIT
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import {spawnSync}from'child_process';import {existsSync,mkdirSync,writeFileSync,unlinkSync,rmSync}from'fs';import {resolve,relative,sep}from'path';async function
|
|
2
|
+
import {spawnSync}from'child_process';import {existsSync,mkdirSync,writeFileSync,unlinkSync,rmSync}from'fs';import {resolve,relative,sep}from'path';async function u(e="src/server/api.ts"){let r=resolve(process.cwd(),e);existsSync(r)||(console.error(`\u274C API entry file "${e}" not found.`),console.error(' By default, vite-elysia-forge looks for "src/server/api.ts".'),console.error(" If your API is located elsewhere, please specify the path:"),console.error(" $ vite-elysia-forge build <path-to-your-api-file>"),process.exit(1));let o=spawnSync("bun",["x","vite","build"],{stdio:"inherit",env:{...process.env,NODE_ENV:"production"}});o.status!==0&&(console.error("\u274C Vite build failed"),process.exit(o.status||1));let s=resolve(process.cwd(),".output");existsSync(s)||mkdirSync(s,{recursive:true});let i=resolve(s,".temp-prod.ts"),t=relative(s,r);t=t.split(sep).join("/"),t.startsWith(".")||(t="./"+t);let p=`
|
|
3
3
|
import { startServer } from "vite-elysia-forge/production";
|
|
4
|
-
import { api } from
|
|
4
|
+
import { api } from ${JSON.stringify(t)};
|
|
5
5
|
|
|
6
6
|
startServer({
|
|
7
7
|
api,
|
|
8
8
|
port: process.env.PORT ? parseInt(process.env.PORT) : 3000,
|
|
9
9
|
distDir: "dist",
|
|
10
10
|
});
|
|
11
|
-
`;writeFileSync(
|
|
11
|
+
`;writeFileSync(i,p);try{let n=await Bun.build({entrypoints:[i],outdir:"dist",target:"bun",minify:!0,naming:"server.js"});if(!n.success){console.error("\u274C Server build failed");for(let d of n.logs)console.error(d);process.exit(1);}}catch(n){console.error("\u274C Failed to build server. Ensure you are running this command with Bun."),console.error(n),process.exit(1);}finally{existsSync(i)&&unlinkSync(i),existsSync(s)&&rmSync(s,{recursive:true,force:true});}}async function h(e="src/server/api.ts"){await u(e);let r=spawnSync("bun",["build","--compile","dist/server.js","--outfile","dist/server"],{stdio:"inherit",env:{...process.env,NODE_ENV:"production"}});r.status!==0&&(console.error("\u274C Bun compile failed"),process.exit(r.status||1));}if(import.meta.main){let e=process.argv.slice(2),r=e[0];if(r==="build"){let o=e[1];u(o);}else if(r==="build-compile"){let o=e[1];h(o);}else console.log("Usage: vite-elysia-forge <command> [api-entry]"),console.log("Commands:"),console.log(" build Build frontend + bundle server to dist/server.js"),console.log(" build-compile Build and compile a standalone server binary to dist/server"),console.log(""),console.log("api-entry: Path to your API entry file (default: src/server/api.ts)");}export{u as build,h as buildCompile};
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
'use strict';var path=require('path');function
|
|
2
|
-
|
|
1
|
+
'use strict';var path=require('path'),child_process=require('child_process'),fs=require('fs');function F({serverFile:v="/server/api.ts",ws:d=false,apiPrefix:E="/api",backendPort:h=3001,MAX_BODY_SIZE:M=1024*1024}={}){return {name:"vite-elysia-forge",config:d?()=>({server:{proxy:{[E]:{target:`http://localhost:${h}`,changeOrigin:true,ws:true}}}}):void 0,async configureServer(o){let l=v,b=path.resolve(o.config.root,l.slice(1)),w=async()=>(await o.ssrLoadModule(l)).api,S=await w(),s=null,g=false,P=async()=>{if(d&&!g){g=true;try{s&&(s.kill("SIGTERM"),s=null);let e=path.resolve(o.config.root,"node_modules",".vite-elysia-forge"),t=path.resolve(e,"dev-server.ts"),a=path.resolve(o.config.root,l.startsWith("/")?l.slice(1):l),i=path.relative(e,a);i.startsWith(".")||(i="./"+i),fs.existsSync(e)||fs.mkdirSync(e,{recursive:!0});let c=`import { api } from ${JSON.stringify(i)};
|
|
2
|
+
api.listen(${h});
|
|
3
|
+
console.log("WebSocket server running at ws://localhost:${h}");
|
|
4
|
+
`;fs.writeFileSync(t,c),s=child_process.spawn("bun",["run",t],{stdio:["ignore","inherit","inherit"],cwd:o.config.root,env:{...process.env}}),s.on("error",n=>{console.error(`Failed to start API server: ${n.message}`);}),s.on("exit",n=>{n!==null&&n!==0&&console.error(`API server process exited with code ${n}`),s=null;});}finally{g=false;}}};d&&(await P(),o.httpServer?.once("close",()=>{s&&(s.kill("SIGTERM"),s=null);})),o.watcher.add(b),o.watcher.on("change",async e=>{let t=await o.moduleGraph.getModuleByUrl(l);if(!t)return;let a=o.moduleGraph.getModulesByFile(e);if(!a||a.size===0)return;let i=false,c=new Set,n=[...a];for(;n.length>0;){let r=n.shift();if(!(!r||!r.id||c.has(r.id))){if(c.add(r.id),r.id===t.id){i=true;break}for(let m of r.importers)n.push(m);}}if(i)try{o.moduleGraph.invalidateModule(t),S=await w(),console.log("Reloaded Elysia API module"),d&&await P();}catch(r){console.error(`Failed to reload Elysia API: ${r}`);}}),!d&&o.middlewares.use(async(e,t,a)=>{if(!e.url?.startsWith("/api"))return a();try{let i="http",c=e.headers.host||"localhost:3000",n=`${i}://${c}${e.url}`,r;if(e.method!=="GET"&&e.method!=="HEAD"){let u=[],f=0;for await(let $ of e){if(f+=$.length,f>M){t.statusCode=413,t.end("Payload Too Large");return}u.push($);}r=Buffer.concat(u).toString();}let m=new Request(n,{method:e.method,headers:e.headers,body:r}),y=await S.handle(m);t.statusCode=y.status,y.headers.forEach((u,f)=>{t.setHeader(f,u);});let k=await y.text();t.end(k);}catch(i){console.error(`Elysia error: ${i}`),t.statusCode=500,t.end("Internal Server Error");}});}}}var T=F;
|
|
5
|
+
module.exports=T;
|
package/dist/index.d.cts
CHANGED
|
@@ -10,6 +10,34 @@ interface ConfigOptions {
|
|
|
10
10
|
* @default "/server/api.ts"
|
|
11
11
|
*/
|
|
12
12
|
serverFile?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Enable WebSocket-capable mode by running the API as a real Bun/Elysia server
|
|
15
|
+
* on a separate port, and letting Vite proxy to it (including WS upgrades).
|
|
16
|
+
*
|
|
17
|
+
* When enabled, the plugin will:
|
|
18
|
+
* - start (and hot-restart) `api.listen(backendPort)`
|
|
19
|
+
* - configure Vite `server.proxy[apiPrefix]` with `ws: true`
|
|
20
|
+
*
|
|
21
|
+
* @default false
|
|
22
|
+
*/
|
|
23
|
+
ws?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Path prefix for API routes.
|
|
26
|
+
* Used for Vite proxy configuration in `ws` mode.
|
|
27
|
+
* @default "/api"
|
|
28
|
+
*/
|
|
29
|
+
apiPrefix?: string;
|
|
30
|
+
/**
|
|
31
|
+
* The port to run the backend API server on in `ws` mode.
|
|
32
|
+
* @default 3001
|
|
33
|
+
*/
|
|
34
|
+
backendPort?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Maximum allowed size for request bodies in bytes.
|
|
37
|
+
* Requests exceeding this size will receive a 413 Payload Too Large response.
|
|
38
|
+
* @default 1048576 (1MB)
|
|
39
|
+
*/
|
|
40
|
+
MAX_BODY_SIZE?: number;
|
|
13
41
|
}
|
|
14
42
|
/**
|
|
15
43
|
* A Vite plugin that integrates ElysiaJS into the Vite development server.
|
|
@@ -20,6 +48,6 @@ interface ConfigOptions {
|
|
|
20
48
|
* @param options - Configuration options for the plugin.
|
|
21
49
|
* @returns A Vite plugin instance.
|
|
22
50
|
*/
|
|
23
|
-
declare function elysiaPlugin({ serverFile }
|
|
51
|
+
declare function elysiaPlugin({ serverFile, ws, apiPrefix, backendPort, MAX_BODY_SIZE, }?: ConfigOptions): Plugin;
|
|
24
52
|
|
|
25
53
|
export { type ConfigOptions, elysiaPlugin as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,34 @@ interface ConfigOptions {
|
|
|
10
10
|
* @default "/server/api.ts"
|
|
11
11
|
*/
|
|
12
12
|
serverFile?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Enable WebSocket-capable mode by running the API as a real Bun/Elysia server
|
|
15
|
+
* on a separate port, and letting Vite proxy to it (including WS upgrades).
|
|
16
|
+
*
|
|
17
|
+
* When enabled, the plugin will:
|
|
18
|
+
* - start (and hot-restart) `api.listen(backendPort)`
|
|
19
|
+
* - configure Vite `server.proxy[apiPrefix]` with `ws: true`
|
|
20
|
+
*
|
|
21
|
+
* @default false
|
|
22
|
+
*/
|
|
23
|
+
ws?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Path prefix for API routes.
|
|
26
|
+
* Used for Vite proxy configuration in `ws` mode.
|
|
27
|
+
* @default "/api"
|
|
28
|
+
*/
|
|
29
|
+
apiPrefix?: string;
|
|
30
|
+
/**
|
|
31
|
+
* The port to run the backend API server on in `ws` mode.
|
|
32
|
+
* @default 3001
|
|
33
|
+
*/
|
|
34
|
+
backendPort?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Maximum allowed size for request bodies in bytes.
|
|
37
|
+
* Requests exceeding this size will receive a 413 Payload Too Large response.
|
|
38
|
+
* @default 1048576 (1MB)
|
|
39
|
+
*/
|
|
40
|
+
MAX_BODY_SIZE?: number;
|
|
13
41
|
}
|
|
14
42
|
/**
|
|
15
43
|
* A Vite plugin that integrates ElysiaJS into the Vite development server.
|
|
@@ -20,6 +48,6 @@ interface ConfigOptions {
|
|
|
20
48
|
* @param options - Configuration options for the plugin.
|
|
21
49
|
* @returns A Vite plugin instance.
|
|
22
50
|
*/
|
|
23
|
-
declare function elysiaPlugin({ serverFile }
|
|
51
|
+
declare function elysiaPlugin({ serverFile, ws, apiPrefix, backendPort, MAX_BODY_SIZE, }?: ConfigOptions): Plugin;
|
|
24
52
|
|
|
25
53
|
export { type ConfigOptions, elysiaPlugin as default };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
import {resolve}from'path';function
|
|
2
|
-
|
|
1
|
+
import {resolve,relative}from'path';import {spawn}from'child_process';import {existsSync,mkdirSync,writeFileSync}from'fs';function F({serverFile:v="/server/api.ts",ws:d=false,apiPrefix:E="/api",backendPort:h=3001,MAX_BODY_SIZE:M=1024*1024}={}){return {name:"vite-elysia-forge",config:d?()=>({server:{proxy:{[E]:{target:`http://localhost:${h}`,changeOrigin:true,ws:true}}}}):void 0,async configureServer(o){let l=v,b=resolve(o.config.root,l.slice(1)),w=async()=>(await o.ssrLoadModule(l)).api,S=await w(),s=null,g=false,P=async()=>{if(d&&!g){g=true;try{s&&(s.kill("SIGTERM"),s=null);let e=resolve(o.config.root,"node_modules",".vite-elysia-forge"),t=resolve(e,"dev-server.ts"),a=resolve(o.config.root,l.startsWith("/")?l.slice(1):l),i=relative(e,a);i.startsWith(".")||(i="./"+i),existsSync(e)||mkdirSync(e,{recursive:!0});let c=`import { api } from ${JSON.stringify(i)};
|
|
2
|
+
api.listen(${h});
|
|
3
|
+
console.log("WebSocket server running at ws://localhost:${h}");
|
|
4
|
+
`;writeFileSync(t,c),s=spawn("bun",["run",t],{stdio:["ignore","inherit","inherit"],cwd:o.config.root,env:{...process.env}}),s.on("error",n=>{console.error(`Failed to start API server: ${n.message}`);}),s.on("exit",n=>{n!==null&&n!==0&&console.error(`API server process exited with code ${n}`),s=null;});}finally{g=false;}}};d&&(await P(),o.httpServer?.once("close",()=>{s&&(s.kill("SIGTERM"),s=null);})),o.watcher.add(b),o.watcher.on("change",async e=>{let t=await o.moduleGraph.getModuleByUrl(l);if(!t)return;let a=o.moduleGraph.getModulesByFile(e);if(!a||a.size===0)return;let i=false,c=new Set,n=[...a];for(;n.length>0;){let r=n.shift();if(!(!r||!r.id||c.has(r.id))){if(c.add(r.id),r.id===t.id){i=true;break}for(let m of r.importers)n.push(m);}}if(i)try{o.moduleGraph.invalidateModule(t),S=await w(),console.log("Reloaded Elysia API module"),d&&await P();}catch(r){console.error(`Failed to reload Elysia API: ${r}`);}}),!d&&o.middlewares.use(async(e,t,a)=>{if(!e.url?.startsWith("/api"))return a();try{let i="http",c=e.headers.host||"localhost:3000",n=`${i}://${c}${e.url}`,r;if(e.method!=="GET"&&e.method!=="HEAD"){let u=[],f=0;for await(let $ of e){if(f+=$.length,f>M){t.statusCode=413,t.end("Payload Too Large");return}u.push($);}r=Buffer.concat(u).toString();}let m=new Request(n,{method:e.method,headers:e.headers,body:r}),y=await S.handle(m);t.statusCode=y.status,y.headers.forEach((u,f)=>{t.setHeader(f,u);});let k=await y.text();t.end(k);}catch(i){console.error(`Elysia error: ${i}`),t.statusCode=500,t.end("Internal Server Error");}});}}}var T=F;
|
|
5
|
+
export{T as default};
|