vite.config.ts 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import { defineConfig } from 'vite'
  2. import react from '@vitejs/plugin-react'
  3. import path from 'path'
  4. // https://vite.dev/config/
  5. export default defineConfig({
  6. plugins: [react()],
  7. resolve: {
  8. alias: {
  9. '@': path.resolve(__dirname, './src'),
  10. },
  11. },
  12. server: {
  13. port: parseInt(process.env.PORT || '5173'),
  14. proxy: {
  15. // WebSocket endpoints
  16. '/ws': {
  17. target: 'ws://localhost:8080',
  18. ws: true,
  19. // Suppress connection errors (common during backend restarts)
  20. configure: (proxy, _options) => {
  21. // Handle proxy errors silently for expected connection issues
  22. const isConnectionError = (err: Error & { code?: string }) => {
  23. const msg = err.message || ''
  24. const code = err.code || ''
  25. // Check error code (most reliable for AggregateError)
  26. if (['ECONNRESET', 'ECONNREFUSED', 'EPIPE', 'ETIMEDOUT'].includes(code)) {
  27. return true
  28. }
  29. // Check message as fallback
  30. if (msg.includes('ECONNRESET') || msg.includes('ECONNREFUSED') ||
  31. msg.includes('EPIPE') || msg.includes('ETIMEDOUT') ||
  32. msg.includes('AggregateError')) {
  33. return true
  34. }
  35. return false
  36. }
  37. const handleError = (err: Error) => {
  38. if (isConnectionError(err)) {
  39. return // Silently ignore connection errors
  40. }
  41. // Only log unexpected errors
  42. console.error('WebSocket proxy error:', err.message)
  43. }
  44. proxy.on('error', handleError)
  45. proxy.on('proxyReqWs', (_proxyReq, _req, socket) => {
  46. socket.on('error', (err) => {
  47. if (!isConnectionError(err)) {
  48. console.error('WebSocket socket error:', err.message)
  49. }
  50. })
  51. })
  52. },
  53. },
  54. // API endpoints - proxy all backend routes
  55. '/send_home': 'http://localhost:8080',
  56. '/send_coordinate': 'http://localhost:8080',
  57. '/stop_execution': 'http://localhost:8080',
  58. '/move_to_center': 'http://localhost:8080',
  59. '/move_to_perimeter': 'http://localhost:8080',
  60. '/set_speed': 'http://localhost:8080',
  61. '/run_theta_rho': 'http://localhost:8080',
  62. '/pause_execution': 'http://localhost:8080',
  63. '/resume_execution': 'http://localhost:8080',
  64. '/skip_pattern': 'http://localhost:8080',
  65. '/serial_status': 'http://localhost:8080',
  66. '/list_serial_ports': 'http://localhost:8080',
  67. '/connect': 'http://localhost:8080',
  68. '/disconnect': 'http://localhost:8080',
  69. '/get_speed': 'http://localhost:8080',
  70. '/list_theta_rho_files': 'http://localhost:8080',
  71. '/list_theta_rho_files_with_metadata': 'http://localhost:8080',
  72. '/list_all_playlists': 'http://localhost:8080',
  73. '/get_playlist': 'http://localhost:8080',
  74. '/create_playlist': 'http://localhost:8080',
  75. '/modify_playlist': 'http://localhost:8080',
  76. '/delete_playlist': 'http://localhost:8080',
  77. '/rename_playlist': 'http://localhost:8080',
  78. '/run_playlist': 'http://localhost:8080',
  79. '/add_to_playlist': 'http://localhost:8080',
  80. '/preview_thr': 'http://localhost:8080',
  81. '/preview_thr_batch': 'http://localhost:8080',
  82. '/preview': 'http://localhost:8080',
  83. '/get_theta_rho_coordinates': 'http://localhost:8080',
  84. '/get_led_config': 'http://localhost:8080',
  85. '/set_led_config': 'http://localhost:8080',
  86. '/api': 'http://localhost:8080',
  87. '/restart': 'http://localhost:8080',
  88. '/static': 'http://localhost:8080',
  89. },
  90. },
  91. build: {
  92. outDir: '../static/dist',
  93. emptyOutDir: true,
  94. },
  95. })