SPB Git forge

spb/rareindex

Public
54commits 1branches 0releases
7.1 MBsize
maindefault branch
10 days agolast push
TypeScript 61.9% HTML 37.2% SQL 0.7%
1.8 KB · 47 lines typescript
Raw Blame History
1import 'server-only';2import { createHmac } from 'node:crypto';3import type { NormalizedRecord } from '@rareindex/shared';4import { NormalizedRecordSchema } from '@rareindex/shared';56/**7 * URL lookup is delegated to the API service (apps/api `/internal/lookup`): connector modules are8 * loaded dynamically from disk, which the Next.js bundler cannot do. Shared secret = SESSION_SECRET.9 */10export function apiBaseUrl(): string {11  return process.env.RI_API_URL ?? `http://127.0.0.1:${process.env.API_PORT ?? 8211}`;12}1314export function internalToken(): string {15  return createHmac('sha256', process.env.SESSION_SECRET ?? 'dev-only').update('internal').digest('hex');16}1718export interface LookupResult {19  connectorId: string;20  sourceId: string;21  records: NormalizedRecord[];22  durationMs: number;23}2425export async function lookupViaApi(url: string, timeoutMs = 90_000): Promise<LookupResult | null | 'unavailable'> {26  const ctrl = new AbortController();27  const t = setTimeout(() => ctrl.abort(), timeoutMs);28  try {29    const res = await fetch(`${apiBaseUrl()}/internal/lookup`, {30      method: 'POST',31      headers: { 'content-type': 'application/json', 'x-internal-token': internalToken() },32      body: JSON.stringify({ url }),33      signal: ctrl.signal,34      cache: 'no-store',35    });36    if (!res.ok) return 'unavailable';37    const json = (await res.json()) as { data: { connectorId: string; sourceId: string; records: unknown[] } | null; meta: { supported: boolean; durationMs?: number } };38    if (!json.data) return null;39    const records = json.data.records.map((r) => NormalizedRecordSchema.parse(r));40    return { connectorId: json.data.connectorId, sourceId: json.data.sourceId, records, durationMs: json.meta.durationMs ?? 0 };41  } catch {42    return 'unavailable';43  } finally {44    clearTimeout(t);45  }46}47