Skip to main content
Glama
import-relationships-csv.ts6.02 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) { const result = await db.createRelationship({ id: relationship.id, model_a: relationship.model_a.toUpperCase(), model_b: relationship.model_b.toUpperCase(), relationship_type: relationship.relationship_type, direction: relationship.direction, confidence: relationship.confidence || 'U', logical_derivation: relationship.logical_derivation, has_literature_support: relationship.has_literature_support === '1' || relationship.has_literature_support?.toLowerCase() === 'true' ? 1 : 0, literature_citation: relationship.literature_citation, literature_url: relationship.literature_url, empirical_observation: relationship.empirical_observation, validated_by: relationship.validated_by, validated_at: relationship.validated_at, review_status: relationship.review_status || 'draft', notes: relationship.notes, }); if (!result.ok) { throw new Error(result.error); } } 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