File size: 2,659 Bytes
ca51841
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import { defineConfig } from 'vite';
import http from 'node:http';
import https from 'node:https';

/**
 * Dev-only CORS proxy middleware.
 * Browser fetches /lw-proxy/<path> with X-LW-Target header → Vite server forwards to target (no CORS).
 */
const lwProxyPlugin = {
  name: 'lw-proxy',
  configureServer(server) {
    server.middlewares.use('/lw-proxy', (req, res) => {
      const target = req.headers['x-lw-target'];
      if (!target) {
        res.writeHead(400, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ error: 'Missing X-LW-Target header' }));
        return;
      }

      let targetUrl;
      try {
        // req.url is the path AFTER /lw-proxy (Connect strips the mount point)
        targetUrl = new URL(req.url ?? '/', target);
      } catch {
        res.writeHead(400, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ error: 'Invalid target URL' }));
        return;
      }

      const httpModule = targetUrl.protocol === 'https:' ? https : http;

      // Forward headers, stripping browser/CORS-related ones
      const fwdHeaders = {};
      for (const [k, v] of Object.entries(req.headers)) {
        const kl = k.toLowerCase();
        if (kl === 'x-lw-target' || kl === 'host' || kl === 'origin' || kl === 'referer') continue;
        fwdHeaders[k] = v;
      }
      fwdHeaders['host'] = targetUrl.host;

      const options = {
        hostname: targetUrl.hostname,
        port: targetUrl.port || (targetUrl.protocol === 'https:' ? 443 : 80),
        path: targetUrl.pathname + (targetUrl.search || ''),
        method: req.method,
        headers: fwdHeaders,
      };

      const proxyReq = httpModule.request(options, (proxyRes) => {
        res.writeHead(proxyRes.statusCode ?? 200, proxyRes.headers);
        proxyRes.pipe(res); // stream response directly (supports SSE)
      });

      proxyReq.on('error', (err) => {
        if (!res.headersSent) {
          res.writeHead(502, { 'Content-Type': 'application/json' });
        }
        res.end(JSON.stringify({ error: err.message }));
      });

      req.pipe(proxyReq); // forward request body (needed for POST /v1/chat/completions)
    });
  },
};

export default defineConfig({
  plugins: [lwProxyPlugin],
  build: {
    target: 'esnext',
    minify: 'esbuild',
    chunkSizeWarningLimit: 600,
    rollupOptions: {
      output: {
        manualChunks(id) {
          if (id.includes('highlight.js')) return 'hljs';
          if (id.includes('marked')) return 'marked';
        },
      },
    },
  },
  test: {
    environment: 'jsdom',
    globals: true,
    setupFiles: ['./tests/setup.js'],
  },
});