#!/usr/bin/env node /** * Comprehensive Database Connection Test * Tests all connections between admin pages, collections, and engines */ const DIRECTUS_URL = 'https://spark.jumpstartscaling.com'; const ADMIN_TOKEN = 'SufWLAbsqmbbqF_gg5I70ng8wE1zXt-a'; async function makeRequest(endpoint, method = 'GET', body = null) { const options = { method, headers: { 'Authorization': `Bearer ${ADMIN_TOKEN}`, 'Content-Type': 'application/json' } }; if (body) { options.body = JSON.stringify(body); } const response = await fetch(`${DIRECTUS_URL}${endpoint}`, options); if (!response.ok) { const errorText = await response.text(); throw new Error(`API Error: ${response.status} - ${errorText}`); } return response.json(); } async function testConnection() { console.log('\nšŸ”Œ COMPREHENSIVE DATABASE CONNECTION TEST\n'); console.log('═'.repeat(80)); const results = { collections: {}, relationships: {}, adminPages: {}, engines: {} }; // Test 1: Core Collections Access console.log('\n1ļøāƒ£ CORE COLLECTIONS ACCESS\n'); const coreCollections = [ 'sites', 'posts', 'pages', 'generated_articles', 'generation_jobs', 'avatar_intelligence', 'avatar_variants', 'geo_intelligence', 'cartesian_patterns', 'spintax_dictionaries', 'campaign_masters', 'content_fragments', 'headline_inventory' ]; for (const collection of coreCollections) { try { const data = await makeRequest(`/items/${collection}?limit=1&meta=filter_count`); const count = data.meta?.filter_count || 0; results.collections[collection] = { accessible: true, count }; console.log(` āœ… ${collection.padEnd(30)} ${count.toString().padStart(5)} records`); } catch (err) { results.collections[collection] = { accessible: false, error: err.message }; console.log(` āŒ ${collection.padEnd(30)} ERROR`); } } // Test 2: Relationship Integrity console.log('\n\n2ļøāƒ£ RELATIONSHIP INTEGRITY TESTS\n'); // Test Sites → Posts/Pages try { const sites = await makeRequest('/items/sites?limit=1'); if (sites.data?.length > 0) { const siteId = sites.data[0].id; const siteName = sites.data[0].name; const posts = await makeRequest(`/items/posts?filter[site_id][_eq]=${siteId}&limit=1`); const pages = await makeRequest(`/items/pages?filter[site_id][_eq]=${siteId}&limit=1`); console.log(` āœ… Sites → Posts (tested with site: ${siteName})`); console.log(` āœ… Sites → Pages (tested with site: ${siteName})`); results.relationships['sites_posts'] = true; results.relationships['sites_pages'] = true; } } catch (err) { console.log(` āŒ Sites relationships: ${err.message}`); results.relationships['sites_posts'] = false; results.relationships['sites_pages'] = false; } // Test Campaign → Content Fragments/Headlines/Articles try { const campaigns = await makeRequest('/items/campaign_masters?limit=1'); if (campaigns.data?.length > 0) { const campaignId = campaigns.data[0].id; const campaignName = campaigns.data[0].name; const fragments = await makeRequest(`/items/content_fragments?filter[campaign_id][_eq]=${campaignId}&limit=1`); const headlines = await makeRequest(`/items/headline_inventory?filter[campaign_id][_eq]=${campaignId}&limit=1`); const articles = await makeRequest(`/items/generated_articles?filter[campaign_id][_eq]=${campaignId}&limit=1`); console.log(` āœ… Campaign → Content Fragments (tested with: ${campaignName})`); console.log(` āœ… Campaign → Headlines (tested with: ${campaignName})`); console.log(` āœ… Campaign → Generated Articles (tested with: ${campaignName})`); results.relationships['campaign_fragments'] = true; results.relationships['campaign_headlines'] = true; results.relationships['campaign_articles'] = true; } } catch (err) { console.log(` āŒ Campaign relationships: ${err.message}`); results.relationships['campaign_fragments'] = false; } // Test 3: Admin Page Data Access console.log('\n\n3ļøāƒ£ ADMIN PAGE DATA ACCESS\n'); // Mission Control (Command Center) - needs sites, generation_jobs console.log('\n šŸ“Š Mission Control / Command Center:'); try { const sites = await makeRequest('/items/sites?fields=id,name,status,url'); const jobs = await makeRequest('/items/generation_jobs?limit=10&sort=-date_created'); console.log(` āœ… Can access sites: ${sites.data?.length || 0} sites`); console.log(` āœ… Can access generation jobs: ${jobs.data?.length || 0} recent jobs`); results.adminPages['mission_control'] = true; } catch (err) { console.log(` āŒ Error: ${err.message}`); results.adminPages['mission_control'] = false; } // Content Factory - needs campaigns, patterns, spintax console.log('\n šŸ­ Content Factory:'); try { const campaigns = await makeRequest('/items/campaign_masters?fields=id,name,status'); const patterns = await makeRequest('/items/cartesian_patterns?fields=id,pattern_key'); const spintax = await makeRequest('/items/spintax_dictionaries?fields=id,category'); console.log(` āœ… Can access campaigns: ${campaigns.data?.length || 0} campaigns`); console.log(` āœ… Can access patterns: ${patterns.data?.length || 0} patterns`); console.log(` āœ… Can access spintax: ${spintax.data?.length || 0} dictionaries`); results.adminPages['content_factory'] = true; } catch (err) { console.log(` āŒ Error: ${err.message}`); results.adminPages['content_factory'] = false; } // Work Log - check if collection exists console.log('\n šŸ“ Work Log:'); try { const workLog = await makeRequest('/items/work_log?limit=10&sort=-date_created'); console.log(` āœ… Can access work log: ${workLog.data?.length || 0} entries`); results.adminPages['work_log'] = true; } catch (err) { if (err.message.includes('404') || err.message.includes('not found')) { console.log(` āš ļø Work log collection doesn't exist - needs to be created`); results.adminPages['work_log'] = 'missing'; } else { console.log(` āŒ Error: ${err.message}`); results.adminPages['work_log'] = false; } } // Test 4: Engine Data Access console.log('\n\n4ļøāƒ£ ENGINE DATA ACCESS TESTS\n'); // Cartesian Engine - needs avatars, geo, patterns, spintax console.log('\n šŸ¤– CartesianEngine Requirements:'); try { const avatars = await makeRequest('/items/avatar_intelligence?fields=id,avatar_key'); const avatarVariants = await makeRequest('/items/avatar_variants?fields=id,avatar_key,variant_type'); const geoData = await makeRequest('/items/geo_intelligence?fields=id,cluster_key'); const patterns = await makeRequest('/items/cartesian_patterns?fields=id,pattern_key,data'); const spintax = await makeRequest('/items/spintax_dictionaries?fields=id,category,data'); console.log(` āœ… Avatar Intelligence: ${avatars.data?.length || 0} avatars`); console.log(` āœ… Avatar Variants: ${avatarVariants.data?.length || 0} variants`); console.log(` āœ… Geo Intelligence: ${geoData.data?.length || 0} locations`); console.log(` āœ… Cartesian Patterns: ${patterns.data?.length || 0} patterns`); console.log(` āœ… Spintax Dictionaries: ${spintax.data?.length || 0} dictionaries`); results.engines['cartesian_data_access'] = true; } catch (err) { console.log(` āŒ Error accessing engine data: ${err.message}`); results.engines['cartesian_data_access'] = false; } // Generation Jobs → Engine Flow console.log('\n āš™ļø Generation Job → Engine Flow:'); try { const jobs = await makeRequest('/items/generation_jobs?filter[status][_eq]=pending&limit=1'); if (jobs.data?.length > 0) { const job = jobs.data[0]; const site = await makeRequest(`/items/sites/${job.site_id}`); console.log(` āœ… Job can access site data: ${site.data?.name}`); console.log(` āœ… Job status: ${job.status}`); console.log(` āœ… Target quantity: ${job.target_quantity}`); results.engines['job_site_access'] = true; } else { console.log(` āš ļø No pending jobs to test`); results.engines['job_site_access'] = 'no_pending_jobs'; } } catch (err) { console.log(` āŒ Error: ${err.message}`); results.engines['job_site_access'] = false; } // Test 5: Cross-Collection Queries console.log('\n\n5ļøāƒ£ CROSS-COLLECTION QUERY TESTS\n'); // Test joining site with articles try { const articlesWithSite = await makeRequest( '/items/generated_articles?fields=id,title,site_id.*&limit=1' ); if (articlesWithSite.data?.length > 0 && articlesWithSite.data[0].site_id) { console.log(` āœ… Can join generated_articles with sites data`); results.relationships['articles_site_join'] = true; } else { console.log(` āš ļø No generated articles to test join`); results.relationships['articles_site_join'] = 'no_data'; } } catch (err) { console.log(` āŒ Articles → Sites join failed: ${err.message}`); results.relationships['articles_site_join'] = false; } // Summary console.log('\n\n═'.repeat(80)); console.log('šŸ“Š TEST SUMMARY'); console.log('═'.repeat(80)); const collectionsPassed = Object.values(results.collections).filter(r => r.accessible).length; const relationshipsPassed = Object.values(results.relationships).filter(r => r === true).length; const adminPagesPassed = Object.values(results.adminPages).filter(r => r === true).length; const enginesPassed = Object.values(results.engines).filter(r => r === true).length; console.log(`\nšŸ“¦ Collections: ${collectionsPassed}/${Object.keys(results.collections).length} accessible`); console.log(`šŸ”— Relationships: ${relationshipsPassed}/${Object.keys(results.relationships).length} working`); console.log(`šŸŽ›ļø Admin Pages: ${adminPagesPassed}/${Object.keys(results.adminPages).length} connected`); console.log(`āš™ļø Engines: ${enginesPassed}/${Object.keys(results.engines).length} data accessible`); // Detailed issues const issues = []; if (results.adminPages['work_log'] === 'missing') { issues.push({ type: 'missing_collection', name: 'work_log', severity: 'medium' }); } Object.entries(results.collections).forEach(([name, data]) => { if (!data.accessible) { issues.push({ type: 'collection_access', name, severity: 'high', error: data.error }); } }); Object.entries(results.relationships).forEach(([name, status]) => { if (status === false) { issues.push({ type: 'relationship', name, severity: 'high' }); } }); if (issues.length > 0) { console.log('\n\nāš ļø ISSUES FOUND:\n'); issues.forEach(issue => { const icon = issue.severity === 'high' ? 'šŸ”“' : '🟔'; console.log(` ${icon} ${issue.type}: ${issue.name}`); }); } else { console.log('\n\nāœ… NO ISSUES FOUND - ALL SYSTEMS OPERATIONAL!'); } console.log('\n' + '═'.repeat(80) + '\n'); // Save results const fs = require('fs'); fs.writeFileSync('connection_test_results.json', JSON.stringify(results, null, 2)); console.log('šŸ“„ Detailed results saved to: connection_test_results.json\n'); return { results, issues }; } testConnection() .then(({ issues }) => { const highIssues = issues.filter(i => i.severity === 'high'); process.exit(highIssues.length > 0 ? 1 : 0); }) .catch(err => { console.error('āŒ Connection test failed:', err.message); process.exit(1); });