/** * WS2: Automated Datasheet Generation * * Generates professional PDF datasheets for transceivers and switches. * Uses HTML templates rendered via the dashboard's static serving. * Returns structured HTML that can be printed to PDF client-side or via Puppeteer. */ import { Router } from "express"; import { pool } from "../db/client"; export const datasheetRouter = Router(); /** * GET /api/datasheets/transceiver/:id * Returns structured datasheet data for a transceiver (JSON or HTML) */ datasheetRouter.get("/transceiver/:id", async (req, res) => { try { const { format = "json" } = req.query; const id = req.params.id; // Get transceiver with full details const t = await pool.query( `SELECT t.*, v.name AS vendor_name, v.website AS vendor_website, v.logo_r2_key, s.name AS standard_full_name, s.ieee_reference, s.year_ratified FROM transceivers t LEFT JOIN vendors v ON t.vendor_id = v.id LEFT JOIN standards s ON t.standard_id = s.id WHERE t.slug = $1 OR t.id::text = $1`, [id] ); if (!t.rows[0]) return res.status(404).json({ error: "Transceiver not found" }); const product = t.rows[0]; // Get compatible switches (top 30) const compat = await pool.query( `SELECT sw.model, sw.series, sv.name AS vendor, c.firmware_min, c.verified_by FROM compatibility c JOIN switches sw ON c.switch_id = sw.id JOIN vendors sv ON sw.vendor_id = sv.id WHERE c.transceiver_id = $1 AND c.status = 'compatible' ORDER BY sv.name, sw.model LIMIT 30`, [product.id] ); // Get latest prices from multiple vendors const prices = await pool.query( `SELECT DISTINCT ON (sv.name) sv.name AS vendor, po.price, po.currency, po.stock_level, po.url, po.time FROM price_observations po JOIN vendors sv ON po.source_vendor_id = sv.id WHERE po.transceiver_id = $1 ORDER BY sv.name, po.time DESC`, [product.id] ); // Power budget calculation const txPowerMin = product.tx_power_min_dbm ? parseFloat(product.tx_power_min_dbm) : null; const txPowerMax = product.tx_power_max_dbm ? parseFloat(product.tx_power_max_dbm) : null; const rxSensitivity = product.rx_sensitivity_dbm ? parseFloat(product.rx_sensitivity_dbm) : null; const opticalBudget = product.optical_budget_db ? parseFloat(product.optical_budget_db) : null; let powerBudget = null; if (txPowerMin !== null && rxSensitivity !== null) { const budget = txPowerMin - rxSensitivity; const connectorLoss = 0.5; // 2 connectors × 0.25 dB const spliceLoss = 0.1; const fiberLoss = product.fiber_type === 'SMF' ? (product.reach_meters / 1000) * 0.35 // 0.35 dB/km at 1310nm : (product.reach_meters / 1000) * 3.5; // 3.5 dB/km at 850nm MMF const margin = budget - fiberLoss - connectorLoss - spliceLoss; powerBudget = { tx_power_min_dbm: txPowerMin, tx_power_max_dbm: txPowerMax, rx_sensitivity_dbm: rxSensitivity, link_budget_db: Math.round(budget * 10) / 10, fiber_loss_db: Math.round(fiberLoss * 10) / 10, connector_loss_db: connectorLoss, splice_loss_db: spliceLoss, margin_db: Math.round(margin * 10) / 10, sufficient: margin >= 3, }; } const datasheet = { product: { slug: product.slug, part_number: product.part_number, vendor: product.vendor_name, standard: product.standard_full_name || product.standard_name, ieee_reference: product.ieee_reference, form_factor: product.form_factor, speed: product.speed, speed_gbps: parseFloat(product.speed_gbps), lanes: product.lanes, lane_rate: product.lane_rate, modulation: product.modulation, reach_label: product.reach_label, reach_meters: product.reach_meters, fiber_type: product.fiber_type, wavelengths: product.wavelengths, connector: product.connector, power_consumption_w: product.power_consumption_w ? parseFloat(product.power_consumption_w) : null, temp_range: product.temp_range, dom_support: product.dom_support, category: product.category, market_status: product.market_status, image_url: product.image_url, }, optical: powerBudget, wdm: product.wdm_type ? { type: product.wdm_type, channels: product.channel_count, spacing_ghz: product.channel_spacing_ghz ? parseFloat(product.channel_spacing_ghz) : null, tunable: product.tunable, itu_grid: product.itu_grid, } : null, coherent: product.coherent ? { baud_rate_gbaud: product.baud_rate_gbaud ? parseFloat(product.baud_rate_gbaud) : null, fec_type: product.fec_type, dsp_vendor: product.dsp_vendor, } : null, compatible_switches: compat.rows, pricing: prices.rows.map(p => ({ vendor: p.vendor, price: parseFloat(p.price), currency: p.currency, stock: p.stock_level, url: p.url, as_of: p.time, })), flexoptix: { buy_url: `https://www.flexoptix.net/en/catalogsearch/result/?q=${encodeURIComponent(product.form_factor + ' ' + product.speed_gbps + 'G ' + product.reach_label)}`, flexbox_note: "Flexoptix transceivers support FlexBox coding — one module works in any vendor's switch.", }, generated_at: new Date().toISOString(), }; if (format === "html") { res.setHeader("Content-Type", "text/html"); res.send(renderDatasheetHtml(datasheet)); } else { res.json(datasheet); } } catch (err) { console.error("Datasheet error:", err); res.status(500).json({ error: "Internal server error" }); } }); /** * GET /api/datasheets/switch/:id */ datasheetRouter.get("/switch/:id", async (req, res) => { try { const id = req.params.id; const sw = await pool.query( `SELECT sw.*, v.name AS vendor_name, v.website AS vendor_website FROM switches sw JOIN vendors v ON sw.vendor_id = v.id WHERE sw.model = $1 OR sw.id::text = $1`, [id] ); if (!sw.rows[0]) return res.status(404).json({ error: "Switch not found" }); const device = sw.rows[0]; const compat = await pool.query( `SELECT t.form_factor, t.speed, t.speed_gbps, t.reach_label, t.fiber_type, tv.name AS transceiver_vendor, c.firmware_min FROM compatibility c JOIN transceivers t ON c.transceiver_id = t.id JOIN vendors tv ON t.vendor_id = tv.id WHERE c.switch_id = $1 AND c.status = 'compatible' ORDER BY t.speed_gbps DESC, tv.name LIMIT 50`, [device.id] ); const docs = await pool.query( `SELECT doc_type, title, source_url FROM product_documents WHERE switch_id = $1 ORDER BY doc_type`, [device.id] ); res.json({ switch: { model: device.model, series: device.series, vendor: device.vendor_name, category: device.category, ports_config: device.ports_config, total_ports: device.total_ports, max_speed_gbps: device.max_speed_gbps, switching_capacity_tbps: device.switching_capacity_tbps, asic: device.asic_vendor ? `${device.asic_vendor} ${device.asic_model || ''}`.trim() : null, sonic_compatible: device.sonic_compatible, image_url: device.image_url, }, compatible_transceivers: compat.rows, documents: docs.rows, generated_at: new Date().toISOString(), }); } catch (err) { console.error("Switch datasheet error:", err); res.status(500).json({ error: "Internal server error" }); } }); /** * GET /api/datasheets/list — recently generated datasheets */ datasheetRouter.get("/list", async (_req, res) => { try { const result = await pool.query( `SELECT * FROM generated_datasheets ORDER BY generated_at DESC LIMIT 50` ); res.json({ datasheets: result.rows }); } catch (err) { res.status(500).json({ error: "Internal server error" }); } }); function renderDatasheetHtml(ds: any): string { const p = ds.product; const prices = ds.pricing.map((pr: any) => `${pr.vendor}${pr.currency} ${pr.price.toFixed(2)}${pr.stock || 'N/A'}`).join(''); const switches = ds.compatible_switches.map((s: any) => `${s.vendor}${s.model}${s.firmware_min || 'Any'}`).join(''); return ` ${p.form_factor} ${p.speed} ${p.reach_label} — Datasheet | TIP

${p.form_factor} ${p.speed} ${p.reach_label}

${p.standard || ''} ${p.ieee_reference ? '(' + p.ieee_reference + ')' : ''}

${p.market_status || 'Active'}
${p.image_url ? `
${p.form_factor}
` : ''}

Specifications

Form Factor${p.form_factor}
Speed${p.speed} (${p.speed_gbps} Gbps)
Reach${p.reach_label} (${p.reach_meters >= 1000 ? (p.reach_meters/1000) + ' km' : p.reach_meters + ' m'})
Fiber${p.fiber_type || 'N/A'}
Connector${p.connector || 'N/A'}
Wavelength${p.wavelengths || 'N/A'}
${p.lanes ? `
Lanes${p.lanes}× ${p.lane_rate || ''}
` : ''} ${p.modulation ? `
Modulation${p.modulation}
` : ''}
Power${p.power_consumption_w ? p.power_consumption_w + ' W' : 'N/A'}
Temperature${p.temp_range === 'COM' ? '0°C to 70°C (Commercial)' : '-40°C to 85°C (Industrial)'}
${ds.optical ? `

Power Budget

TX Power: ${ds.optical.tx_power_min_dbm} to ${ds.optical.tx_power_max_dbm} dBm | RX Sensitivity: ${ds.optical.rx_sensitivity_dbm} dBm | Link Budget: ${ds.optical.link_budget_db} dB | Fiber Loss: ${ds.optical.fiber_loss_db} dB | Margin: ${ds.optical.margin_db} dB ${ds.optical.sufficient ? '✓' : '⚠ INSUFFICIENT'}
` : ''} ${prices ? `

Current Pricing

${prices}
VendorPriceStock
` : ''} ${switches ? `

Compatible Switches (${ds.compatible_switches.length})

${switches}
VendorModelMin Firmware
` : ''}
Buy at Flexoptix →

${ds.flexoptix.flexbox_note}

`; }