Fix Vercel function limit - remove unused API endpoints

- Removed fetch-forecast.ts (not used)
- Removed fetch-vendor-stock.ts (not used)
- Removed migrate-experiments.ts (manual SQL migration is sufficient)
- Kept 10 essential API functions (limit is 12 on Hobby plan)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
Christian Vidal Wolf
2026-02-21 00:25:04 +01:00
co-authored by Qwen-Coder
parent edbde19f3a
commit aebebecf1b
3 changed files with 0 additions and 204 deletions
-49
View File
@@ -1,49 +0,0 @@
import type { VercelRequest, VercelResponse } from '@vercel/node';
import fs from 'fs';
import path from 'path';
export default async function handler(req: VercelRequest, res: VercelResponse) {
// CORS headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === 'OPTIONS') {
return res.status(200).end();
}
try {
console.log('[fetch-forecast] Reading Forecast file from local storage...');
// Try multiple possible paths to be robust
const pathsToTry = [
path.join(process.cwd(), 'fc 26.xlsx'),
path.join(process.cwd(), 'public', 'fc 26.xlsx'),
path.join('/Users/christianvidalwolf/github/CrazeAnalytix', 'fc 26.xlsx') // Direct path as fallback for this environment
];
let buffer = null;
let foundPath = '';
for (const p of pathsToTry) {
console.log(`[fetch-forecast] Checking path: ${p}`);
if (fs.existsSync(p)) {
buffer = fs.readFileSync(p);
foundPath = p;
break;
}
}
if (!buffer) {
throw new Error(`Forecast file 'fc 26.xlsx' not found in any of: ${pathsToTry.join(', ')}`);
}
console.log(`[fetch-forecast] Successfully read Forecast Excel from ${foundPath}, size: ${buffer.byteLength}`);
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.status(200).send(buffer);
} catch (error: any) {
console.error('[fetch-forecast] Error:', error);
res.status(500).json({ error: error.message });
}
}
-49
View File
@@ -1,49 +0,0 @@
import type { VercelRequest, VercelResponse } from '@vercel/node';
import fs from 'fs';
import path from 'path';
export default async function handler(req: VercelRequest, res: VercelResponse) {
// CORS headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === 'OPTIONS') {
return res.status(200).end();
}
try {
console.log('[fetch-vendor-stock] Reading Vendor Stock file from local storage...');
// Try multiple possible paths to be robust
const pathsToTry = [
path.join(process.cwd(), 'Vendor Stock.xlsx'),
path.join(process.cwd(), 'public', 'Vendor Stock.xlsx'),
path.join('/Users/christianvidalwolf/github/CrazeAnalytix', 'Vendor Stock.xlsx')
];
let buffer = null;
let foundPath = '';
for (const p of pathsToTry) {
console.log(`[fetch-vendor-stock] Checking path: ${p}`);
if (fs.existsSync(p)) {
buffer = fs.readFileSync(p);
foundPath = p;
break;
}
}
if (!buffer) {
throw new Error(`Vendor Stock file 'Vendor Stock.xlsx' not found in any of: ${pathsToTry.join(', ')}`);
}
console.log(`[fetch-vendor-stock] Successfully read Vendor Stock Excel from ${foundPath}, size: ${buffer.byteLength}`);
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.status(200).send(buffer);
} catch (error: any) {
console.error('[fetch-vendor-stock] Error:', error);
res.status(500).json({ error: error.message });
}
}
-106
View File
@@ -1,106 +0,0 @@
import type { VercelRequest, VercelResponse } from '@vercel/node';
import { createClient } from '@supabase/supabase-js';
export default async function handler(req: VercelRequest, res: VercelResponse) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === 'OPTIONS') return res.status(200).end();
if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' });
const supabaseUrl = process.env.SUPABASE_URL;
const supabaseServiceKey = process.env.SUPABASE_SERVICE_KEY;
if (!supabaseUrl || !supabaseServiceKey) {
return res.status(500).json({ error: 'Supabase credentials not configured' });
}
const supabase = createClient(supabaseUrl, supabaseServiceKey);
const sql = `
CREATE TABLE IF NOT EXISTS experiments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
description TEXT,
type TEXT NOT NULL CHECK (type IN ('pricing', 'advertising', 'content', 'promotion')),
status TEXT NOT NULL DEFAULT 'planned' CHECK (status IN ('planned', 'active', 'completed', 'paused')),
asins TEXT[] NOT NULL DEFAULT '{}',
marketplace TEXT NOT NULL,
start_date DATE NOT NULL,
end_date DATE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
hypothesis TEXT,
primary_metric TEXT NOT NULL DEFAULT 'units',
target_lift_percent NUMERIC,
baseline_units NUMERIC,
baseline_revenue NUMERIC,
experiment_units NUMERIC,
experiment_revenue NUMERIC,
actual_lift_percent NUMERIC,
statistical_significance NUMERIC,
learnings TEXT,
owner TEXT
);
CREATE INDEX IF NOT EXISTS idx_experiments_status ON experiments(status);
CREATE INDEX IF NOT EXISTS idx_experiments_marketplace ON experiments(marketplace);
CREATE INDEX IF NOT EXISTS idx_experiments_type ON experiments(type);
CREATE INDEX IF NOT EXISTS idx_experiments_dates ON experiments(start_date, end_date);
CREATE INDEX IF NOT EXISTS idx_experiments_asins ON experiments USING GIN(asins);
-- Create updated_at trigger function if not exists
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Create trigger
DROP TRIGGER IF EXISTS update_experiments_updated_at ON experiments;
CREATE TRIGGER update_experiments_updated_at
BEFORE UPDATE ON experiments
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
`;
try {
// Execute SQL via Supabase RPC or direct connection
// Since we can't run raw SQL via JS client, we'll create the table using the query builder
// First check if table exists
const { error: checkError } = await supabase.from('experiments').select('id').limit(1);
if (checkError && checkError.message.includes('relation') && checkError.message.includes('does not exist')) {
// Table doesn't exist - we need to create it via SQL
// Unfortunately the JS client can't run CREATE TABLE directly
// We'll return instructions
return res.status(200).json({
message: 'Table needs to be created via SQL Editor',
instructions: 'Please go to Supabase Dashboard → SQL Editor and run the migration SQL',
sql: sql
});
}
// Table exists, create indexes
await supabase.rpc('create_experiment_indexes');
return res.status(200).json({
success: true,
message: 'Experiments table is ready'
});
} catch (error: any) {
return res.status(500).json({
error: error.message,
instructions: 'Please go to Supabase Dashboard → SQL Editor and run the migration SQL manually'
});
}
}