@burger-api/cli 0.6.6 → 0.7.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 +66 -57
- package/README.md +565 -656
- package/package.json +50 -50
- package/src/commands/add.ts +201 -201
- package/src/commands/build.ts +250 -250
- package/src/commands/create.ts +229 -229
- package/src/commands/list.ts +88 -88
- package/src/commands/serve.ts +100 -100
- package/src/index.ts +59 -59
- package/src/types/index.ts +53 -53
- package/src/utils/github.ts +260 -260
- package/src/utils/logger.ts +478 -478
- package/src/utils/templates.ts +1116 -1120
package/src/commands/build.ts
CHANGED
|
@@ -1,250 +1,250 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Build Commands
|
|
3
|
-
*
|
|
4
|
-
* Two commands for packaging your Burger API project:
|
|
5
|
-
* 1. `burger-api build <file>` - Bundle to single JS file
|
|
6
|
-
* 2. `burger-api build:executable <file>` - Compile to standalone executable
|
|
7
|
-
*
|
|
8
|
-
* These are wrappers around Bun's build commands with sensible defaults.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { Command } from 'commander';
|
|
12
|
-
import { existsSync, readFileSync } from 'fs';
|
|
13
|
-
import { join } from 'path';
|
|
14
|
-
import {
|
|
15
|
-
spinner,
|
|
16
|
-
success,
|
|
17
|
-
error as logError,
|
|
18
|
-
info,
|
|
19
|
-
newline,
|
|
20
|
-
formatSize,
|
|
21
|
-
dim,
|
|
22
|
-
} from '../utils/logger';
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Build command options
|
|
26
|
-
*/
|
|
27
|
-
interface BuildCommandOptions {
|
|
28
|
-
outfile: string;
|
|
29
|
-
minify?: boolean;
|
|
30
|
-
sourcemap?: string;
|
|
31
|
-
target?: string;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Build executable command options
|
|
36
|
-
*/
|
|
37
|
-
interface BuildExecutableOptions {
|
|
38
|
-
outfile?: string;
|
|
39
|
-
target?: string;
|
|
40
|
-
minify: boolean;
|
|
41
|
-
bytecode: boolean;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Create the "build" command
|
|
46
|
-
* Bundles your code into a single JavaScript file
|
|
47
|
-
*/
|
|
48
|
-
export const buildCommand = new Command('build')
|
|
49
|
-
.description('Bundle your project to a single JavaScript file')
|
|
50
|
-
.argument('<file>', 'Entry file to build (e.g., index.ts)')
|
|
51
|
-
.option('--outfile <path>', 'Output file path', '.build/bundle.js')
|
|
52
|
-
.option('--minify', 'Minify the output')
|
|
53
|
-
.option(
|
|
54
|
-
'--sourcemap <type>',
|
|
55
|
-
'Generate sourcemaps (inline, linked, or none)'
|
|
56
|
-
)
|
|
57
|
-
.option('--target <target>', 'Target environment (e.g., bun, node)')
|
|
58
|
-
.action(async (file: string, options: BuildCommandOptions) => {
|
|
59
|
-
// Check if the input file exists
|
|
60
|
-
if (!existsSync(file)) {
|
|
61
|
-
logError(`File not found: ${file}`);
|
|
62
|
-
process.exit(1);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const spin = spinner('Building project...');
|
|
66
|
-
|
|
67
|
-
try {
|
|
68
|
-
// Build the command arguments for Bun
|
|
69
|
-
const args = ['build', file];
|
|
70
|
-
|
|
71
|
-
// Add output file
|
|
72
|
-
args.push('--outfile', options.outfile);
|
|
73
|
-
|
|
74
|
-
// Add optional flags
|
|
75
|
-
if (options.minify) {
|
|
76
|
-
args.push('--minify');
|
|
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',
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
// Wait for it to complete
|
|
93
|
-
const exitCode = await proc.exited;
|
|
94
|
-
|
|
95
|
-
if (exitCode !== 0) {
|
|
96
|
-
// Read error output
|
|
97
|
-
const errorText = await new Response(proc.stderr).text();
|
|
98
|
-
spin.stop('Build failed', true);
|
|
99
|
-
logError(errorText || 'Build process failed');
|
|
100
|
-
process.exit(1);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Get file size
|
|
104
|
-
const outputFile = Bun.file(options.outfile);
|
|
105
|
-
const size = outputFile.size;
|
|
106
|
-
|
|
107
|
-
spin.stop('Build completed successfully!');
|
|
108
|
-
newline();
|
|
109
|
-
success(`Output: ${options.outfile}`);
|
|
110
|
-
info(`Size: ${formatSize(size)}`);
|
|
111
|
-
newline();
|
|
112
|
-
dim('Run your bundle with: bun ' + options.outfile);
|
|
113
|
-
newline();
|
|
114
|
-
} catch (err) {
|
|
115
|
-
spin.stop('Build failed', true);
|
|
116
|
-
logError(err instanceof Error ? err.message : 'Unknown error');
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Create the "build:executable" command
|
|
123
|
-
* Compiles your code to a standalone executable
|
|
124
|
-
*/
|
|
125
|
-
export const buildExecutableCommand = new Command('build:executable')
|
|
126
|
-
.description('Compile your project to a standalone executable')
|
|
127
|
-
.argument('<file>', 'Entry file to compile (e.g., index.ts)')
|
|
128
|
-
.option('--outfile <path>', 'Output file path')
|
|
129
|
-
.option(
|
|
130
|
-
'--target <target>',
|
|
131
|
-
'Target platform (bun-windows-x64, bun-linux-x64, bun-darwin-arm64)'
|
|
132
|
-
)
|
|
133
|
-
.option('--minify', 'Minify the output (enabled by default)', true)
|
|
134
|
-
.option('--no-bytecode', 'Disable bytecode compilation')
|
|
135
|
-
.action(async (file: string, options: BuildExecutableOptions) => {
|
|
136
|
-
// Check if the input file exists
|
|
137
|
-
if (!existsSync(file)) {
|
|
138
|
-
logError(`File not found: ${file}`);
|
|
139
|
-
process.exit(1);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Determine output filename
|
|
143
|
-
let outfile = options.outfile;
|
|
144
|
-
if (!outfile) {
|
|
145
|
-
// Get project name from package.json or use basename
|
|
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
|
|
150
|
-
const isWindows =
|
|
151
|
-
options.target?.includes('windows') ||
|
|
152
|
-
(!options.target && process.platform === 'win32');
|
|
153
|
-
|
|
154
|
-
if (isWindows) {
|
|
155
|
-
outfile = `.build/${projectName}.exe`;
|
|
156
|
-
} else {
|
|
157
|
-
outfile = `.build/${projectName}`;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const spin = spinner('Compiling to executable...');
|
|
162
|
-
|
|
163
|
-
try {
|
|
164
|
-
// Build the command arguments for Bun
|
|
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
|
-
|
|
185
|
-
spin.update('Compiling... (this may take a minute)');
|
|
186
|
-
|
|
187
|
-
// Run the build using Bun.spawn
|
|
188
|
-
const proc = Bun.spawn(['bun', ...args], {
|
|
189
|
-
stdout: 'pipe',
|
|
190
|
-
stderr: 'pipe',
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
// Wait for it to complete
|
|
194
|
-
const exitCode = await proc.exited;
|
|
195
|
-
|
|
196
|
-
if (exitCode !== 0) {
|
|
197
|
-
// Read error output
|
|
198
|
-
const errorText = await new Response(proc.stderr).text();
|
|
199
|
-
spin.stop('Compilation failed', true);
|
|
200
|
-
logError(errorText || 'Compilation process failed');
|
|
201
|
-
process.exit(1);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Get file size - check if file exists first
|
|
205
|
-
let size = 0;
|
|
206
|
-
if (existsSync(outfile)) {
|
|
207
|
-
const executableFile = Bun.file(outfile);
|
|
208
|
-
size = executableFile.size;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
spin.stop('Compilation completed successfully!');
|
|
212
|
-
newline();
|
|
213
|
-
success(`Executable: ${outfile}`);
|
|
214
|
-
if (size > 0) {
|
|
215
|
-
info(`Size: ${formatSize(size)}`);
|
|
216
|
-
}
|
|
217
|
-
newline();
|
|
218
|
-
info('Your standalone executable is ready to run!');
|
|
219
|
-
|
|
220
|
-
if (process.platform !== 'win32') {
|
|
221
|
-
dim(`Make it executable: chmod +x ${outfile}`);
|
|
222
|
-
dim(`Run it: ./${outfile}`);
|
|
223
|
-
} else {
|
|
224
|
-
dim(`Run it: ${outfile}`);
|
|
225
|
-
}
|
|
226
|
-
newline();
|
|
227
|
-
} catch (err) {
|
|
228
|
-
spin.stop('Compilation failed', true);
|
|
229
|
-
logError(err instanceof Error ? err.message : 'Unknown error');
|
|
230
|
-
process.exit(1);
|
|
231
|
-
}
|
|
232
|
-
});
|
|
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
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Build Commands
|
|
3
|
+
*
|
|
4
|
+
* Two commands for packaging your Burger API project:
|
|
5
|
+
* 1. `burger-api build <file>` - Bundle to single JS file
|
|
6
|
+
* 2. `burger-api build:executable <file>` - Compile to standalone executable
|
|
7
|
+
*
|
|
8
|
+
* These are wrappers around Bun's build commands with sensible defaults.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { Command } from 'commander';
|
|
12
|
+
import { existsSync, readFileSync } from 'fs';
|
|
13
|
+
import { join } from 'path';
|
|
14
|
+
import {
|
|
15
|
+
spinner,
|
|
16
|
+
success,
|
|
17
|
+
error as logError,
|
|
18
|
+
info,
|
|
19
|
+
newline,
|
|
20
|
+
formatSize,
|
|
21
|
+
dim,
|
|
22
|
+
} from '../utils/logger';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Build command options
|
|
26
|
+
*/
|
|
27
|
+
interface BuildCommandOptions {
|
|
28
|
+
outfile: string;
|
|
29
|
+
minify?: boolean;
|
|
30
|
+
sourcemap?: string;
|
|
31
|
+
target?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Build executable command options
|
|
36
|
+
*/
|
|
37
|
+
interface BuildExecutableOptions {
|
|
38
|
+
outfile?: string;
|
|
39
|
+
target?: string;
|
|
40
|
+
minify: boolean;
|
|
41
|
+
bytecode: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Create the "build" command
|
|
46
|
+
* Bundles your code into a single JavaScript file
|
|
47
|
+
*/
|
|
48
|
+
export const buildCommand = new Command('build')
|
|
49
|
+
.description('Bundle your project to a single JavaScript file')
|
|
50
|
+
.argument('<file>', 'Entry file to build (e.g., index.ts)')
|
|
51
|
+
.option('--outfile <path>', 'Output file path', '.build/bundle.js')
|
|
52
|
+
.option('--minify', 'Minify the output')
|
|
53
|
+
.option(
|
|
54
|
+
'--sourcemap <type>',
|
|
55
|
+
'Generate sourcemaps (inline, linked, or none)'
|
|
56
|
+
)
|
|
57
|
+
.option('--target <target>', 'Target environment (e.g., bun, node)')
|
|
58
|
+
.action(async (file: string, options: BuildCommandOptions) => {
|
|
59
|
+
// Check if the input file exists
|
|
60
|
+
if (!existsSync(file)) {
|
|
61
|
+
logError(`File not found: ${file}`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const spin = spinner('Building project...');
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
// Build the command arguments for Bun
|
|
69
|
+
const args = ['build', file];
|
|
70
|
+
|
|
71
|
+
// Add output file
|
|
72
|
+
args.push('--outfile', options.outfile);
|
|
73
|
+
|
|
74
|
+
// Add optional flags
|
|
75
|
+
if (options.minify) {
|
|
76
|
+
args.push('--minify');
|
|
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',
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Wait for it to complete
|
|
93
|
+
const exitCode = await proc.exited;
|
|
94
|
+
|
|
95
|
+
if (exitCode !== 0) {
|
|
96
|
+
// Read error output
|
|
97
|
+
const errorText = await new Response(proc.stderr).text();
|
|
98
|
+
spin.stop('Build failed', true);
|
|
99
|
+
logError(errorText || 'Build process failed');
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Get file size
|
|
104
|
+
const outputFile = Bun.file(options.outfile);
|
|
105
|
+
const size = outputFile.size;
|
|
106
|
+
|
|
107
|
+
spin.stop('Build completed successfully!');
|
|
108
|
+
newline();
|
|
109
|
+
success(`Output: ${options.outfile}`);
|
|
110
|
+
info(`Size: ${formatSize(size)}`);
|
|
111
|
+
newline();
|
|
112
|
+
dim('Run your bundle with: bun ' + options.outfile);
|
|
113
|
+
newline();
|
|
114
|
+
} catch (err) {
|
|
115
|
+
spin.stop('Build failed', true);
|
|
116
|
+
logError(err instanceof Error ? err.message : 'Unknown error');
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Create the "build:executable" command
|
|
123
|
+
* Compiles your code to a standalone executable
|
|
124
|
+
*/
|
|
125
|
+
export const buildExecutableCommand = new Command('build:executable')
|
|
126
|
+
.description('Compile your project to a standalone executable')
|
|
127
|
+
.argument('<file>', 'Entry file to compile (e.g., index.ts)')
|
|
128
|
+
.option('--outfile <path>', 'Output file path')
|
|
129
|
+
.option(
|
|
130
|
+
'--target <target>',
|
|
131
|
+
'Target platform (bun-windows-x64, bun-linux-x64, bun-darwin-arm64)'
|
|
132
|
+
)
|
|
133
|
+
.option('--minify', 'Minify the output (enabled by default)', true)
|
|
134
|
+
.option('--no-bytecode', 'Disable bytecode compilation')
|
|
135
|
+
.action(async (file: string, options: BuildExecutableOptions) => {
|
|
136
|
+
// Check if the input file exists
|
|
137
|
+
if (!existsSync(file)) {
|
|
138
|
+
logError(`File not found: ${file}`);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Determine output filename
|
|
143
|
+
let outfile = options.outfile;
|
|
144
|
+
if (!outfile) {
|
|
145
|
+
// Get project name from package.json or use basename
|
|
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
|
|
150
|
+
const isWindows =
|
|
151
|
+
options.target?.includes('windows') ||
|
|
152
|
+
(!options.target && process.platform === 'win32');
|
|
153
|
+
|
|
154
|
+
if (isWindows) {
|
|
155
|
+
outfile = `.build/${projectName}.exe`;
|
|
156
|
+
} else {
|
|
157
|
+
outfile = `.build/${projectName}`;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const spin = spinner('Compiling to executable...');
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
// Build the command arguments for Bun
|
|
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
|
+
|
|
185
|
+
spin.update('Compiling... (this may take a minute)');
|
|
186
|
+
|
|
187
|
+
// Run the build using Bun.spawn
|
|
188
|
+
const proc = Bun.spawn(['bun', ...args], {
|
|
189
|
+
stdout: 'pipe',
|
|
190
|
+
stderr: 'pipe',
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Wait for it to complete
|
|
194
|
+
const exitCode = await proc.exited;
|
|
195
|
+
|
|
196
|
+
if (exitCode !== 0) {
|
|
197
|
+
// Read error output
|
|
198
|
+
const errorText = await new Response(proc.stderr).text();
|
|
199
|
+
spin.stop('Compilation failed', true);
|
|
200
|
+
logError(errorText || 'Compilation process failed');
|
|
201
|
+
process.exit(1);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Get file size - check if file exists first
|
|
205
|
+
let size = 0;
|
|
206
|
+
if (existsSync(outfile)) {
|
|
207
|
+
const executableFile = Bun.file(outfile);
|
|
208
|
+
size = executableFile.size;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
spin.stop('Compilation completed successfully!');
|
|
212
|
+
newline();
|
|
213
|
+
success(`Executable: ${outfile}`);
|
|
214
|
+
if (size > 0) {
|
|
215
|
+
info(`Size: ${formatSize(size)}`);
|
|
216
|
+
}
|
|
217
|
+
newline();
|
|
218
|
+
info('Your standalone executable is ready to run!');
|
|
219
|
+
|
|
220
|
+
if (process.platform !== 'win32') {
|
|
221
|
+
dim(`Make it executable: chmod +x ${outfile}`);
|
|
222
|
+
dim(`Run it: ./${outfile}`);
|
|
223
|
+
} else {
|
|
224
|
+
dim(`Run it: ${outfile}`);
|
|
225
|
+
}
|
|
226
|
+
newline();
|
|
227
|
+
} catch (err) {
|
|
228
|
+
spin.stop('Compilation failed', true);
|
|
229
|
+
logError(err instanceof Error ? err.message : 'Unknown error');
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
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
|
+
}
|