Files
CrazeAnalytix/api/migrate-experiments.ts
T

107 lines
3.9 KiB
TypeScript

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'
});
}
}