mirror of
https://github.com/christianvidalwolf-prog/Craze-Data-check.git
synced 2026-08-03 16:25:24 +02:00
fix(dropbox): use direct raw fallback
This commit is contained in:
+142
-132
@@ -29,9 +29,147 @@ async function readJsonBody(req: any): Promise<any> {
|
||||
});
|
||||
}
|
||||
|
||||
function createLocalApiMiddleware(env: Record<string, string>, prodEnv: Record<string, string>) {
|
||||
return async (req: any, res: any, next: any) => {
|
||||
try {
|
||||
const url = new URL(req.url || '/', 'http://localhost');
|
||||
const config = getBcConfig(env);
|
||||
|
||||
// Populate process.env with loaded env variables for serverless handlers.
|
||||
// The Dropbox proxy reads env at request time so preview/dev/production
|
||||
// can share the same handler implementation.
|
||||
Object.assign(process.env, prodEnv, 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 (req.method === 'OPTIONS') {
|
||||
res.statusCode = 204;
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
if (req.method !== 'POST') {
|
||||
res.statusCode = 405;
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ error: 'Method not allowed' }));
|
||||
return;
|
||||
}
|
||||
|
||||
const body = await readJsonBody(req);
|
||||
const { articleNo, cpnpNo } = body || {};
|
||||
if (!articleNo || cpnpNo === undefined) {
|
||||
res.statusCode = 400;
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ error: 'Missing articleNo or cpnpNo' }));
|
||||
return;
|
||||
}
|
||||
|
||||
const token = await getBCToken(config);
|
||||
const item = await findItem(config, token, articleNo);
|
||||
await patchItemCpnpNo(config, token, item, String(cpnpNo));
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ success: true, articleNo, cpnpNo }));
|
||||
return;
|
||||
}
|
||||
|
||||
if (url.pathname === '/api/bc-export') {
|
||||
if (req.method === 'OPTIONS') {
|
||||
res.statusCode = 204;
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
if (req.method !== 'GET') {
|
||||
res.statusCode = 405;
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ error: 'Method not allowed' }));
|
||||
return;
|
||||
}
|
||||
|
||||
const token = await getBCToken(config);
|
||||
const items = await fetchAllItems(config, token);
|
||||
|
||||
if (url.searchParams.get('format') === 'json') {
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ success: true, count: items.length, items }));
|
||||
return;
|
||||
}
|
||||
|
||||
const workbook = buildWorkbook(items);
|
||||
const buffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'buffer' });
|
||||
const dateStr = new Date().toISOString().split('T')[0];
|
||||
res.statusCode = 200;
|
||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
res.setHeader('Content-Disposition', `attachment; filename="BusinessCentral_Items_${dateStr}.xlsx"`);
|
||||
res.setHeader('Cache-Control', 'no-store');
|
||||
res.end(buffer);
|
||||
return;
|
||||
}
|
||||
} catch (err: any) {
|
||||
const message = err?.message || String(err);
|
||||
if ((req.url || '').startsWith('/api/bc-')) {
|
||||
res.statusCode = 500;
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ success: false, error: message }));
|
||||
return;
|
||||
}
|
||||
console.error('[bc-local-api]', message);
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
||||
export default defineConfig(({mode}) => {
|
||||
const env = loadEnv(mode, '.', '');
|
||||
const prodEnv = loadEnv('production', '.', '');
|
||||
const localApiMiddleware = createLocalApiMiddleware(env, prodEnv);
|
||||
return {
|
||||
plugins: [
|
||||
react(),
|
||||
@@ -39,138 +177,10 @@ export default defineConfig(({mode}) => {
|
||||
{
|
||||
name: 'bc-local-api',
|
||||
configureServer(server) {
|
||||
server.middlewares.use(async (req, res, next) => {
|
||||
try {
|
||||
const url = new URL(req.url || '/', 'http://localhost');
|
||||
const config = getBcConfig(env);
|
||||
|
||||
// Populate process.env with loaded env variables for serverless handlers
|
||||
Object.assign(process.env, prodEnv, 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 (req.method === 'OPTIONS') {
|
||||
res.statusCode = 204;
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
if (req.method !== 'POST') {
|
||||
res.statusCode = 405;
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ error: 'Method not allowed' }));
|
||||
return;
|
||||
}
|
||||
|
||||
const body = await readJsonBody(req);
|
||||
const { articleNo, cpnpNo } = body || {};
|
||||
if (!articleNo || cpnpNo === undefined) {
|
||||
res.statusCode = 400;
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ error: 'Missing articleNo or cpnpNo' }));
|
||||
return;
|
||||
}
|
||||
|
||||
const token = await getBCToken(config);
|
||||
const item = await findItem(config, token, articleNo);
|
||||
await patchItemCpnpNo(config, token, item, String(cpnpNo));
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ success: true, articleNo, cpnpNo }));
|
||||
return;
|
||||
}
|
||||
|
||||
if (url.pathname === '/api/bc-export') {
|
||||
if (req.method === 'OPTIONS') {
|
||||
res.statusCode = 204;
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
if (req.method !== 'GET') {
|
||||
res.statusCode = 405;
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ error: 'Method not allowed' }));
|
||||
return;
|
||||
}
|
||||
|
||||
const token = await getBCToken(config);
|
||||
const items = await fetchAllItems(config, token);
|
||||
|
||||
if (url.searchParams.get('format') === 'json') {
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ success: true, count: items.length, items }));
|
||||
return;
|
||||
}
|
||||
|
||||
const workbook = buildWorkbook(items);
|
||||
const buffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'buffer' });
|
||||
const dateStr = new Date().toISOString().split('T')[0];
|
||||
res.statusCode = 200;
|
||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
res.setHeader('Content-Disposition', `attachment; filename="BusinessCentral_Items_${dateStr}.xlsx"`);
|
||||
res.setHeader('Cache-Control', 'no-store');
|
||||
res.end(buffer);
|
||||
return;
|
||||
}
|
||||
} catch (err: any) {
|
||||
const message = err?.message || String(err);
|
||||
if ((req.url || '').startsWith('/api/bc-')) {
|
||||
res.statusCode = 500;
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ success: false, error: message }));
|
||||
return;
|
||||
}
|
||||
console.error('[bc-local-api]', message);
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
server.middlewares.use(localApiMiddleware);
|
||||
},
|
||||
configurePreviewServer(server) {
|
||||
server.middlewares.use(localApiMiddleware);
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user