import { supabase } from '../db/client.js';
import type {
ListStylesResponse,
StyleDetailsResponse,
DesignStyle
} from '../types.js';
/**
* List all available design styles
*/
export async function listStyles(): Promise<ListStylesResponse> {
try {
const client = supabase.getAnonClient();
const { data, error, count } = await client
.from('design_styles')
.select(`
id,
name,
category,
category_label,
industry,
businesses
`, { count: 'exact' })
.order('name');
if (error) {
supabase.log(`Error fetching styles: ${error.message}`, 'error');
throw new Error(`Failed to fetch styles: ${error.message}`);
}
if (!data) {
return { styles: [], total: 0 };
}
const styles = data.map(style => ({
id: style.id,
name: style.name,
category: style.category,
categoryLabel: style.category_label,
industry: style.industry,
businesses: style.businesses || []
}));
supabase.log(`Retrieved ${styles.length} styles`);
return {
styles,
total: count || styles.length
};
} catch (error) {
supabase.log(`Error in listStyles: ${error}`, 'error');
throw error;
}
}
/**
* Get detailed information about a specific style
*/
export async function getStyleDetails(styleId: string): Promise<StyleDetailsResponse> {
try {
if (!styleId) {
throw new Error('Style ID is required');
}
const client = supabase.getAnonClient();
const { data, error } = await client
.from('design_styles')
.select('*')
.eq('id', styleId)
.single();
if (error) {
if (error.code === 'PGRST116') {
throw new Error(`Style with ID '${styleId}' not found`);
}
supabase.log(`Error fetching style details: ${error.message}`, 'error');
throw new Error(`Failed to fetch style details: ${error.message}`);
}
if (!data) {
throw new Error(`Style with ID '${styleId}' not found`);
}
const style = data as DesignStyle;
supabase.log(`Retrieved details for style: ${style.name}`);
return {
id: style.id,
name: style.name,
industry: style.industry,
category: style.category,
categoryLabel: style.category_label,
businesses: style.businesses || [],
styleDNA: style.style_dna as any, // The JSONB will preserve the structure
dos: style.dos || [],
donts: style.donts || [],
tokens: style.tokens,
rawLength: style.raw_length
};
} catch (error) {
supabase.log(`Error in getStyleDetails: ${error}`, 'error');
throw error;
}
}
/**
* Search styles by category, industry, or business type
*/
export async function searchStyles(params: {
category?: string;
industry?: string;
businessType?: string;
limit?: number;
}): Promise<ListStylesResponse> {
try {
const client = supabase.getAnonClient();
const { category, industry, businessType, limit = 50 } = params;
let query = client
.from('design_styles')
.select(`
id,
name,
category,
category_label,
industry,
businesses
`, { count: 'exact' });
// Apply filters
if (category) {
query = query.eq('category', category);
}
if (industry) {
query = query.eq('industry', industry);
}
if (businessType) {
query = query.contains('businesses', [businessType]);
}
const { data, error, count } = await query
.order('name')
.limit(limit);
if (error) {
supabase.log(`Error searching styles: ${error.message}`, 'error');
throw new Error(`Failed to search styles: ${error.message}`);
}
if (!data) {
return { styles: [], total: 0 };
}
const styles = data.map(style => ({
id: style.id,
name: style.name,
category: style.category,
categoryLabel: style.category_label,
industry: style.industry,
businesses: style.businesses || []
}));
supabase.log(`Found ${styles.length} styles matching criteria`);
return {
styles,
total: count || styles.length
};
} catch (error) {
supabase.log(`Error in searchStyles: ${error}`, 'error');
throw error;
}
}