spb/cancerindex
Public
TypeScript 97.2%
SQL 1.5%
CSS 0.6%
JavaScript 0.5%
1import { eq } from 'drizzle-orm';2import { type Database, sources, mintId } from '@cancerindex/database';3import { CONNECTORS } from './registry.js';4import type { ConnectorManifest } from './sdk/manifest.js';56/** Sync connector manifests into the `sources` registry (CLAUDE.md §95, §142, §307). Idempotent. */7export async function syncSources(db: Database, extra: ConnectorManifest[] = []): Promise<{ created: number; updated: number }> {8 let created = 0;9 let updated = 0;10 const manifests = [...CONNECTORS.map((c) => c.manifest), ...extra];11 for (const m of manifests) {12 const values = {13 slug: m.id,14 name: m.name,15 organization: m.organization,16 category: m.category,17 description: m.description,18 homepage: m.homepage,19 docsUrl: m.docsUrl ?? null,20 termsUrl: m.termsUrl ?? null,21 accessType: m.access.type,22 accessAuth: m.access.auth,23 license: m.license,24 licenseStatus: m.licenseStatus,25 commercialUse: m.commercialUse,26 redistribution: m.redistribution,27 attribution: m.attribution ?? null,28 licenseReviewedAt: m.termsReviewedAt ? new Date(m.termsReviewedAt) : null,29 approvedForProduction: m.licenseStatus === 'approved',30 updateFrequency: m.updateFrequency,31 supportsIncremental: m.supportsIncrementalSync,32 entities: m.entities,33 metrics: m.metrics,34 rateLimit: m.rateLimits.requestsPerSecond ? `${m.rateLimits.requestsPerSecond} req/s` : m.rateLimits.requestsPerMinute ? `${m.rateLimits.requestsPerMinute} req/min` : null,35 tier: m.tier,36 manifest: m as unknown as Record<string, unknown>,37 updatedAt: new Date(),38 };39 const [existing] = await db.select({ id: sources.id, status: sources.status }).from(sources).where(eq(sources.slug, m.id)).limit(1);40 if (existing) {41 // Keep runtime status (active/degraded) unless manifest declares a gating status.42 const gating = ['awaiting_credentials', 'review', 'retired', 'paused'].includes(m.status);43 await db.update(sources).set({ ...values, ...(gating ? { status: m.status } : {}) }).where(eq(sources.id, existing.id));44 updated++;45 } else {46 await db.insert(sources).values({ id: await mintId(db, 'SOURCE'), ...values, status: m.status });47 created++;48 }49 }50 return { created, updated };51}52