diff --git a/packages/scraper/src/robots/flexoptix-api-sync.ts b/packages/scraper/src/robots/flexoptix-api-sync.ts index 8a1c7a7..abb05b9 100644 --- a/packages/scraper/src/robots/flexoptix-api-sync.ts +++ b/packages/scraper/src/robots/flexoptix-api-sync.ts @@ -239,6 +239,20 @@ function inferWavelengthNm(...values: Array): number | null { // ── Normalization ────────────────────────────────────────────────────────── +function parseStandardName(title: string | null): string | null { + if (!title) return null; + // Extract from first segment (before first " | ") + const seg = title.split(" | ")[0] ?? title; + // Try full IEEE form first: 10GBASE-SR, 100GBASE-DR4, etc. + const ieee = seg.match(/((?:\d+(?:\.\d+)?[TGM])?BASE[-/]\w+)/i); + if (ieee) return ieee[1].toUpperCase(); + // Short-form standards — ordered longest-first to avoid partial matches + const m = seg.match( + /(OpenZR\+|ZR\+|ZX\+|DR4\+|LR4\+|SR10|SR8|LR8|ER8|DR8|VR8|SR4|LR4|ER4|FR4|DR4|CLR4|PLR4|PSM4|CWDM4|LRM|BX\w*|DR|LR|ER|SR|ZR|ZX|SX|LX|LH|EX|T)/ + ); + return m ? m[1] : null; +} + function parseCdrType(title: string | null): string | null { if (!title) return null; if (/dual[\s-]cdr/i.test(title)) return "dual_cdr"; @@ -433,7 +447,7 @@ async function importProduct( product.url ?? null, product.title, transceiverId, - product.optics.protocol ?? null, + parseStandardName(product.title) ?? product.optics.protocol ?? null, wdmType, product.optics.cdrType ?? null, product.optics.protocolFamily ?? null,