@burger-api/cli 0.7.1 → 0.9.1
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/CHANGELOG.md +17 -1
- package/README.md +57 -19
- package/package.json +8 -4
- package/src/commands/build.ts +111 -137
- package/src/commands/create.ts +6 -2
- package/src/index.ts +20 -2
- package/src/types/index.ts +12 -0
- package/src/utils/config.ts +78 -0
- package/src/utils/entry-options.ts +326 -0
- package/src/utils/logger.ts +5 -4
- package/src/utils/route-conventions.ts +142 -0
- package/src/utils/route-methods.ts +91 -0
- package/src/utils/scanner.ts +185 -0
- package/src/utils/templates.ts +41 -4
- package/src/utils/virtual-entry.ts +121 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the Burger API CLI will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## Version 0.9.0 - (March 15, 2026)
|
|
6
|
+
|
|
7
|
+
- ✨ **Create** – New projects get a config file (`burger.config.ts`) from
|
|
8
|
+
your answers; the build uses this config when present.
|
|
9
|
+
- 🔨 **Build** – One build pipeline for both bundle and executable; routes
|
|
10
|
+
are found at build time so production is fast and reliable.
|
|
11
|
+
- 📂 **Defaults** – Executable output: `.build/executable/<project>` (or
|
|
12
|
+
`.exe` on Windows); bundle: `.build/bundle/app.js`.
|
|
13
|
+
- 🧪 **Tests** – New tests for routes, config, and build output; CI catches
|
|
14
|
+
broken builds early.
|
|
15
|
+
- 🐛 **Fixed** – Invalid route combinations are caught at build time.
|
|
16
|
+
- 🐛 **Fixed** – Production build keeps your middleware and options (e.g.
|
|
17
|
+
title, description) instead of dropping them.
|
|
18
|
+
- 📚 **Docs** – README updated with production build steps and test
|
|
19
|
+
commands.
|
|
20
|
+
|
|
5
21
|
## Version 0.7.0 - (December 23, 2025)
|
|
6
22
|
|
|
7
23
|
### Added
|
|
@@ -32,7 +48,7 @@ All notable changes to the Burger API CLI will be documented in this file.
|
|
|
32
48
|
- `list` command to show available middleware from ecosystem
|
|
33
49
|
- `add` command to download and install middleware
|
|
34
50
|
- `build` command to bundle projects to single JS file
|
|
35
|
-
- `build:
|
|
51
|
+
- `build:exec` command to compile to standalone executable
|
|
36
52
|
- `serve` command for development server with hot reload
|
|
37
53
|
- Beautiful console output with colors and symbols
|
|
38
54
|
- Zero external dependencies for file operations (uses Bun's native APIs)
|
package/README.md
CHANGED
|
@@ -69,9 +69,24 @@ installed!
|
|
|
69
69
|
- ✅ Full project structure
|
|
70
70
|
- ✅ TypeScript configured
|
|
71
71
|
- ✅ Dependencies installed
|
|
72
|
+
- ✅ `burger.config.ts` generated from your answers
|
|
72
73
|
- ✅ Example routes
|
|
73
74
|
- ✅ Ready to run!
|
|
74
75
|
|
|
76
|
+
Generated config example:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
export default {
|
|
80
|
+
apiDir: './src/api',
|
|
81
|
+
pageDir: './src/pages',
|
|
82
|
+
apiPrefix: '/api',
|
|
83
|
+
pagePrefix: '/',
|
|
84
|
+
debug: false,
|
|
85
|
+
};
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Edit `burger.config.ts` anytime to change routes, prefixes, or debug mode.
|
|
89
|
+
|
|
75
90
|
---
|
|
76
91
|
|
|
77
92
|
### `burger-api list`
|
|
@@ -151,7 +166,8 @@ const app = new Burger({
|
|
|
151
166
|
|
|
152
167
|
### `burger-api build <file>`
|
|
153
168
|
|
|
154
|
-
Bundle your project
|
|
169
|
+
Bundle your project with build-time (AOT) route discovery.
|
|
170
|
+
The CLI scans routes first, generates a virtual entry file, then runs Bun build.
|
|
155
171
|
|
|
156
172
|
**Example:**
|
|
157
173
|
|
|
@@ -171,22 +187,29 @@ burger-api build index.ts --sourcemap linked
|
|
|
171
187
|
|
|
172
188
|
**Options:**
|
|
173
189
|
|
|
174
|
-
- `--outfile <path>` - Output file path (default: `.build/bundle.js`)
|
|
190
|
+
- `--outfile <path>` - Output file path (default: `.build/bundle/app.js`)
|
|
175
191
|
- `--minify` - Minify the output for smaller file size
|
|
176
192
|
- `--sourcemap <type>` - Generate sourcemaps (inline, linked, or none)
|
|
177
193
|
- `--target <target>` - Target environment (e.g., bun, node)
|
|
178
194
|
|
|
195
|
+
Build config is loaded from `burger.config.ts` or `burger.config.js` when
|
|
196
|
+
present. If no config exists, the CLI uses defaults:
|
|
197
|
+
`apiDir=./src/api`, `pageDir=./src/pages`, `apiPrefix=/api`, `pagePrefix=/`.
|
|
198
|
+
|
|
179
199
|
**Output:**
|
|
180
200
|
|
|
181
201
|
```
|
|
182
202
|
✓ Build completed successfully!
|
|
183
|
-
Output: .build/bundle.js
|
|
203
|
+
Output: .build/bundle/app.js
|
|
184
204
|
Size: 42.5 KB
|
|
185
205
|
```
|
|
186
206
|
|
|
207
|
+
- API-only apps: `app.js` is usually enough to deploy.
|
|
208
|
+
- Apps with pages/assets: deploy the full `.build/bundle/` directory.
|
|
209
|
+
|
|
187
210
|
---
|
|
188
211
|
|
|
189
|
-
### `burger-api build:
|
|
212
|
+
### `burger-api build:exec <file>`
|
|
190
213
|
|
|
191
214
|
Compile your project to a standalone executable that runs without Bun installed!
|
|
192
215
|
|
|
@@ -194,19 +217,19 @@ Compile your project to a standalone executable that runs without Bun installed!
|
|
|
194
217
|
|
|
195
218
|
```bash
|
|
196
219
|
# Build for current platform
|
|
197
|
-
burger-api build:
|
|
220
|
+
burger-api build:exec index.ts
|
|
198
221
|
|
|
199
222
|
# Build for Windows
|
|
200
|
-
burger-api build:
|
|
223
|
+
burger-api build:exec index.ts --target bun-windows-x64
|
|
201
224
|
|
|
202
225
|
# Build for Linux
|
|
203
|
-
burger-api build:
|
|
226
|
+
burger-api build:exec index.ts --target bun-linux-x64
|
|
204
227
|
|
|
205
228
|
# Build for Mac (ARM)
|
|
206
|
-
burger-api build:
|
|
229
|
+
burger-api build:exec index.ts --target bun-darwin-arm64
|
|
207
230
|
|
|
208
231
|
# Custom output name
|
|
209
|
-
burger-api build:
|
|
232
|
+
burger-api build:exec index.ts --outfile my-server.exe
|
|
210
233
|
```
|
|
211
234
|
|
|
212
235
|
**Options:**
|
|
@@ -228,11 +251,11 @@ burger-api build:executable index.ts --outfile my-server.exe
|
|
|
228
251
|
|
|
229
252
|
```
|
|
230
253
|
✓ Compilation completed successfully!
|
|
231
|
-
Executable: .build/
|
|
254
|
+
Executable: .build/executable/<project>.exe
|
|
232
255
|
Size: 45.2 MB
|
|
233
256
|
|
|
234
257
|
Your standalone executable is ready to run!
|
|
235
|
-
Run it: .build/
|
|
258
|
+
Run it: .build/executable/<project>.exe
|
|
236
259
|
```
|
|
237
260
|
|
|
238
261
|
**Use case:** Perfect for deploying your API to production servers without
|
|
@@ -371,9 +394,13 @@ burger-api serve
|
|
|
371
394
|
1. You're in a Burger API project directory
|
|
372
395
|
2. The entry file exists
|
|
373
396
|
3. There are no TypeScript errors in your code
|
|
397
|
+
4. Route folder rules are valid (no mixed dynamic + wildcard siblings)
|
|
374
398
|
|
|
375
399
|
Run `bun run dev` first to see any errors.
|
|
376
400
|
|
|
401
|
+
If you use custom folders or prefixes, verify your `burger.config.ts` /
|
|
402
|
+
`burger.config.js` values.
|
|
403
|
+
|
|
377
404
|
### Cross-compilation fails from Windows (D:\ drive)
|
|
378
405
|
|
|
379
406
|
**Error:**
|
|
@@ -500,17 +527,23 @@ you encounter crashes, rebuild without `--bytecode`. The build scripts use
|
|
|
500
527
|
|
|
501
528
|
### Testing
|
|
502
529
|
|
|
503
|
-
|
|
530
|
+
Run tests (from `packages/cli`):
|
|
504
531
|
|
|
505
532
|
```bash
|
|
506
|
-
#
|
|
507
|
-
bun run
|
|
533
|
+
# Run all CLI tests
|
|
534
|
+
bun run test
|
|
535
|
+
|
|
536
|
+
# Run build tests only (check production matches dev)
|
|
537
|
+
bun run test:build
|
|
538
|
+
|
|
539
|
+
# Run one test file
|
|
540
|
+
bun test test/build-output.test.ts
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
From the **repo root**, run all CLI tests with:
|
|
508
544
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
bun run ../src/index.ts list
|
|
512
|
-
bun run ../src/index.ts add cors
|
|
513
|
-
bun run ../src/index.ts serve
|
|
545
|
+
```bash
|
|
546
|
+
bun run test:cli
|
|
514
547
|
```
|
|
515
548
|
|
|
516
549
|
### Contributing
|
|
@@ -527,6 +560,11 @@ bun run ../src/index.ts serve
|
|
|
527
560
|
- Add comments explaining your code
|
|
528
561
|
- Test all commands before submitting
|
|
529
562
|
- Update README if adding new features
|
|
563
|
+
- Keep route rules in one place:
|
|
564
|
+
- runtime/shared rules: `packages/burger-api/src/utils/pathConversion.ts`
|
|
565
|
+
- scanner traversal: `packages/cli/src/utils/scanner.ts`
|
|
566
|
+
- Run build tests when changing routing/build (keeps dev and production behavior the same):
|
|
567
|
+
- `bun run test:build`
|
|
530
568
|
|
|
531
569
|
### Design Principles
|
|
532
570
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@burger-api/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "Simple command-line tool for Burger API projects",
|
|
5
5
|
"module": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
20
20
|
"dev": "bun run src/index.ts",
|
|
21
|
+
"test": "bun test --timeout 30000 ./test",
|
|
22
|
+
"test:build": "bun test test/scanner.test.ts test/virtual-entry.test.ts test/entry-options.test.ts test/build-preserve-options.test.ts",
|
|
21
23
|
"build:win": "bun build ./src/index.ts --compile --target bun-windows-x64 --outfile dist/burger-api.exe --minify",
|
|
22
24
|
"build:linux": "bun build ./src/index.ts --compile --target bun-linux-x64 --outfile dist/burger-api-linux --minify",
|
|
23
25
|
"build:mac": "bun build ./src/index.ts --compile --target bun-darwin-arm64 --outfile dist/burger-api-mac --minify",
|
|
@@ -29,8 +31,7 @@
|
|
|
29
31
|
"@clack/prompts": "^0.7.0"
|
|
30
32
|
},
|
|
31
33
|
"devDependencies": {
|
|
32
|
-
"@types/bun": "latest"
|
|
33
|
-
"@types/commander": "^2.12.5"
|
|
34
|
+
"@types/bun": "latest"
|
|
34
35
|
},
|
|
35
36
|
"peerDependencies": {
|
|
36
37
|
"typescript": "^5"
|
|
@@ -47,5 +48,8 @@
|
|
|
47
48
|
"type": "git",
|
|
48
49
|
"url": "git+https://github.com/isfhan/burger-api.git",
|
|
49
50
|
"directory": "packages/cli"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
50
54
|
}
|
|
51
|
-
}
|
|
55
|
+
}
|
package/src/commands/build.ts
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
* Build Commands
|
|
3
3
|
*
|
|
4
4
|
* Two commands for packaging your Burger API project:
|
|
5
|
-
* 1. `burger-api build <file>`
|
|
6
|
-
* 2. `burger-api build:
|
|
5
|
+
* 1. `burger-api build <file>` — Bundle to .build/bundle/
|
|
6
|
+
* 2. `burger-api build:exec <file>` — Compile to .build/executable/
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* Both use build-time (AOT) route discovery — no filesystem scanning at runtime.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { Command } from 'commander';
|
|
12
|
-
import { existsSync
|
|
13
|
-
import {
|
|
12
|
+
import { existsSync } from 'fs';
|
|
13
|
+
import { dirname, resolve } from 'path';
|
|
14
14
|
import {
|
|
15
15
|
spinner,
|
|
16
16
|
success,
|
|
@@ -20,9 +20,11 @@ import {
|
|
|
20
20
|
formatSize,
|
|
21
21
|
dim,
|
|
22
22
|
} from '../utils/logger';
|
|
23
|
+
import { runVirtualEntryBuild } from '../utils/build/pipeline';
|
|
24
|
+
import { getProjectName } from '../utils/build/project';
|
|
23
25
|
|
|
24
26
|
/**
|
|
25
|
-
*
|
|
27
|
+
* Options for the `build` command.
|
|
26
28
|
*/
|
|
27
29
|
interface BuildCommandOptions {
|
|
28
30
|
outfile: string;
|
|
@@ -32,7 +34,7 @@ interface BuildCommandOptions {
|
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
/**
|
|
35
|
-
*
|
|
37
|
+
* Options for the `build:exec` command.
|
|
36
38
|
*/
|
|
37
39
|
interface BuildExecutableOptions {
|
|
38
40
|
outfile?: string;
|
|
@@ -42,74 +44,81 @@ interface BuildExecutableOptions {
|
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
+
* `burger-api build <file>`
|
|
48
|
+
*
|
|
49
|
+
* Bundles your project into .build/bundle/ using AOT route discovery.
|
|
50
|
+
*
|
|
51
|
+
* Output:
|
|
52
|
+
* .build/bundle/
|
|
53
|
+
* app.js — Bun server (run with: bun .build/bundle/app.js)
|
|
54
|
+
* index.html — HTML pages (flat, one per page route)
|
|
55
|
+
* style-[hash].css — CSS assets (flat)
|
|
56
|
+
* app-[hash].js — JS chunks (flat)
|
|
57
|
+
*
|
|
58
|
+
* API-only projects: app.js is a self-contained single file.
|
|
59
|
+
* Projects with HTML pages: deploy the entire .build/bundle/ directory.
|
|
47
60
|
*/
|
|
48
61
|
export const buildCommand = new Command('build')
|
|
49
|
-
.description('Bundle your project
|
|
50
|
-
.argument(
|
|
51
|
-
|
|
62
|
+
.description('Bundle your project into .build/bundle/')
|
|
63
|
+
.argument(
|
|
64
|
+
'<file>',
|
|
65
|
+
'Entry file (used for compatibility; config from burger.config.ts or conventions)'
|
|
66
|
+
)
|
|
67
|
+
.option('--outfile <path>', 'Output bundle path', '.build/bundle/app.js')
|
|
52
68
|
.option('--minify', 'Minify the output')
|
|
53
69
|
.option(
|
|
54
70
|
'--sourcemap <type>',
|
|
55
71
|
'Generate sourcemaps (inline, linked, or none)'
|
|
56
72
|
)
|
|
57
|
-
.option('--target <
|
|
73
|
+
.option('--target <env>', 'Target environment (default: bun)')
|
|
58
74
|
.action(async (file: string, options: BuildCommandOptions) => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
75
|
+
const cwd = process.cwd();
|
|
76
|
+
const entryPath = resolve(cwd, file);
|
|
77
|
+
if (!existsSync(entryPath)) {
|
|
78
|
+
logError(`Entry file not found: ${file}`);
|
|
79
|
+
info('Make sure you are in the project directory.');
|
|
62
80
|
process.exit(1);
|
|
63
81
|
}
|
|
64
82
|
|
|
65
83
|
const spin = spinner('Building project...');
|
|
66
84
|
|
|
67
85
|
try {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (options.sourcemap) {
|
|
80
|
-
args.push('--sourcemap', options.sourcemap);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Always target bun by default since BurgerAPI uses Bun builtins
|
|
84
|
-
args.push('--target', options.target || 'bun');
|
|
85
|
-
|
|
86
|
-
// Run the build using Bun.spawn
|
|
87
|
-
const proc = Bun.spawn(['bun', ...args], {
|
|
88
|
-
stdout: 'pipe',
|
|
89
|
-
stderr: 'pipe',
|
|
86
|
+
info('Build-time route discovery enabled.');
|
|
87
|
+
|
|
88
|
+
const { success: ok, hasPages } = await runVirtualEntryBuild({
|
|
89
|
+
cwd,
|
|
90
|
+
entryFile: file,
|
|
91
|
+
outfile: options.outfile,
|
|
92
|
+
target: options.target || 'bun',
|
|
93
|
+
minify: options.minify,
|
|
94
|
+
sourcemap: options.sourcemap,
|
|
90
95
|
});
|
|
91
96
|
|
|
92
|
-
|
|
93
|
-
const exitCode = await proc.exited;
|
|
94
|
-
|
|
95
|
-
if (exitCode !== 0) {
|
|
96
|
-
// Read error output
|
|
97
|
-
const errorText = await new Response(proc.stderr).text();
|
|
97
|
+
if (!ok) {
|
|
98
98
|
spin.stop('Build failed', true);
|
|
99
|
-
logError(
|
|
99
|
+
logError(
|
|
100
|
+
'Bun.build failed. Check that api/page directories and route files are valid.'
|
|
101
|
+
);
|
|
100
102
|
process.exit(1);
|
|
101
103
|
}
|
|
102
104
|
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
const size = outputFile.size;
|
|
105
|
+
const size = Bun.file(options.outfile).size;
|
|
106
|
+
const bundleDir = dirname(options.outfile);
|
|
106
107
|
|
|
107
108
|
spin.stop('Build completed successfully!');
|
|
108
109
|
newline();
|
|
109
|
-
success(`
|
|
110
|
-
info(`Size: ${formatSize(size)}`);
|
|
110
|
+
success(`Bundle: ${options.outfile} (${formatSize(size)})`);
|
|
111
111
|
newline();
|
|
112
|
-
|
|
112
|
+
if (hasPages) {
|
|
113
|
+
info(`Pages and assets are in: ${bundleDir}/`);
|
|
114
|
+
dim(
|
|
115
|
+
'Deploy the entire directory — HTML pages depend on their chunks.'
|
|
116
|
+
);
|
|
117
|
+
dim(`Run: bun ${options.outfile}`);
|
|
118
|
+
} else {
|
|
119
|
+
info('API-only bundle — self-contained single file.');
|
|
120
|
+
dim(`Run anywhere: bun ${options.outfile}`);
|
|
121
|
+
}
|
|
113
122
|
newline();
|
|
114
123
|
} catch (err) {
|
|
115
124
|
spin.stop('Build failed', true);
|
|
@@ -119,109 +128,92 @@ export const buildCommand = new Command('build')
|
|
|
119
128
|
});
|
|
120
129
|
|
|
121
130
|
/**
|
|
122
|
-
*
|
|
123
|
-
*
|
|
131
|
+
* `burger-api build:exec <file>`
|
|
132
|
+
*
|
|
133
|
+
* Compiles your project into a standalone binary in .build/executable/.
|
|
134
|
+
* The binary is fully self-contained — no Bun installation required on the target.
|
|
135
|
+
* All routes, pages, and assets are embedded inside the binary.
|
|
124
136
|
*/
|
|
125
|
-
export const buildExecutableCommand = new Command('build:
|
|
126
|
-
.description(
|
|
127
|
-
|
|
128
|
-
|
|
137
|
+
export const buildExecutableCommand = new Command('build:exec')
|
|
138
|
+
.description(
|
|
139
|
+
'Compile your project to a standalone executable in .build/executable/'
|
|
140
|
+
)
|
|
141
|
+
.argument(
|
|
142
|
+
'<file>',
|
|
143
|
+
'Entry file (used for compatibility; config from burger.config.ts or conventions)'
|
|
144
|
+
)
|
|
145
|
+
.option('--outfile <path>', 'Output executable path')
|
|
129
146
|
.option(
|
|
130
|
-
'--target <
|
|
147
|
+
'--target <platform>',
|
|
131
148
|
'Target platform (bun-windows-x64, bun-linux-x64, bun-darwin-arm64)'
|
|
132
149
|
)
|
|
133
150
|
.option('--minify', 'Minify the output (enabled by default)', true)
|
|
134
151
|
.option('--no-bytecode', 'Disable bytecode compilation')
|
|
135
152
|
.action(async (file: string, options: BuildExecutableOptions) => {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
153
|
+
const cwd = process.cwd();
|
|
154
|
+
const entryPath = resolve(cwd, file);
|
|
155
|
+
if (!existsSync(entryPath)) {
|
|
156
|
+
logError(`Entry file not found: ${file}`);
|
|
157
|
+
info('Make sure you are in the project directory.');
|
|
139
158
|
process.exit(1);
|
|
140
159
|
}
|
|
141
160
|
|
|
142
|
-
// Determine output filename
|
|
143
161
|
let outfile = options.outfile;
|
|
144
162
|
if (!outfile) {
|
|
145
|
-
|
|
146
|
-
const projectName = getProjectName();
|
|
147
|
-
|
|
148
|
-
// Add platform-specific extension
|
|
149
|
-
// Check if targeting Windows or if we're on Windows without a specific target
|
|
163
|
+
const projectName = getProjectName(cwd);
|
|
150
164
|
const isWindows =
|
|
151
165
|
options.target?.includes('windows') ||
|
|
152
166
|
(!options.target && process.platform === 'win32');
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
} else {
|
|
157
|
-
outfile = `.build/${projectName}`;
|
|
158
|
-
}
|
|
167
|
+
outfile = isWindows
|
|
168
|
+
? `.build/executable/${projectName}.exe`
|
|
169
|
+
: `.build/executable/${projectName}`;
|
|
159
170
|
}
|
|
160
171
|
|
|
161
172
|
const spin = spinner('Compiling to executable...');
|
|
162
173
|
|
|
163
174
|
try {
|
|
164
|
-
|
|
165
|
-
const args = ['build', file, '--compile'];
|
|
166
|
-
|
|
167
|
-
// Add output file
|
|
168
|
-
args.push('--outfile', outfile);
|
|
169
|
-
|
|
170
|
-
// Add target platform
|
|
171
|
-
if (options.target) {
|
|
172
|
-
args.push('--target', options.target);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Add minify (on by default)
|
|
176
|
-
if (options.minify) {
|
|
177
|
-
args.push('--minify');
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Add bytecode (on by default, unless --no-bytecode is passed)
|
|
181
|
-
if (options.bytecode !== false) {
|
|
182
|
-
args.push('--bytecode');
|
|
183
|
-
}
|
|
184
|
-
|
|
175
|
+
info('Build-time route discovery enabled.');
|
|
185
176
|
spin.update('Compiling... (this may take a minute)');
|
|
186
177
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
178
|
+
const { success: ok, outputs } = await runVirtualEntryBuild({
|
|
179
|
+
cwd,
|
|
180
|
+
entryFile: file,
|
|
181
|
+
outfile,
|
|
182
|
+
target: options.target,
|
|
183
|
+
minify: options.minify,
|
|
184
|
+
bytecode: options.bytecode !== false,
|
|
185
|
+
compile: true,
|
|
191
186
|
});
|
|
192
187
|
|
|
193
|
-
|
|
194
|
-
const exitCode = await proc.exited;
|
|
195
|
-
|
|
196
|
-
if (exitCode !== 0) {
|
|
197
|
-
// Read error output
|
|
198
|
-
const errorText = await new Response(proc.stderr).text();
|
|
188
|
+
if (!ok) {
|
|
199
189
|
spin.stop('Compilation failed', true);
|
|
200
|
-
logError(
|
|
190
|
+
logError(
|
|
191
|
+
'Bun.build failed. Check that api/page directories and route files are valid.'
|
|
192
|
+
);
|
|
201
193
|
process.exit(1);
|
|
202
194
|
}
|
|
203
195
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const executableFile = Bun.file(outfile);
|
|
208
|
-
size = executableFile.size;
|
|
209
|
-
}
|
|
196
|
+
const size = existsSync(outfile)
|
|
197
|
+
? Bun.file(outfile).size
|
|
198
|
+
: (outputs[0]?.size ?? 0);
|
|
210
199
|
|
|
211
200
|
spin.stop('Compilation completed successfully!');
|
|
212
201
|
newline();
|
|
213
202
|
success(`Executable: ${outfile}`);
|
|
214
|
-
if (size > 0) {
|
|
215
|
-
|
|
216
|
-
|
|
203
|
+
if (size > 0) info(`Size: ${formatSize(size)}`);
|
|
204
|
+
newline();
|
|
205
|
+
info(
|
|
206
|
+
'Standalone binary — copy it anywhere, no Bun required on the target.'
|
|
207
|
+
);
|
|
208
|
+
dim(
|
|
209
|
+
'All routes, pages, and assets are embedded inside the binary.'
|
|
210
|
+
);
|
|
217
211
|
newline();
|
|
218
|
-
info('Your standalone executable is ready to run!');
|
|
219
|
-
|
|
220
212
|
if (process.platform !== 'win32') {
|
|
221
|
-
dim(`Make
|
|
222
|
-
dim(`Run
|
|
213
|
+
dim(`Make executable: chmod +x ${outfile}`);
|
|
214
|
+
dim(`Run: ./${outfile}`);
|
|
223
215
|
} else {
|
|
224
|
-
dim(`Run
|
|
216
|
+
dim(`Run: ${outfile}`);
|
|
225
217
|
}
|
|
226
218
|
newline();
|
|
227
219
|
} catch (err) {
|
|
@@ -230,21 +222,3 @@ export const buildExecutableCommand = new Command('build:executable')
|
|
|
230
222
|
process.exit(1);
|
|
231
223
|
}
|
|
232
224
|
});
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Get the project name from package.json
|
|
236
|
-
* Falls back to 'app' if not found
|
|
237
|
-
*/
|
|
238
|
-
function getProjectName(): string {
|
|
239
|
-
try {
|
|
240
|
-
const packageJsonPath = join(process.cwd(), 'package.json');
|
|
241
|
-
if (existsSync(packageJsonPath)) {
|
|
242
|
-
const content = readFileSync(packageJsonPath, 'utf-8');
|
|
243
|
-
const packageJson = JSON.parse(content);
|
|
244
|
-
return packageJson?.name || 'app';
|
|
245
|
-
}
|
|
246
|
-
} catch (err) {
|
|
247
|
-
// Ignore errors
|
|
248
|
-
}
|
|
249
|
-
return 'app';
|
|
250
|
-
}
|
package/src/commands/create.ts
CHANGED
|
@@ -82,6 +82,7 @@ export const createCommand = new Command('create')
|
|
|
82
82
|
info('Creating project with the following configuration:');
|
|
83
83
|
newline();
|
|
84
84
|
console.log(` Name: ${projectName}`);
|
|
85
|
+
console.log(` Config File: burger.config.ts`);
|
|
85
86
|
if (options.useApi) {
|
|
86
87
|
console.log(` API Routes: ${options.apiDir || 'api'}`);
|
|
87
88
|
}
|
|
@@ -106,10 +107,13 @@ export const createCommand = new Command('create')
|
|
|
106
107
|
console.log(` 2. Start the development server:`);
|
|
107
108
|
command('bun run dev');
|
|
108
109
|
newline();
|
|
109
|
-
console.log(` 3.
|
|
110
|
+
console.log(` 3. Edit config if needed:`);
|
|
111
|
+
command('burger.config.ts');
|
|
112
|
+
newline();
|
|
113
|
+
console.log(` 4. Open your browser:`);
|
|
110
114
|
console.log(` ${highlight('http://localhost:4000')}`);
|
|
111
115
|
newline();
|
|
112
|
-
console.log(`
|
|
116
|
+
console.log(` 5. Add middleware (optional):`);
|
|
113
117
|
command('burger-api add cors logger');
|
|
114
118
|
newline();
|
|
115
119
|
success('Happy coding!');
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* This makes it easy to add new commands and provide helpful error messages.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { readFileSync } from 'fs';
|
|
14
|
+
import { join } from 'path';
|
|
13
15
|
import { Command } from 'commander';
|
|
14
16
|
import { createCommand } from './commands/create';
|
|
15
17
|
import { addCommand } from './commands/add';
|
|
@@ -18,6 +20,22 @@ import { buildCommand, buildExecutableCommand } from './commands/build';
|
|
|
18
20
|
import { serveCommand } from './commands/serve';
|
|
19
21
|
import { showBanner } from './utils/logger';
|
|
20
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Read CLI version from package.json (single source of truth for publish).
|
|
25
|
+
* @returns The version of the CLI.
|
|
26
|
+
*/
|
|
27
|
+
function getVersion(): string {
|
|
28
|
+
try {
|
|
29
|
+
const pkgPath = join(import.meta.dir, '..', 'package.json');
|
|
30
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as {
|
|
31
|
+
version?: string;
|
|
32
|
+
};
|
|
33
|
+
return pkg.version ?? '0.0.0';
|
|
34
|
+
} catch {
|
|
35
|
+
return '0.0.0';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
21
39
|
/**
|
|
22
40
|
* Create the main CLI program
|
|
23
41
|
* This is what runs when someone types 'burger-api' in their terminal
|
|
@@ -28,7 +46,7 @@ const program = new Command();
|
|
|
28
46
|
program
|
|
29
47
|
.name('burger-api')
|
|
30
48
|
.description('Simple tool to work with BurgerAPI projects')
|
|
31
|
-
.version(
|
|
49
|
+
.version(getVersion());
|
|
32
50
|
|
|
33
51
|
// Add all our commands to the CLI
|
|
34
52
|
// Each command is defined in its own file for better organization
|
|
@@ -41,7 +59,7 @@ program.addCommand(serveCommand); // Run development server
|
|
|
41
59
|
|
|
42
60
|
// Show banner + help when no command is provided
|
|
43
61
|
program.action(() => {
|
|
44
|
-
showBanner();
|
|
62
|
+
showBanner(getVersion());
|
|
45
63
|
program.help();
|
|
46
64
|
});
|
|
47
65
|
|
package/src/types/index.ts
CHANGED
|
@@ -51,3 +51,15 @@ export interface GitHubFile {
|
|
|
51
51
|
download_url?: string;
|
|
52
52
|
size: number;
|
|
53
53
|
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Build-time configuration for Burger API (conventions or burger.config.ts).
|
|
57
|
+
* Used by the CLI when generating the virtual entry and scanning routes.
|
|
58
|
+
*/
|
|
59
|
+
export interface BuildConfig {
|
|
60
|
+
apiDir: string;
|
|
61
|
+
pageDir: string;
|
|
62
|
+
apiPrefix: string;
|
|
63
|
+
pagePrefix: string;
|
|
64
|
+
debug?: boolean;
|
|
65
|
+
}
|