feat(dev): support Vercel serverless API handlers locally in Vite dev server

This commit is contained in:
Christian Vidal Wolf
2026-05-20 13:40:51 +02:00
parent b2c6bce8eb
commit 4612f13968
+60
View File
@@ -4,6 +4,14 @@ import path from 'path';
import {defineConfig, loadEnv} from 'vite'; import {defineConfig, loadEnv} from 'vite';
import { getBcConfig, getBCToken, findItem, patchItemCpnpNo, fetchAllItems, buildWorkbook } from './bc-runtime.js'; import { getBcConfig, getBCToken, findItem, patchItemCpnpNo, fetchAllItems, buildWorkbook } from './bc-runtime.js';
import * as XLSX from 'xlsx'; import * as XLSX from 'xlsx';
// @ts-ignore
import dropboxProxyHandler from './api/dropbox-proxy.js';
// @ts-ignore
import dropboxSyncHandler from './api/dropbox-sync.js';
// @ts-ignore
import backupHandler from './api/backup.js';
// @ts-ignore
import usersAdminHandler from './api/users-admin.js';
async function readJsonBody(req: any): Promise<any> { async function readJsonBody(req: any): Promise<any> {
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
@@ -35,6 +43,58 @@ export default defineConfig(({mode}) => {
const url = new URL(req.url || '/', 'http://localhost'); const url = new URL(req.url || '/', 'http://localhost');
const config = getBcConfig(env); const config = getBcConfig(env);
// Populate process.env with loaded env variables for serverless handlers
Object.assign(process.env, env);
// Helper to adapt Node.js req/res to Vercel signature
const adaptVercelHandler = async (handler: any) => {
(req as any).query = Object.fromEntries(url.searchParams.entries());
try {
(req as any).body = await readJsonBody(req);
} catch {
(req as any).body = {};
}
(res as any).status = (code: number) => {
res.statusCode = code;
return res;
};
(res as any).json = (data: any) => {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(data));
};
(res as any).send = (data: any) => {
if (data instanceof Buffer) {
res.end(data);
} else if (typeof data === 'object') {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(data));
} else {
res.end(data);
}
};
await handler(req, res);
};
if (url.pathname === '/api/dropbox-proxy') {
await adaptVercelHandler(dropboxProxyHandler);
return;
}
if (url.pathname === '/api/dropbox-sync') {
await adaptVercelHandler(dropboxSyncHandler);
return;
}
if (url.pathname === '/api/backup') {
await adaptVercelHandler(backupHandler);
return;
}
if (url.pathname === '/api/users-admin') {
await adaptVercelHandler(usersAdminHandler);
return;
}
if (url.pathname === '/api/bc-proxy') { if (url.pathname === '/api/bc-proxy') {
if (req.method === 'OPTIONS') { if (req.method === 'OPTIONS') {
res.statusCode = 204; res.statusCode = 204;