106 lines
3.0 KiB
JavaScript
106 lines
3.0 KiB
JavaScript
require('dotenv').config();
|
|
const admin = require('firebase-admin');
|
|
|
|
function inferSource(entry) {
|
|
const rawSource = (entry && entry.source ? String(entry.source) : '').trim().toLowerCase();
|
|
|
|
if (rawSource === 'server' || rawSource === 'worker') return 'server';
|
|
if (rawSource === 'app' || rawSource === 'mobile') return 'app';
|
|
|
|
const rawType = (entry && entry.type ? String(entry.type) : '').trim();
|
|
if (rawType.length > 0) return 'server';
|
|
|
|
return 'app';
|
|
}
|
|
|
|
async function main() {
|
|
const isDryRun = process.argv.includes('--dry-run');
|
|
|
|
const requiredEnvs = [
|
|
'FIREBASE_PROJECT_ID',
|
|
'FIREBASE_CLIENT_EMAIL',
|
|
'FIREBASE_PRIVATE_KEY',
|
|
'FIREBASE_DATABASE_URL',
|
|
];
|
|
|
|
const missing = requiredEnvs.filter((key) => !process.env[key]);
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing env vars: ${missing.join(', ')}`);
|
|
}
|
|
|
|
admin.initializeApp({
|
|
credential: admin.credential.cert({
|
|
projectId: process.env.FIREBASE_PROJECT_ID,
|
|
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
|
|
privateKey: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n'),
|
|
}),
|
|
databaseURL: process.env.FIREBASE_DATABASE_URL,
|
|
});
|
|
|
|
const db = admin.database();
|
|
const snap = await db.ref('history').get();
|
|
|
|
if (!snap.exists()) {
|
|
console.log('No history node found. Nothing to migrate.');
|
|
await admin.app().delete();
|
|
return;
|
|
}
|
|
|
|
const history = snap.val();
|
|
const updates = {};
|
|
|
|
let totalEntries = 0;
|
|
let changedEntries = 0;
|
|
let serverAssigned = 0;
|
|
let appAssigned = 0;
|
|
|
|
for (const dateKey of Object.keys(history)) {
|
|
const dateNode = history[dateKey];
|
|
if (!dateNode || typeof dateNode !== 'object') continue;
|
|
|
|
for (const timeKey of Object.keys(dateNode)) {
|
|
const entry = dateNode[timeKey];
|
|
if (!entry || typeof entry !== 'object') continue;
|
|
|
|
totalEntries += 1;
|
|
const target = inferSource(entry);
|
|
const currentRaw = entry.source == null ? '' : String(entry.source).trim().toLowerCase();
|
|
const current = currentRaw === 'worker' ? 'server' : currentRaw === 'mobile' ? 'app' : currentRaw;
|
|
|
|
if (current !== target) {
|
|
updates[`history/${dateKey}/${timeKey}/source`] = target;
|
|
changedEntries += 1;
|
|
if (target === 'server') {
|
|
serverAssigned += 1;
|
|
} else {
|
|
appAssigned += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log('=== History Source Migration ===');
|
|
console.log(`Mode: ${isDryRun ? 'DRY RUN' : 'APPLY'}`);
|
|
console.log(`Total entries scanned: ${totalEntries}`);
|
|
console.log(`Entries to update: ${changedEntries}`);
|
|
console.log(`Assign source=server: ${serverAssigned}`);
|
|
console.log(`Assign source=app: ${appAssigned}`);
|
|
|
|
if (!isDryRun && changedEntries > 0) {
|
|
await db.ref().update(updates);
|
|
console.log('Migration applied successfully.');
|
|
} else if (!isDryRun) {
|
|
console.log('No updates needed.');
|
|
}
|
|
|
|
await admin.app().delete();
|
|
}
|
|
|
|
main().catch(async (err) => {
|
|
console.error('Migration failed:', err.message);
|
|
process.exitCode = 1;
|
|
try {
|
|
await admin.app().delete();
|
|
} catch (_) {}
|
|
});
|