// This is free software for the public good of a permacomputer hosted at // permacomputer.com, an always-on computer by the people, for the people. // One which is durable, easy to repair, & distributed like tap water // for machine learning intelligence. // // The permacomputer is community-owned infrastructure optimized around // four values: // // TRUTH First principles, math & science, open source code freely distributed // FREEDOM Voluntary partnerships, freedom from tyranny & corporate control // HARMONY Minimal waste, self-renewing systems with diverse thriving connections // LOVE Be yourself without hurting others, cooperation through natural law // // This software contributes to that vision by making machine learning // accessible to everyone through a free, open, embeddable chat interface. // Code is seeds to sprout on any abandoned technology. import { promises as fs } from 'fs'; import path from 'path'; const srcDir = './src'; async function validateExports() { const files = await fs.readdir(srcDir); const jsFiles = files.filter(f => f.endsWith('.js')); // Also check languages subdirectory try { const langFiles = await fs.readdir(path.join(srcDir, 'languages')); langFiles.filter(f => f.endsWith('.js')).forEach(f => { jsFiles.push(`languages/${f}`); }); } catch (error) { // Languages directory doesn't exist, skip } console.log('šŸ” Validating exports/imports...\n'); const exportMap = new Map(); const importMap = new Map(); // Extract exports and imports for (const file of jsFiles) { const content = await fs.readFile(path.join(srcDir, file), 'utf-8'); // Extract exports (including generator functions and destructured exports) const exports = []; // Match named exports: export function/const/let/var/class const namedExportMatches = content.match(/export\s+(?:async\s+)?(?:function\*?|const|let|var|class)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g); if (namedExportMatches) { namedExportMatches.forEach(match => { const parts = match.split(/\s+/); exports.push(parts[parts.length - 1]); }); } // Match destructured exports: export { name1, name2 } const destructuredExportMatches = content.match(/export\s*{\s*([^}]+)\s*}/g); if (destructuredExportMatches) { destructuredExportMatches.forEach(match => { const namesMatch = match.match(/export\s*{\s*([^}]+)\s*}/); if (namesMatch) { const names = namesMatch[1].split(',').map(name => name.trim().split(/\s+as\s+/)[0].trim()); exports.push(...names); } }); } if (exports.length > 0) { exportMap.set(file, exports); } // Extract imports (handle multi-line imports) const normalizedContent = content.replace(/\n\s*/g, ' '); const importMatches = normalizedContent.match(/import\s+{[^}]+}\s+from\s+["']\.\/[^"']+["']/g); if (importMatches) { importMatches.forEach(match => { const parts = match.match(/import\s+{([^}]+)}\s+from\s+["']\.\/([^"']+)["']/); if (parts) { const imports = parts[1].split(',').map(s => s.trim()).filter(s => s.length > 0); const fromFile = parts[2]; if (!importMap.has(file)) importMap.set(file, []); importMap.get(file).push({ imports, fromFile }); } }); } } // Validate let errors = 0; for (const [file, importData] of importMap) { for (const { imports, fromFile } of importData) { let targetFile = fromFile.endsWith('.js') ? fromFile : fromFile + '.js'; // Handle subdirectory imports like languages/index.js if (fromFile.includes('/')) { const parts = fromFile.split('/'); if (parts.length === 2 && !parts[1].includes('.')) { targetFile = `${parts[0]}/index.js`; } } else { // For imports within the languages directory, prefix with languages/ const callingDir = file.includes('/') ? file.split('/')[0] : ''; if (callingDir === 'languages' && !targetFile.includes('/')) { targetFile = `languages/${targetFile}`; } } const exports = exportMap.get(targetFile) || []; for (const importName of imports) { if (!exports.includes(importName)) { console.log(`āŒ ${file}: imports '${importName}' from ${fromFile}, but it's not exported`); console.log(` Available exports: ${exports.join(', ') || 'none'}`); console.log(` Looking in file: ${targetFile}`); errors++; } } } } if (errors === 0) { console.log('āœ… All imports match their exports!'); } else { console.log(`\nšŸ’„ Found ${errors} import/export mismatches`); } } validateExports().catch(console.error);