|
| 1 | +import { existsSync } from 'node:fs'; |
| 2 | +import path from 'node:path'; |
| 3 | +import { spawn } from 'node:child_process'; |
1 | 4 | import chalk from 'chalk'; |
2 | 5 | import { Command } from 'commander'; |
3 | 6 | import { loadCLIConfig } from '@/cli/utils/config'; |
4 | | -import { PACKAGE_ROOT } from '@/cli/utils/resolve'; |
5 | | -import { linkContent } from '@/cli/utils/scaffold'; |
| 7 | + |
| 8 | +function resolveServerEntry(projectRoot: string, preset?: string): string { |
| 9 | + if (preset === 'vercel' || preset === 'vercel-static') { |
| 10 | + return path.resolve(projectRoot, '.vercel/output/server/index.mjs'); |
| 11 | + } |
| 12 | + return path.resolve(projectRoot, '.output/server/index.mjs'); |
| 13 | +} |
6 | 14 |
|
7 | 15 | export const startCommand = new Command('start') |
8 | 16 | .description('Start production server') |
9 | 17 | .option('-p, --port <port>', 'Port number', '3000') |
10 | 18 | .option('--config <path>', 'Path to chronicle.yaml') |
11 | | - .option('--host <host>', 'Host address', 'localhost') |
| 19 | + .option('--host <host>', 'Host address', '0.0.0.0') |
| 20 | + .option('--preset <preset>', 'Deploy preset (must match build preset)') |
12 | 21 | .action(async options => { |
13 | | - const { config, projectRoot, configPath } = await loadCLIConfig(options.config); |
14 | | - const port = parseInt(options.port, 10); |
15 | | - await linkContent(projectRoot, config); |
| 22 | + const { config, projectRoot } = await loadCLIConfig(options.config); |
| 23 | + const preset = options.preset ?? config.preset; |
| 24 | + const serverEntry = resolveServerEntry(projectRoot, preset); |
16 | 25 |
|
17 | | - console.log(chalk.cyan('Starting production server...')); |
| 26 | + if (!existsSync(serverEntry)) { |
| 27 | + console.error(chalk.red(`No build found at ${serverEntry}`)); |
| 28 | + console.error(chalk.red('Run `chronicle build` first.')); |
| 29 | + process.exit(1); |
| 30 | + } |
18 | 31 |
|
19 | | - const { preview } = await import('vite'); |
20 | | - const { createViteConfig } = await import('@/server/vite-config'); |
| 32 | + console.log(chalk.cyan('Starting production server...')); |
21 | 33 |
|
22 | | - const viteConfig = await createViteConfig({ packageRoot: PACKAGE_ROOT, projectRoot, configPath }); |
23 | | - const server = await preview({ |
24 | | - ...viteConfig, |
25 | | - preview: { port, host: options.host } |
| 34 | + const child = spawn(process.execPath, [serverEntry], { |
| 35 | + stdio: 'inherit', |
| 36 | + env: { |
| 37 | + ...process.env, |
| 38 | + PORT: options.port, |
| 39 | + HOST: options.host, |
| 40 | + }, |
26 | 41 | }); |
27 | 42 |
|
28 | | - server.printUrls(); |
| 43 | + const shutdown = () => { |
| 44 | + child.kill('SIGTERM'); |
| 45 | + }; |
| 46 | + process.once('SIGINT', shutdown); |
| 47 | + process.once('SIGTERM', shutdown); |
| 48 | + |
| 49 | + child.on('exit', (code) => { |
| 50 | + process.exit(code ?? 0); |
| 51 | + }); |
29 | 52 | }); |
0 commit comments