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%
2.7 KB · 63 lines typescript
Raw Blame History
1import { readFileSync } from 'node:fs';2import path from 'node:path';3import { fileURLToPath } from 'node:url';4import { RegistrySchema, type ConnectorMeta, type Registry, type RareIndexConnector } from './types.js';56const here = path.dirname(fileURLToPath(import.meta.url));7export const CONNECTORS_DIR = path.resolve(here, '../../../connectors');8export const REGISTRY_PATH = path.join(CONNECTORS_DIR, 'registry.json');910let cached: Registry | null = null;1112/** Load and validate connectors/registry.json (§106). */13export function loadRegistry(force = false): Registry {14  if (cached && !force) return cached;15  const raw = JSON.parse(readFileSync(REGISTRY_PATH, 'utf8'));16  cached = RegistrySchema.parse(raw);17  const ids = new Set<string>();18  for (const c of cached.connectors) {19    if (ids.has(c.id)) throw new Error(`registry: duplicate connector id ${c.id}`);20    ids.add(c.id);21  }22  return cached;23}2425export function getConnectorMeta(id: string): ConnectorMeta {26  const meta = loadRegistry().connectors.find((c) => c.id === id);27  if (!meta) throw new Error(`Unknown connector: ${id}`);28  return meta;29}3031export function listConnectorMeta(filter: { enabled?: boolean; category?: string; sourceType?: string } = {}): ConnectorMeta[] {32  return loadRegistry().connectors.filter((c) => {33    if (filter.enabled !== undefined && c.enabled !== filter.enabled) return false;34    if (filter.category && !c.categories.includes(filter.category)) return false;35    if (filter.sourceType && c.sourceType !== filter.sourceType) return false;36    return true;37  });38}3940/**41 * Dynamically import a connector module. Each module default-exports a factory42 * `(meta: ConnectorMeta) => RareIndexConnector`.43 */44export async function loadConnector(id: string): Promise<RareIndexConnector> {45  const meta = getConnectorMeta(id);46  const modPath = path.join(CONNECTORS_DIR, meta.module, 'index.ts');47  const mod = (await import(modPath)) as { default?: (meta: ConnectorMeta) => RareIndexConnector | Promise<RareIndexConnector>; createConnector?: (meta: ConnectorMeta) => RareIndexConnector | Promise<RareIndexConnector> };48  const factory = mod.default ?? mod.createConnector;49  if (!factory) throw new Error(`connector module ${meta.module} must default-export a factory`);50  return factory(meta);51}5253/** Find connectors whose urlPatterns match a URL (scanner paste-URL, §114). */54export async function connectorsForUrl(url: string): Promise<RareIndexConnector[]> {55  const out: RareIndexConnector[] = [];56  for (const meta of listConnectorMeta({ enabled: true })) {57    if (!meta.supportsLookup) continue;58    const c = await loadConnector(meta.id);59    if (c.urlPatterns?.some((re) => re.test(url))) out.push(c);60  }61  return out;62}63