vite-elysia-forge 1.0.1 → 1.0.2

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 CHANGED
@@ -176,72 +176,139 @@ const app = new Elysia().use(
176
176
 
177
177
  ## 7. Production Deployment
178
178
 
179
- ### 7.1 Build Configuration
179
+ The CLI provides several build commands to bundle your frontend and Elysia backend for production.
180
180
 
181
- Update your `package.json` scripts:
181
+ By default, the CLI looks for your API at `src/server/api.ts`. You can specify a custom path with the `--api` flag:
182
182
 
183
- Pick **one** build mode.
183
+ ```bash
184
+ vite-elysia-forge build --api server/api.ts
185
+ ```
186
+
187
+ ### 7.1 Standard Build (`build`)
188
+
189
+ Builds the frontend with Vite and bundles the Elysia server into a single JavaScript file.
190
+
191
+ ```bash
192
+ vite-elysia-forge build
193
+ ```
194
+
195
+ **What it does:**
196
+
197
+ 1. Runs `vite build` to compile your frontend to `dist/`
198
+ 2. Generates a production entry file that imports your API
199
+ 3. Bundles the server into `dist/server.js`
184
200
 
185
- Option A: build to `dist/server.js` (run with Bun):
201
+ **package.json:**
186
202
 
187
203
  ```json
188
204
  {
189
205
  "scripts": {
190
- "dev": "vite",
191
206
  "build": "vite-elysia-forge build",
192
207
  "start": "bun dist/server.js"
193
208
  }
194
209
  }
195
210
  ```
196
211
 
197
- Option B: build + compile to a standalone binary `dist/server`:
212
+ ### 7.2 Compiled Binary (`build-compile`)
213
+
214
+ Builds everything and compiles the server into a **standalone executable** (no Bun runtime required on the target machine).
215
+
216
+ ```bash
217
+ vite-elysia-forge build-compile
218
+ ```
219
+
220
+ **What it does:**
221
+
222
+ 1. Performs the standard build
223
+ 2. Compiles `dist/server.js` into a native binary at `dist/server`
224
+
225
+ **package.json:**
198
226
 
199
227
  ```json
200
228
  {
201
229
  "scripts": {
202
- "dev": "vite",
203
230
  "build": "vite-elysia-forge build-compile",
204
231
  "start": "./dist/server"
205
232
  }
206
233
  }
207
234
  ```
208
235
 
209
- If your API is located elsewhere, specify the path:
236
+ ### 7.3 Separate Outputs (`--static` / `--server`)
237
+
238
+ Build the frontend and backend to **separate directories** for independent deployment (e.g., static assets to a CDN, server to a VPS).
210
239
 
211
240
  ```bash
212
- vite-elysia-forge build src/my-api.ts
241
+ vite-elysia-forge build --static dist --server .output
213
242
  ```
214
243
 
215
- ### 7.2 Building for Production
244
+ **Output structure:**
216
245
 
217
- Run the build command:
246
+ ```
247
+ project/
248
+ ├── dist/ # Static assets (deploy to CDN)
249
+ │ ├── index.html
250
+ │ └── assets/
251
+ └── .output/ # Server bundle (deploy to server)
252
+ └── server.js
253
+ ```
254
+
255
+ **Use cases:**
256
+
257
+ - Deploying static assets to Cloudflare Pages, Netlify, Vercel, etc.
258
+ - Running the Elysia server on a separate VPS or Docker container
259
+ - CI/CD pipelines that deploy frontend and backend independently
260
+
261
+ **package.json:**
262
+
263
+ ```json
264
+ {
265
+ "scripts": {
266
+ "build": "vite-elysia-forge build --static dist --server .output",
267
+ "start": "bun .output/server.js"
268
+ }
269
+ }
270
+ ```
271
+
272
+ Override the static assets path at runtime:
218
273
 
219
274
  ```bash
220
- bun run build
275
+ STATIC_DIR=/path/to/static bun .output/server.js
221
276
  ```
222
277
 
223
- This command performs the following steps:
278
+ ### 7.4 Frontend Only (`build-static`)
224
279
 
225
- 1. Runs `vite build` to compile your frontend to `dist/`
226
- 2. Automatically generates a temporary entry file that imports your API from `src/server/api.ts`
227
- 3. Bundles the server into a single file at `dist/server.js`
280
+ Build only the frontend, skipping the server bundle.
228
281
 
229
- ### 7.3 Building a Standalone Binary
282
+ ```bash
283
+ vite-elysia-forge build-static
284
+ ```
285
+
286
+ Useful for rebuilding just the frontend without touching the server.
230
287
 
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:
288
+ ### 7.5 Server Only (`build-server`)
289
+
290
+ Build only the server bundle, skipping the Vite frontend build.
232
291
 
233
292
  ```bash
234
- bun run build
293
+ vite-elysia-forge build-server --server .output --static dist
235
294
  ```
236
295
 
237
- This runs the normal build and then compiles `dist/server.js` into a standalone binary at `dist/server`.
296
+ Useful when the frontend is already built or deployed separately.
297
+
298
+ ### 7.6 CLI Reference
238
299
 
239
- ### 7.4 Starting the Production Server
300
+ | Option | Short | Default | Description |
301
+ | :--------------- | :---: | :------------------ | :------------------------------------------ |
302
+ | `--api <path>` | `-a` | `src/server/api.ts` | Path to API entry file |
303
+ | `--static <dir>` | `-s` | `dist` | Output directory for static frontend assets |
304
+ | `--server <dir>` | `-o` | Same as `--static` | Output directory for server bundle |
305
+ | `--skip-vite` | | `false` | Skip the Vite frontend build |
306
+ | `--skip-server` | | `false` | Skip the server build |
240
307
 
241
- Start the server with:
308
+ **Example with custom API path:**
242
309
 
243
310
  ```bash
244
- bun start
311
+ vite-elysia-forge build --api src/my-api.ts
245
312
  ```
246
313
 
247
314
  ## 8. Troubleshooting
package/dist/cli.d.ts CHANGED
@@ -1,5 +1,39 @@
1
1
  #!/usr/bin/env bun
2
- declare function build(apiEntry?: string): Promise<void>;
3
- declare function buildCompile(apiEntry?: string): Promise<void>;
2
+ /**
3
+ * Build options for customizing output directories.
4
+ */
5
+ interface BuildOptions {
6
+ /**
7
+ * Path to the API entry file.
8
+ * @default "src/server/api.ts"
9
+ */
10
+ apiEntry?: string;
11
+ /**
12
+ * Output directory for the Vite/frontend static assets.
13
+ * @default "dist"
14
+ */
15
+ staticDir?: string;
16
+ /**
17
+ * Output directory for the Elysia server bundle.
18
+ * When set to a different value than staticDir, the server and static assets
19
+ * will be built to separate directories.
20
+ * @default "dist" (same as staticDir)
21
+ */
22
+ serverDir?: string;
23
+ /**
24
+ * Whether to skip the Vite frontend build.
25
+ * Useful when you only want to rebuild the server.
26
+ * @default false
27
+ */
28
+ skipVite?: boolean;
29
+ /**
30
+ * Whether to skip the server build.
31
+ * Useful when you only want to rebuild the frontend.
32
+ * @default false
33
+ */
34
+ skipServer?: boolean;
35
+ }
36
+ declare function build(options?: BuildOptions | string): Promise<void>;
37
+ declare function buildCompile(options?: BuildOptions | string): Promise<void>;
4
38
 
5
- export { build, buildCompile };
39
+ export { type BuildOptions, build, buildCompile };
package/dist/cli.js CHANGED
@@ -1,11 +1,13 @@
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 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=`
2
+ import {spawnSync}from'child_process';import {existsSync,mkdirSync,writeFileSync,unlinkSync,rmSync}from'fs';import {resolve,relative,sep}from'path';async function v(r={}){let s=typeof r=="string"?{apiEntry:r}:r,t=s.apiEntry||"src/server/api.ts",e=s.staticDir||"dist",o=s.serverDir||e,u=s.skipVite||false,y=s.skipServer||false,b=e!==o,m=resolve(process.cwd(),t);if(!y&&!existsSync(m)&&(console.error(`\u274C API entry file "${t}" 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 --api <path-to-your-api-file>"),process.exit(1)),!u){console.log(`\u{1F4E6} Building frontend to "${e}"...`);let i=spawnSync("bun",["x","vite","build","--outDir",e],{stdio:"inherit",env:{...process.env,NODE_ENV:"production"}});i.status!==0&&(console.error("\u274C Vite build failed"),process.exit(i.status||1)),console.log(`\u2705 Frontend built to "${e}"`);}if(y){console.log("\u23ED\uFE0F Skipping server build (--skip-server)");return}let c=resolve(process.cwd(),".output");existsSync(c)||mkdirSync(c,{recursive:true});let d=resolve(c,".temp-prod.ts"),a=relative(c,m);a=a.split(sep).join("/"),a.startsWith(".")||(a="./"+a);let n;if(b){let i=resolve(process.cwd(),o),g=resolve(process.cwd(),e);n=relative(i,g),n.startsWith(".")||(n="./"+n),n=n.split(sep).join("/");}else n=".";let O=`
3
3
  import { startServer } from "vite-elysia-forge/production";
4
- import { api } from ${JSON.stringify(t)};
4
+ import { api } from ${JSON.stringify(a)};
5
5
 
6
6
  startServer({
7
7
  api,
8
8
  port: process.env.PORT ? parseInt(process.env.PORT) : 3000,
9
- distDir: "dist",
9
+ distDir: process.env.STATIC_DIR || ${JSON.stringify(n)},
10
10
  });
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};
11
+ `;writeFileSync(d,O);let h=resolve(process.cwd(),o);existsSync(h)||mkdirSync(h,{recursive:true}),console.log(`\u{1F4E6} Building server to "${o}"...`);try{let i=await Bun.build({entrypoints:[d],outdir:o,target:"bun",minify:!0,naming:"server.js"});if(!i.success){console.error("\u274C Server build failed");for(let g of i.logs)console.error(g);process.exit(1);}console.log(`\u2705 Server built to "${o}/server.js"`);}catch(i){console.error("\u274C Failed to build server. Ensure you are running this command with Bun."),console.error(i),process.exit(1);}finally{existsSync(d)&&unlinkSync(d),existsSync(c)&&rmSync(c,{recursive:true,force:true});}b&&(console.log(`
12
+ \u{1F4C1} Output structure:`),console.log(` Static assets: ${e}/`),console.log(` Server bundle: ${o}/server.js`),console.log(`
13
+ \u{1F4A1} To run: cd ${o} && bun server.js`),console.log(" Or set STATIC_DIR to override the static assets path"));}async function x(r={}){let s=typeof r=="string"?{apiEntry:r}:r,t=s.serverDir||s.staticDir||"dist";await v(s),console.log("\u{1F527} Compiling server to standalone binary...");let e=resolve(process.cwd(),t,"server.js"),o=resolve(process.cwd(),t,"server"),u=spawnSync("bun",["build","--compile",e,"--outfile",o],{stdio:"inherit",env:{...process.env,NODE_ENV:"production"}});u.status!==0&&(console.error("\u274C Bun compile failed"),process.exit(u.status||1)),console.log(`\u2705 Compiled standalone binary: ${t}/server`);}function f(r){let s={};for(let t=0;t<r.length;t++){let e=r[t],o=r[t+1];switch(e){case "--api":case "-a":o&&!o.startsWith("-")&&(s.apiEntry=o,t++);break;case "--static":case "-s":o&&!o.startsWith("-")&&(s.staticDir=o,t++);break;case "--server":case "-o":o&&!o.startsWith("-")&&(s.serverDir=o,t++);break;case "--skip-vite":s.skipVite=true;break;case "--skip-server":s.skipServer=true;break;default:e&&!e.startsWith("-")&&!s.apiEntry&&(s.apiEntry=e);}}return s}if(import.meta.main){let r=process.argv.slice(2),s=r[0],t=r.slice(1);if(s==="build"){let e=f(t);v(e);}else if(s==="build-compile"){let e=f(t);x(e);}else if(s==="build-static"){let e=f(t);e.skipServer=true,v(e);}else if(s==="build-server"){let e=f(t);e.skipVite=true,v(e);}else console.log("Usage: vite-elysia-forge <command> [options]"),console.log(""),console.log("Commands:"),console.log(" build Build frontend + bundle server"),console.log(" build-compile Build and compile a standalone server binary"),console.log(" build-static Build only the frontend (skip server)"),console.log(" build-server Build only the server (skip frontend)"),console.log(""),console.log("Options:"),console.log(" --api, -a <path> Path to API entry file (default: src/server/api.ts)"),console.log(" --static, -s <dir> Output directory for static assets (default: dist)"),console.log(" --server, -o <dir> Output directory for server bundle (default: same as --static)"),console.log(" --skip-vite Skip the Vite frontend build"),console.log(" --skip-server Skip the server build"),console.log(""),console.log("Examples:"),console.log(" # Build everything to 'dist/' (default)"),console.log(" vite-elysia-forge build"),console.log(""),console.log(" # Build with separate output directories"),console.log(" vite-elysia-forge build --static dist --server .output"),console.log(""),console.log(" # Build only the frontend"),console.log(" vite-elysia-forge build-static --static public"),console.log(""),console.log(" # Build only the server to a separate folder"),console.log(" vite-elysia-forge build-server --server .output --static dist");}export{v as build,x as buildCompile};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-elysia-forge",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "A Vite plugin to seamlessly integrate ElysiaJS for full-stack development with Bun runtime.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",