mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 12:25:22 +02:00
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:
co-authored by
Qwen-Coder
parent
edbde19f3a
commit
aebebecf1b
@@ -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 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user