SPB Git forge

spb/cancerindex

Public
37commits 1branches 0releases
2.9 MBsize
maindefault branch
10 days agolast push
TypeScript 97.2% SQL 1.5% CSS 0.6% JavaScript 0.5%
2.3 KB · 52 lines typescript
Raw Blame History
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