SFS/scripts/migrate-strapi.js
2025-12-16 10:03:26 +05:30

246 lines
6.9 KiB
JavaScript

/**
* 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 };