Skip to main content
Glama
import-relationships-csv.ts5.48 kB
#!/usr/bin/env node // HUMMBL CSV Relationship Import Script // Bulk imports relationships from CSV for validation workflow import { createD1Client } from "../storage/d1-client.js"; import { isRelationshipType, isDirection, isConfidence, isReviewStatus, } from "../types/relationships.js"; import type { D1Database } from "@cloudflare/workers-types"; interface Env { DB: D1Database; } interface CSVRelationship { id: string; model_a: string; model_b: string; relationship_type: string; direction: string; confidence: string; logical_derivation: string; has_literature_support?: string; literature_citation?: string; literature_url?: string; empirical_observation?: string; validated_by: string; validated_at: string; review_status?: string; notes?: string; } // Simple CSV parser (for basic CSV format) function parseCSV(csvText: string): CSVRelationship[] { const lines = csvText.trim().split("\n"); const headers = lines[0].split(",").map((h) => h.trim()); const relationships: CSVRelationship[] = []; for (let i = 1; i < lines.length; i++) { const values = lines[i].split(",").map((v) => v.trim()); if (values.length !== headers.length) continue; const relationship: any = {}; headers.forEach((header, index) => { const value = values[index]; relationship[header] = value === "" ? undefined : value; }); relationships.push(relationship as CSVRelationship); } return relationships; } async function importRelationshipsFromCSV(env: Env, csvText: string, dryRun = false) { const db = createD1Client(env.DB); const relationships = parseCSV(csvText); console.log(`📄 Parsed ${relationships.length} relationships from CSV`); if (dryRun) { console.log("🔍 DRY RUN - No data will be inserted"); } let successCount = 0; let errorCount = 0; const errors: string[] = []; for (const relationship of relationships) { try { // Validate required fields if ( !relationship.id || !relationship.model_a || !relationship.model_b || !relationship.relationship_type || !relationship.direction || !relationship.logical_derivation || !relationship.validated_by ) { throw new Error("Missing required fields"); } // Validate enums if (!isRelationshipType(relationship.relationship_type)) { throw new Error(`Invalid relationship type: ${relationship.relationship_type}`); } if (!isDirection(relationship.direction)) { throw new Error(`Invalid direction: ${relationship.direction}`); } if (relationship.confidence && !isConfidence(relationship.confidence)) { throw new Error(`Invalid confidence: ${relationship.confidence}`); } if (relationship.review_status && !isReviewStatus(relationship.review_status)) { throw new Error(`Invalid review status: ${relationship.review_status}`); } if (!dryRun) { // Convert to RelationshipInput format const relationshipInput = { source_code: relationship.model_a.toUpperCase(), target_code: relationship.model_b.toUpperCase(), relationship_type: relationship.relationship_type, confidence: (relationship.confidence || "C") as "A" | "B" | "C", evidence: relationship.logical_derivation, }; await db.createRelationship(relationshipInput); } successCount++; console.log( `✅ ${dryRun ? "Validated" : "Imported"} relationship ${relationship.id}: ${relationship.model_a} ${relationship.relationship_type} ${relationship.model_b}` ); } catch (error) { errorCount++; const errorMsg = `❌ Failed to ${dryRun ? "validate" : "import"} relationship ${relationship.id}: ${error instanceof Error ? error.message : "Unknown error"}`; errors.push(errorMsg); console.error(errorMsg); } } console.log(`\n📊 Import complete:`); console.log(` ✅ ${successCount} relationships ${dryRun ? "validated" : "imported"}`); console.log(` ❌ ${errorCount} errors`); if (errors.length > 0) { console.log("\n🚨 Errors:"); errors.forEach((error) => console.log(` ${error}`)); } return { successCount, errorCount, errors }; } // CSV Template export const CSV_TEMPLATE = `id,model_a,model_b,relationship_type,direction,confidence,logical_derivation,has_literature_support,literature_citation,literature_url,empirical_observation,validated_by,validated_at,review_status,notes R011,DE2,SY2,enables,a→b,B,Systems Thinking requires understanding feedback loops and Second-Order Thinking provides the temporal depth needed to trace system behaviors over time.,1,"Senge, P. (1990). The Fifth Discipline","https://en.wikipedia.org/wiki/The_Fifth_Discipline",Complex system failures often stem from second-order effects that first-order thinking misses.,Reuben Bowlby,2025-11-28T00:00:00.000Z,draft,Initial import from validation exercise`; export default { importRelationshipsFromCSV, CSV_TEMPLATE }; // For local development if (import.meta.main) { console.log("🚀 HUMMBL CSV Relationship Importer"); console.log("Usage: Read CSV from stdin and pipe to this script"); console.log( "Example: cat relationships.csv | npx wrangler d1 execute <database> --file=./src/scripts/import-relationships-csv.ts" ); console.log("\n📄 CSV Format template:"); console.log(CSV_TEMPLATE); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hummbl-dev/mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server