dev.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import { spawn } from 'child_process';
  2. import { existsSync, copyFileSync } from 'fs';
  3. import { join, dirname } from 'path';
  4. import { fileURLToPath } from 'url';
  5. const __dirname = dirname(fileURLToPath(import.meta.url));
  6. const backendDir = join(__dirname, 'backend');
  7. const frontendDir = join(__dirname, 'frontend');
  8. const backendEnv = join(backendDir, '.env');
  9. const backendEnvExample = join(backendDir, '.env.example');
  10. if (!existsSync(backendEnv) && existsSync(backendEnvExample)) {
  11. console.log('Creating .env from .env.example...');
  12. copyFileSync(backendEnvExample, backendEnv);
  13. console.log('Please edit backend/.env and add your DASHSCOPE_API_KEY and DASHSCOPE_APP_ID');
  14. }
  15. const BACKEND_URL = 'http://localhost:3101';
  16. const HEALTH_ENDPOINT = `${BACKEND_URL}/api/health`;
  17. function waitForBackend(maxRetries = 30, interval = 1000) {
  18. return new Promise((resolve, reject) => {
  19. let retries = 0;
  20. const check = async () => {
  21. try {
  22. const response = await fetch(HEALTH_ENDPOINT);
  23. if (response.ok) {
  24. console.log('Backend is ready!');
  25. resolve(true);
  26. return;
  27. }
  28. } catch {
  29. }
  30. retries++;
  31. if (retries >= maxRetries) {
  32. reject(new Error('Backend failed to start'));
  33. return;
  34. }
  35. setTimeout(check, interval);
  36. };
  37. check();
  38. });
  39. }
  40. function startBackend() {
  41. console.log('Starting backend...');
  42. const backend = spawn('pnpm', ['dev'], {
  43. cwd: backendDir,
  44. shell: true,
  45. stdio: 'pipe'
  46. });
  47. backend.stdout.on('data', (data) => {
  48. process.stdout.write(`[backend] ${data}`);
  49. });
  50. backend.stderr.on('data', (data) => {
  51. process.stderr.write(`[backend] ${data}`);
  52. });
  53. backend.on('close', (code) => {
  54. if (code !== 0) {
  55. console.error(`Backend process exited with code ${code}`);
  56. }
  57. process.exit(code);
  58. });
  59. return backend;
  60. }
  61. function startFrontend() {
  62. console.log('Starting frontend...');
  63. const frontend = spawn('pnpm', ['start'], {
  64. cwd: frontendDir,
  65. shell: true,
  66. stdio: 'pipe'
  67. });
  68. frontend.stdout.on('data', (data) => {
  69. process.stdout.write(`[frontend] ${data}`);
  70. });
  71. frontend.stderr.on('data', (data) => {
  72. process.stderr.write(`[frontend] ${data}`);
  73. });
  74. frontend.on('close', (code) => {
  75. if (code !== 0) {
  76. console.error(`Frontend process exited with code ${code}`);
  77. }
  78. process.exit(code);
  79. });
  80. return frontend;
  81. }
  82. async function main() {
  83. console.log('=== Starting Dev Server ===\n');
  84. const backend = startBackend();
  85. try {
  86. await waitForBackend();
  87. startFrontend();
  88. } catch (error) {
  89. console.error(error.message);
  90. backend.kill();
  91. process.exit(1);
  92. }
  93. }
  94. main();