SPB Git forge
38commits 1branches 0releases
338.7 MBsize
maindefault branch
6 h agolast push
HTML 53.9% TypeScript 44.5% JavaScript 0.6% SQL 0.5%
4.3 KB · 55 lines typescript
Raw Blame History
1/** Pulse, operator comparison, coverage report. */2import type { FastifyInstance } from "fastify";3import { z } from "zod";4import { publicGet } from "../../lib/route.js";5import { TTL, badRequest, csv } from "../../lib/http.js";6import { csvParam } from "../../lib/params.js";7import { pulse, PULSE_METHODOLOGY } from "../../repositories/pulse.js";8import { compareOperators, COMPARE_METHODOLOGY } from "../../repositories/compare.js";9import { coverageReport, sourceCoverage, COVERAGE_METHODOLOGY } from "../../repositories/coverage.js";1011const empty = (v: unknown) => (v === "" || v === null ? undefined : v);1213export async function marketRoutes(app: FastifyInstance): Promise<void> {14  publicGet(app, {15    url: "/pulse", ttl: TTL.dashboard, tags: ["pulse"],16    query: z.object({ window: z.preprocess(empty, z.enum(["24h", "7d", "30d"]).default("24h")) }),17    summary: "Infrastructure pulse: what measurably changed in the last 24h / 7d / 30d (Pulse)",18    description: "Deterministic counts (events, new projects, construction starts, openings, new markets per operator, power / grid events) — no scoring.",19    response: { type: "Pulse", description: "Counts over the window plus the major events and per-country / per-operator breakdowns.", example: { window: "7d", since: "2026-09-05T00:00:00.000Z", newProjects: 12, projectsEnteredConstruction: 3, facilitiesOpened: 2, newlyAnnouncedMw: 850, eventsTotal: 310, operatorsNewMarkets: [{ operator: { id: "op_x", slug: "example", name: "Example" }, market: { id: "met_x", slug: "ashburn", name: "Northern Virginia" }, countryIso2: "US" }] } },20  }, async (q) => {21    const data = await pulse(q.window);22    return { data, meta: { window: q.window, methodology: PULSE_METHODOLOGY } };23  });2425  publicGet(app, {26    url: "/compare/operators", ttl: TTL.detail, tags: ["compare"],27    query: z.object({ slugs: csvParam }),28    summary: "Compare 2–5 operators side by side (OperatorComparison)",29    response: { type: "OperatorComparison", description: "One column per operator: summary, pipeline, velocity windows, new markets (12 m), recent projects, MW coverage.", example: { operators: [{ id: "op_x", slug: "equinix", name: "Equinix", facilityCount: 260, countryCount: 33, knownMw: 1200, mwCoverage: 0.62, pipeline: { operational: { count: 240, mw: 1200 } } }], generatedAt: "2026-09-12T00:00:00.000Z" } },30  }, async (q) => {31    const slugs = [...new Set(csv(q.slugs))];32    if (slugs.length < 2 || slugs.length > 5) throw badRequest("slugs must list 2 to 5 operator slugs (comma-separated)");33    const data = await compareOperators(slugs);34    return { data, meta: { methodology: COMPARE_METHODOLOGY } };35  });3637  publicGet(app, {38    url: "/coverage", ttl: TTL.detail, tags: ["coverage"],39    summary: "Coverage report: share of known fields per country / metro / operator (≥ 5 facilities) / field / source kind (CoverageReport)",40    response: { type: "CoverageReport", description: "Containment-aware shares 0..1; a low share means unknown, not zero.", example: { global: { key: "global", name: "Global", slug: "global", facilities: 8400, capacityCoverage: 0.18, operatorCoverage: 0.9, preciseLocationCoverage: 0.55 }, fields: [{ field: "it_capacity_mw", label: "IT capacity (MW)", coverage: 0.12, count: 1000 }] } },41  }, async () => {42    const data = await coverageReport();43    return { data, meta: { methodology: COVERAGE_METHODOLOGY } };44  });4546  publicGet(app, {47    url: "/coverage/sources", ttl: TTL.detail, tags: ["coverage"],48    summary: "Per-source contribution, freshness, authority tier, failure rate and licence (SourceCoverage[])",49    response: { type: "SourceCoverage[]", description: "One row per source; uniqueRecords = entities only this source documents.", example: [{ id: "src_x", name: "Equinix", kind: "operator", recordsContributed: 262, fieldsContributed: 3100, uniqueRecords: 40, lastSuccessfulCrawl: "2026-09-11T02:00:00.000Z", freshnessDays: 1, authority: "A", failureRate: 0, license: "Terms of use", redistribution: "attribution" }] },50  }, async () => {51    const items = await sourceCoverage();52    return { data: items, meta: { total: items.length, methodology: "recordsContributed / fieldsContributed count current provenance rows; authority is the identity-field tier of the source kind (packages/core claims.ts FIELD_AUTHORITY); failureRate = failed or aborted runs ÷ finished runs over 30 days." } };53  });54}55