Files
CrazeAnalytix/services/supabase.ts
T

127 lines
3.2 KiB
TypeScript

import { createClient, SupabaseClient } from '@supabase/supabase-js';
const supabaseUrl = process.env.SUPABASE_URL || '';
const supabaseAnonKey = process.env.SUPABASE_ANON_KEY || '';
let _client: SupabaseClient | null = null;
const getClient = (): SupabaseClient => {
if (!_client) {
if (!supabaseUrl || !supabaseAnonKey) {
throw new Error('Supabase credentials not configured. Add SUPABASE_URL and SUPABASE_ANON_KEY to environment variables.');
}
_client = createClient(supabaseUrl, supabaseAnonKey);
}
return _client;
};
export interface VendorDailyRow {
id?: number;
date: string;
market: string;
asin: string;
product_title: string | null;
tags: string | null;
bsr_top_rank: number | null;
bsr_top_category: string | null;
bsr_detail_rank: number | null;
bsr_detail_category: string | null;
avg_rating: number | null;
num_reviews: number | null;
buybox_owner: string | null;
buybox_price: number | null;
amazon_has_buybox: boolean | null;
glance_views: number | null;
}
export interface VendorFilters {
markets?: string[];
tags?: string[];
asins?: string[];
dateFrom?: string;
dateTo?: string;
}
export const fetchVendorData = async (filters: VendorFilters): Promise<VendorDailyRow[]> => {
const allRows: VendorDailyRow[] = [];
let offset = 0;
const pageSize = 1000;
let hasMore = true;
while (hasMore) {
let query = getClient()
.from('vendor_daily_data')
.select('*')
.order('date', { ascending: true })
.range(offset, offset + pageSize - 1);
if (filters.markets?.length) {
query = query.in('market', filters.markets);
}
if (filters.tags?.length) {
query = query.in('tags', filters.tags);
}
if (filters.asins?.length) {
query = query.in('asin', filters.asins);
}
if (filters.dateFrom) {
query = query.gte('date', filters.dateFrom);
}
if (filters.dateTo) {
query = query.lte('date', filters.dateTo);
}
const { data, error } = await query;
if (error) throw error;
if (data) {
allRows.push(...data);
hasMore = data.length === pageSize;
offset += pageSize;
} else {
hasMore = false;
}
}
return allRows;
};
export const fetchVendorFilterOptions = async (): Promise<{
markets: string[];
tags: string[];
dateRange: { min: string; max: string } | null;
}> => {
const client = getClient();
const { data: marketData } = await client
.from('vendor_daily_data')
.select('market');
const { data: tagData } = await client
.from('vendor_daily_data')
.select('tags');
const { data: dateMin } = await client
.from('vendor_daily_data')
.select('date')
.order('date', { ascending: true })
.limit(1);
const { data: dateMax } = await client
.from('vendor_daily_data')
.select('date')
.order('date', { ascending: false })
.limit(1);
const markets = [...new Set((marketData || []).map(r => r.market))].sort();
const tags = [...new Set((tagData || []).map(r => r.tags).filter(Boolean))].sort();
return {
markets,
tags,
dateRange: dateMin?.[0] && dateMax?.[0]
? { min: dateMin[0].date, max: dateMax[0].date }
: null,
};
};