import axios from 'axios'; import * as cheerio from 'cheerio'; import type { Filament } from '../../types/filament'; // Mock data for development - replace with actual Confluence API integration const mockFilaments: Filament[] = [ { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Mistletoe Green", refill: "", vakum: "vakuum x1", otvoreno: "otvorena x1", kolicina: "2", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Indigo Purple", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Black", refill: "", vakum: "", otvoreno: "2x otvorena", kolicina: "2", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Black", refill: "Da", vakum: "vakuum", otvoreno: "", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Jade White", refill: "", vakum: "vakuum", otvoreno: "", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Gray", refill: "", vakum: "vakuum", otvoreno: "", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Red", refill: "", vakum: "vakuum", otvoreno: "", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Hot Pink", refill: "", vakum: "vakuum", otvoreno: "", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Cocoa Brown", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "White", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Cotton Candy Cloud", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Sunflower Yellow", refill: "", vakum: "vakuum", otvoreno: "", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Yellow", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Magenta", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Beige", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Basic", boja: "Cyan", refill: "", vakum: "vakuum", otvoreno: "", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Matte", boja: "Scarlet Red", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Matte", boja: "Mandarin Orange", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Matte", boja: "Marine Blue", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Matte", boja: "Charcoal", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" }, { brand: "BambuLab", tip: "PLA", finish: "Matte", boja: "Ivory White", refill: "", vakum: "", otvoreno: "otvorena", kolicina: "", cena: "" } ]; interface ConfluencePageContent { body: { storage?: { value: string; }; view?: { value: string; }; }; } async function fetchFromConfluence(): Promise { const confluenceUrl = process.env.CONFLUENCE_API_URL || process.env.VITE_CONFLUENCE_API_URL; const confluenceToken = process.env.CONFLUENCE_TOKEN || process.env.VITE_CONFLUENCE_TOKEN; const pageId = process.env.CONFLUENCE_PAGE_ID || process.env.VITE_CONFLUENCE_PAGE_ID; if (!confluenceUrl || !confluenceToken || !pageId) { console.warn('Confluence configuration missing, using mock data'); return mockFilaments; } try { const response = await axios.get( `${confluenceUrl}/rest/api/content/${pageId}?expand=body.storage`, { headers: { 'Authorization': `Bearer ${confluenceToken}`, 'Accept': 'application/json' } } ); const htmlContent = response.data.body.storage?.value || ''; return parseConfluenceTable(htmlContent); } catch (error) { console.error('Failed to fetch from Confluence:', error); return mockFilaments; } } function parseConfluenceTable(html: string): Filament[] { const $ = cheerio.load(html); const filaments: Filament[] = []; // Find all tables and process each one $('table').each((_tableIndex, table) => { let headers: string[] = []; // Get headers $(table).find('tr').first().find('th, td').each((_i, cell) => { headers.push($(cell).text().trim()); }); // Skip if not our filament table (check for expected headers) if (!headers.includes('Boja') || !headers.includes('Brand')) { return; } // Process rows $(table).find('tr').slice(1).each((_rowIndex, row) => { const cells = $(row).find('td'); if (cells.length >= headers.length) { const filament: any = {}; cells.each((cellIndex, cell) => { const headerName = headers[cellIndex]; const cellText = $(cell).text().trim(); // Map headers to our expected structure switch(headerName.toLowerCase()) { case 'brand': filament.brand = cellText; break; case 'tip': filament.tip = cellText; break; case 'finish': filament.finish = cellText; break; case 'boja': filament.boja = cellText; break; case 'refill': filament.refill = cellText; break; case 'vakum': filament.vakum = cellText; break; case 'otvoreno': filament.otvoreno = cellText; break; case 'količina': filament.kolicina = cellText; break; case 'cena': filament.cena = cellText; break; } }); // Only add if we have the required fields if (filament.brand && filament.boja) { filaments.push(filament as Filament); } } }); }); return filaments.length > 0 ? filaments : mockFilaments; } export async function handler(event: any) { // For AWS Amplify if (event.httpMethod !== 'GET') { return { statusCode: 405, body: JSON.stringify({ error: 'Method not allowed' }) }; } try { const filaments = await fetchFromConfluence(); return { statusCode: 200, headers: { 'Content-Type': 'application/json', 'Cache-Control': 'max-age=300' // 5 minutes cache }, body: JSON.stringify(filaments) }; } catch (error) { return { statusCode: 500, body: JSON.stringify({ error: 'Failed to fetch filaments', message: error instanceof Error ? error.message : 'Unknown error' }) }; } } // For local development with Vite export default async function(req: Request): Promise { if (req.method !== 'GET') { return new Response('Method not allowed', { status: 405 }); } try { const filaments = await fetchFromConfluence(); return new Response(JSON.stringify(filaments), { headers: { 'Content-Type': 'application/json', 'Cache-Control': 'max-age=300' } }); } catch (error) { return new Response(JSON.stringify({ error: 'Failed to fetch filaments', message: error instanceof Error ? error.message : 'Unknown error' }), { status: 500, headers: { 'Content-Type': 'application/json' } }); } }