/** * Strapi Content Migration Script * * This script exports content from the old Strapi server and imports it to the new one. * * Usage: * 1. Set environment variables: * * NEW_STRAPI_URL=https://your-new-strapi-server.com * NEW_STRAPI_API_TOKEN=your-api-token (if authentication is required) * * 2. Run: node scripts/migrate-strapi.js */ const fs = require('fs'); const path = require('path'); // Configuration from environment variables const OLD_STRAPI_URL = process.env.NEXT_PUBLIC_STRAPI_BASE_URL; const NEW_STRAPI_URL = process.env.NEW_STRAPI_URL || ''; const NEW_STRAPI_API_TOKEN = process.env.NEW_STRAPI_API_TOKEN || ''; // Content types to migrate const CONTENT_TYPES = [ 'schoolforschools', 'whyschoolforschools' ]; // Directory to store exported data const EXPORT_DIR = path.join(__dirname, 'strapi-export'); /** * Fetch all entries from a Strapi content type (handles pagination) */ async function fetchStrapiContent(contentType, baseUrl) { console.log(`\nšŸ“„ Fetching ${contentType} from ${baseUrl}...`); try { let allData = []; let page = 1; let hasMore = true; const pageSize = 100; while (hasMore) { const url = `${baseUrl}/api/${contentType}?pagination[page]=${page}&pagination[pageSize]=${pageSize}&populate=*`; const response = await fetch(url, { headers: { 'Accept': 'application/json', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' } }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data = await response.json(); // Handle Strapi v4 format with pagination if (data.data) { allData = allData.concat(data.data); // Check if there are more pages if (data.meta?.pagination) { const { page: currentPage, pageCount } = data.meta.pagination; hasMore = currentPage < pageCount; page++; } else { hasMore = false; } } else if (Array.isArray(data)) { // Handle Strapi v3 format or direct array (no pagination) allData = data; hasMore = false; } else { hasMore = false; } } console.log(` Found ${allData.length} entries`); return allData; } catch (error) { console.error(`āŒ Error fetching ${contentType}:`, error.message); return []; } } /** * Export content to JSON files */ async function exportContent() { console.log('šŸš€ Starting Strapi content export...'); console.log(`šŸ“” Source: ${OLD_STRAPI_URL}\n`); // Create export directory if (!fs.existsSync(EXPORT_DIR)) { fs.mkdirSync(EXPORT_DIR, { recursive: true }); } const exportData = {}; for (const contentType of CONTENT_TYPES) { const content = await fetchStrapiContent(contentType, OLD_STRAPI_URL); exportData[contentType] = content; // Save individual file const filePath = path.join(EXPORT_DIR, `${contentType}.json`); fs.writeFileSync(filePath, JSON.stringify(content, null, 2)); console.log(`āœ… Exported ${content.length} entries for ${contentType}`); } // Save combined export const combinedPath = path.join(EXPORT_DIR, 'all-content.json'); fs.writeFileSync(combinedPath, JSON.stringify(exportData, null, 2)); console.log(`\nāœ… Export complete! Data saved to: ${EXPORT_DIR}`); return exportData; } /** * Upload content to new Strapi server */ async function uploadToStrapi(contentType, entries, baseUrl, apiToken) { console.log(`\nšŸ“¤ Uploading ${entries.length} entries for ${contentType}...`); const headers = { 'Content-Type': 'application/json', 'Accept': 'application/json' }; if (apiToken) { headers['Authorization'] = `Bearer ${apiToken}`; } let successCount = 0; let errorCount = 0; for (const entry of entries) { try { // Remove id and other Strapi-specific fields that shouldn't be sent const { id, createdAt, updatedAt, publishedAt, ...entryData } = entry; // Handle nested relations - you may need to adjust this based on your schema const payload = { data: entryData }; const response = await fetch(`${baseUrl}/api/${contentType}`, { method: 'POST', headers, body: JSON.stringify(payload) }); if (response.ok) { successCount++; process.stdout.write('.'); } else { const errorText = await response.text(); console.error(`\nāŒ Failed to upload entry ${id}: ${response.status} - ${errorText}`); errorCount++; } } catch (error) { console.error(`\nāŒ Error uploading entry:`, error.message); errorCount++; } } console.log(`\nāœ… ${successCount} entries uploaded, ${errorCount} errors`); return { successCount, errorCount }; } /** * Import content from exported files */ async function importContent() { if (!NEW_STRAPI_URL) { console.error('āŒ NEW_STRAPI_URL environment variable is required for import'); return; } console.log('\nšŸš€ Starting Strapi content import...'); console.log(`šŸ“” Destination: ${NEW_STRAPI_URL}\n`); const combinedPath = path.join(EXPORT_DIR, 'all-content.json'); if (!fs.existsSync(combinedPath)) { console.error(`āŒ Export file not found: ${combinedPath}`); console.log('šŸ’” Run export first by calling exportContent()'); return; } const exportData = JSON.parse(fs.readFileSync(combinedPath, 'utf8')); for (const contentType of CONTENT_TYPES) { if (exportData[contentType]) { await uploadToStrapi(contentType, exportData[contentType], NEW_STRAPI_URL, NEW_STRAPI_API_TOKEN); } } console.log('\nāœ… Import complete!'); } /** * Main execution */ async function main() { const command = process.argv[2] || 'export'; if (command === 'export') { await exportContent(); } else if (command === 'import') { await importContent(); } else if (command === 'migrate') { // Export first, then import const exportData = await exportContent(); console.log('\nā³ Waiting 2 seconds before import...\n'); await new Promise(resolve => setTimeout(resolve, 2000)); await importContent(); } else { console.log(` Usage: node scripts/migrate-strapi.js [command] Commands: export - Export content from old Strapi server (default) import - Import content to new Strapi server migrate - Export and import in one go Environment Variables: OLD_STRAPI_URL - Source Strapi server URL NEW_STRAPI_URL - Destination Strapi server URL (required for import) NEW_STRAPI_API_TOKEN - API token for new Strapi server (if authentication required) Example: OLD_STRAPI_URL=https://old-server.com NEW_STRAPI_URL=https://new-server.com NEW_STRAPI_API_TOKEN=xxx node scripts/migrate-strapi.js migrate `); } } // Run if executed directly if (require.main === module) { main().catch(console.error); } module.exports = { exportContent, importContent };