spb/datacenterindex
Public
HTML 53.9%
TypeScript 44.5%
JavaScript 0.6%
SQL 0.5%
1import { load } from "cheerio";2import type { ExtractedRecord, Parser, RawDocument } from "@dci/connectors";3import { areaSqm, cleanText, description, parseMw, record, renewableFrom, usStateCode } from "./shared.js";45/**6 * Switch campus pages (www.switch.com/core|citadel|keep|pyramid/). The body is rendered client-side (the <article> is7 * empty in the HTML), so the only server-rendered facts are the <title> ("Switch – The Core Campus, Las Vegas, Nevada")8 * and the meta description ("Switch's Tier 5 Platinum rated multi-tenant/colocation data center with up to 2.4 million sqft9 * and 315 MW."). "up to N MW" is the design/full-build figure → plannedPowerMw. No address/coordinates on the page.10 */11export const switchCampus: Parser = {12 name: "switch_campus_v1",13 version: "1.0.0",14 pageTypes: ["facility_page"],15 parse(doc: RawDocument): ExtractedRecord[] {16 const url = doc.finalUrl;17 const m = url.match(/switch\.com\/(core|citadel|keep|pyramid|rock)\/?$/);18 if (!m) return [];19 const slug = m[1]!;20 const $ = load(doc.text);21 const title = cleanText($('meta[property="og:title"]').attr("content") ?? $("title").first().text());22 if (!title) return [];23 const t = title.replace(/^Switch\s*[–—-]\s*/, "");24 const parts = t.split(",").map((s) => s.trim()).filter(Boolean);25 // "The Core Campus, Las Vegas, Nevada" → campus / city / state. When the title is a slogan instead26 // (Pyramid: "GRAND RAPIDS: Largest, Most Advanced Campus …"), fall back to the campus table published on27 // Switch's own market pages (/las-vegas/, /tahoe-reno/, /atlanta/, /grand-rapids/, /austin/).28 const TABLE: Record<string, { campus: string; city: string; state: string }> = { core: { campus: "The Core Campus", city: "Las Vegas", state: "NV" }, citadel: { campus: "The Citadel Campus", city: "Tahoe Reno", state: "NV" }, keep: { campus: "The Keep Campus", city: "Atlanta", state: "GA" }, pyramid: { campus: "The Pyramid Campus", city: "Grand Rapids", state: "MI" }, rock: { campus: "The Rock Campus", city: "Austin", state: "TX" } };29 const parsedState = usStateCode(parts[2] ?? null);30 const fromTitle = parts.length >= 3 && parsedState && /campus/i.test(parts[0] ?? "");31 const tbl = TABLE[slug];32 const campus = fromTitle ? parts[0]! : tbl?.campus ?? `The ${slug[0]!.toUpperCase()}${slug.slice(1)} Campus`;33 const city = fromTitle ? parts[1]! : tbl?.city ?? null;34 const regionName = fromTitle ? parsedState : tbl?.state ?? null;35 const desc = description(doc.text);36 const tier = desc?.match(/Tier\s?(?:5|IV|4|III|3)(?:\s?(?:Platinum|Gold))?/i)?.[0] ?? null;37 const upTo = desc?.match(/up to[\s\S]{0,80}?(\d[\d.,]*\s*(?:MW|megawatts?))\b/i)?.[1] ?? null;38 const anyMw = desc ? parseMw(desc) : null;39 const plannedPowerMw = upTo ? parseMw(upTo) : null;40 const totalPowerMw = !upTo && anyMw ? anyMw : null;41 const buildingSqm = areaSqm(desc);42 const data: Record<string, unknown> = {43 name: /^switch/i.test(campus) ? campus : `Switch ${campus}`, code: slug.toUpperCase(), aliases: [campus, `Switch ${slug.toUpperCase()}`],44 city, regionName, countryIso2: regionName ? "US" : null,45 tier, plannedPowerMw, totalPowerMw, buildingSqm, renewableClaim: renewableFrom(desc),46 facilityType: "colocation", description: desc,47 externalIds: { switch_slug: slug },48 };49 const src = fromTitle ? "meta:og:title+parse" : "fallback:switch-campus-table";50 const methods: Record<string, string> = {51 name: src, code: "url:slug", city: src, regionName: src, countryIso2: `${src}>state`,52 tier: "meta:description+regex:tier", plannedPowerMw: "meta:description+regex:up_to_mw", totalPowerMw: "meta:description>mw", buildingSqm: "meta:description>sqm", renewableClaim: "meta:description+regex:renewable_v1", facilityType: "meta:description", description: "meta:description", externalIds: "url:slug",53 };54 return [record("facility", `switch:${slug}`, url, data, methods, 0.7)];55 },56};57