w-funnel/scripts/migrate-trial-choice-arrow-hint.mjs
2025-12-01 04:09:26 +03:00

166 lines
5.1 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Миграционный скрипт для добавления arrowHint и accentedOption настроек
* к существующим trialChoice экранам.
*
* Этот скрипт:
* 1. Подключается к MongoDB
* 2. Находит все воронки с экранами template: "trialChoice"
* 3. Добавляет дефолтные arrowHint и accentedOption настройки если их нет
*
* Запуск:
* node scripts/migrate-trial-choice-arrow-hint.mjs
*
* Опции:
* --dry-run Показать изменения без записи в базу
*/
import mongoose from 'mongoose';
import dotenv from 'dotenv';
// Load environment variables
dotenv.config({ path: '.env.local' });
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/witlab-funnel';
const isDryRun = process.argv.includes('--dry-run');
// Дефолтные значения для arrowHint
const DEFAULT_ARROW_HINT = {
text: "It costs us {{maxTrialPrice}} to compensate our team for the work involved in creating your personalized portrait and guide, but please choose the amount you are comfortable with.",
position: "bottom-right"
};
// Дефолтное значение для accentedOption
const DEFAULT_ACCENTED_OPTION = "server";
// Mongoose schema (minimal for migration)
const FunnelSchema = new mongoose.Schema({
funnelData: mongoose.Schema.Types.Mixed,
name: String,
status: String,
}, {
timestamps: true,
collection: 'funnels'
});
const FunnelModel = mongoose.models.Funnel || mongoose.model('Funnel', FunnelSchema);
async function connectToDatabase() {
try {
await mongoose.connect(MONGODB_URI, {
bufferCommands: false,
maxPoolSize: 10,
serverSelectionTimeoutMS: 5000,
socketTimeoutMS: 45000,
});
console.log('✅ Connected to MongoDB');
} catch (error) {
console.error('❌ Failed to connect to MongoDB:', error.message);
process.exit(1);
}
}
async function migrateFunnels() {
// Находим все воронки с trialChoice экранами без arrowHint
const funnels = await FunnelModel.find({
'funnelData.screens': {
$elemMatch: {
template: 'trialChoice'
}
}
});
console.log(`\n📋 Found ${funnels.length} funnels with trialChoice screens\n`);
let updatedCount = 0;
let screensUpdated = 0;
for (const funnel of funnels) {
const funnelId = funnel.funnelData?.meta?.id || funnel._id;
const funnelName = funnel.name || funnelId;
let hasChanges = false;
const screens = funnel.funnelData?.screens || [];
for (let i = 0; i < screens.length; i++) {
const screen = screens[i];
if (screen.template === 'trialChoice') {
const needsArrowHint = !screen.arrowHint;
const needsAccentedOption = screen.accentedOption === undefined;
if (needsArrowHint || needsAccentedOption) {
const updates = [];
if (needsArrowHint) updates.push('arrowHint');
if (needsAccentedOption) updates.push('accentedOption');
console.log(` 📍 [${funnelName}] Screen "${screen.id}" needs: ${updates.join(', ')}`);
if (!isDryRun) {
screens[i] = {
...screen,
...(needsArrowHint && { arrowHint: DEFAULT_ARROW_HINT }),
...(needsAccentedOption && { accentedOption: DEFAULT_ACCENTED_OPTION }),
};
}
hasChanges = true;
screensUpdated++;
} else {
console.log(` ✅ [${funnelName}] Screen "${screen.id}" already has all settings`);
}
}
}
if (hasChanges) {
if (!isDryRun) {
funnel.funnelData.screens = screens;
funnel.markModified('funnelData');
await funnel.save();
console.log(` 💾 [${funnelName}] Saved changes`);
} else {
console.log(` 🔍 [${funnelName}] Would update (dry-run)`);
}
updatedCount++;
}
}
return { updatedCount, screensUpdated, total: funnels.length };
}
async function main() {
console.log('🚀 Starting trialChoice arrowHint migration...');
if (isDryRun) {
console.log('⚠️ DRY RUN MODE - No changes will be saved\n');
}
await connectToDatabase();
const { updatedCount, screensUpdated, total } = await migrateFunnels();
console.log('\n📊 Migration Summary:');
console.log('=====================');
console.log(`📁 Total funnels with trialChoice: ${total}`);
console.log(`📝 Funnels updated: ${updatedCount}`);
console.log(`🎯 Screens updated: ${screensUpdated}`);
if (isDryRun) {
console.log('\n⚠ This was a dry run. Run without --dry-run to apply changes.');
} else if (updatedCount > 0) {
console.log('\n✅ Migration completed successfully!');
} else {
console.log('\n✨ All trialChoice screens already have arrowHint configured!');
}
await mongoose.connection.close();
console.log('\n👋 Database connection closed.');
}
main().catch(error => {
console.error('\n💥 Fatal error:', error);
process.exit(1);
});