UNPKG

codalware-auth

Version:

Complete authentication system with enterprise security, attack protection, team workspaces, waitlist, billing, UI components, 2FA, and account recovery - production-ready in 5 minutes. Enhanced CLI with verification, rollback, and App Router scaffolding.

157 lines (131 loc) 4.89 kB
#!/usr/bin/env node /** * Rollback AuthCore Scaffold * Removes files created by `npx authcore init` * * Usage: * node scripts/undo-scaffold-auth.js * node scripts/undo-scaffold-auth.js --dry-run */ const fs = require('fs'); const path = require('path'); const DRY_RUN = process.argv.includes('--dry-run'); const MANIFEST_PATH = path.join(process.cwd(), '.scaffold-auth', 'manifest.json'); const colors = { green: '\x1b[32m', red: '\x1b[31m', yellow: '\x1b[33m', blue: '\x1b[34m', reset: '\x1b[0m', }; function log(message, color = 'reset') { console.log(`${colors[color]}${message}${colors.reset}`); } function deleteFile(filePath) { if (!fs.existsSync(filePath)) { log(` ⚠️ File not found: ${filePath}`, 'yellow'); return false; } if (DRY_RUN) { log(` [DRY-RUN] Would delete: ${filePath}`, 'blue'); return true; } try { fs.unlinkSync(filePath); log(` ✅ Deleted: ${filePath}`, 'green'); return true; } catch (error) { log(` ❌ Failed to delete: ${filePath} (${error.message})`, 'red'); return false; } } function deleteEmptyDir(dirPath) { if (!fs.existsSync(dirPath)) return; const files = fs.readdirSync(dirPath); if (files.length === 0) { if (DRY_RUN) { log(` [DRY-RUN] Would delete empty dir: ${dirPath}`, 'blue'); } else { fs.rmdirSync(dirPath); log(` 🗑️ Deleted empty directory: ${dirPath}`, 'green'); } } } async function rollback() { log('\n🔄 AuthCore Scaffold Rollback\n', 'blue'); if (!fs.existsSync(MANIFEST_PATH)) { log('❌ No manifest found at .scaffold-auth/manifest.json', 'red'); log(' Cannot rollback without manifest. Files may have been created manually.\n', 'yellow'); process.exit(1); } const manifest = JSON.parse(fs.readFileSync(MANIFEST_PATH, 'utf-8')); log(`📋 Manifest loaded: ${manifest.files.length} files to remove\n`, 'yellow'); log(` Created at: ${new Date(manifest.createdAt).toLocaleString()}`); log(` Flags used: ${JSON.stringify(manifest.flags)}\n`); if (DRY_RUN) { log('🏃 Running in DRY-RUN mode (no files will be deleted)\n', 'yellow'); } // Confirm before deleting if (!DRY_RUN) { log('⚠️ This will DELETE the following files:', 'red'); manifest.files.forEach(file => log(` - ${file}`, 'yellow')); log('\nPress Ctrl+C to cancel, or wait 5 seconds to continue...', 'yellow'); await new Promise(resolve => setTimeout(resolve, 5000)); log('\n🗑️ Starting deletion...\n', 'red'); } // Delete files let deletedCount = 0; let failedCount = 0; for (const file of manifest.files) { const filePath = path.join(process.cwd(), file); const deleted = deleteFile(filePath); if (deleted) deletedCount++; else failedCount++; } // Clean up empty directories const dirs = new Set(manifest.files.map(f => path.dirname(f))); const sortedDirs = Array.from(dirs).sort((a, b) => b.length - a.length); // Deepest first log('\n🧹 Cleaning up empty directories...\n', 'blue'); for (const dir of sortedDirs) { const dirPath = path.join(process.cwd(), dir); deleteEmptyDir(dirPath); } // Database migration warning if (manifest.migrations && manifest.migrations.length > 0) { log('\n⚠️ Database Migrations Detected:', 'yellow'); log(' The following migrations were applied:', 'yellow'); manifest.migrations.forEach(m => log(` - ${m}`, 'yellow')); log('\n ⚠️ IMPORTANT: Migrations are NOT automatically rolled back!', 'red'); log(' To reverse database changes, you must:', 'yellow'); log(' 1. Back up your database'); log(' 2. Manually revert migrations or restore from backup'); log(' 3. Run: npx prisma migrate resolve --rolled-back <migration-name>\n'); } // Delete manifest itself if (!DRY_RUN) { try { fs.unlinkSync(MANIFEST_PATH); log('✅ Deleted manifest file\n', 'green'); const manifestDir = path.dirname(MANIFEST_PATH); if (fs.existsSync(manifestDir) && fs.readdirSync(manifestDir).length === 0) { fs.rmdirSync(manifestDir); log('✅ Deleted .scaffold-auth directory\n', 'green'); } } catch (error) { log(`⚠️ Could not delete manifest: ${error.message}\n`, 'yellow'); } } // Summary log('📊 Summary:', 'blue'); log(` Files deleted: ${deletedCount}`); log(` Failed: ${failedCount}`); if (DRY_RUN) { log('\n💡 Run without --dry-run to actually delete files\n', 'yellow'); } else { log('\n✨ Rollback complete!\n', 'green'); } } rollback().catch(error => { log(`\n❌ Rollback failed: ${error.message}\n`, 'red'); process.exit(1); });