second to last commit hopefully final features and Ui refinements
This commit is contained in:
85
scripts/migrate-geohash-precision.js
Normal file
85
scripts/migrate-geohash-precision.js
Normal file
@@ -0,0 +1,85 @@
|
||||
// scripts/migrate-geohash-precision.js
|
||||
//
|
||||
// One-time migration: re-encodes every existing message's `geohash` field at
|
||||
// precision 9 (previously 6), matching the precision addMessage() now writes
|
||||
// for new messages (see src/lib/firebase/messages.js). lat/lng/text/etc are
|
||||
// read from each doc but never written back - updateDoc() below is only ever
|
||||
// called with { geohash: newGeohash }, so this cannot touch any other field.
|
||||
//
|
||||
// Firestore's security rules normally only allow `echoCount`/`lastEchoAt` to
|
||||
// change via update() (see firestore.rules). Before running this script,
|
||||
// temporarily add 'geohash' to that allowlist and deploy:
|
||||
//
|
||||
// firebase deploy --only firestore:rules
|
||||
//
|
||||
// Then run this script:
|
||||
//
|
||||
// node scripts/migrate-geohash-precision.js
|
||||
//
|
||||
// Then revert firestore.rules back to its original allowlist and redeploy.
|
||||
|
||||
import { initializeApp } from 'firebase/app';
|
||||
import { getFirestore, collection, getDocs, doc, updateDoc } from 'firebase/firestore';
|
||||
import ngeohash from 'ngeohash';
|
||||
import { readFileSync } from 'fs';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { dirname, join } from 'path';
|
||||
|
||||
// --- load PUBLIC_FIREBASE_* values from .env (same file SvelteKit reads via
|
||||
// $env/static/public, which only works inside SvelteKit - this script is a
|
||||
// plain Node script, so .env is parsed by hand here instead) --------------
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const envPath = join(__dirname, '..', '.env');
|
||||
const env = {};
|
||||
for (const line of readFileSync(envPath, 'utf-8').split('\n')) {
|
||||
const trimmed = line.trim();
|
||||
if (!trimmed || trimmed.startsWith('#')) continue;
|
||||
const eq = trimmed.indexOf('=');
|
||||
if (eq === -1) continue;
|
||||
env[trimmed.slice(0, eq).trim()] = trimmed.slice(eq + 1).trim();
|
||||
}
|
||||
|
||||
const firebaseConfig = {
|
||||
apiKey: env.PUBLIC_FIREBASE_API_KEY,
|
||||
authDomain: env.PUBLIC_FIREBASE_AUTH_DOMAIN,
|
||||
projectId: env.PUBLIC_FIREBASE_PROJECT_ID,
|
||||
storageBucket: env.PUBLIC_FIREBASE_STORAGE_BUCKET,
|
||||
messagingSenderId: env.PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
|
||||
appId: env.PUBLIC_FIREBASE_APP_ID
|
||||
};
|
||||
|
||||
const NEW_PRECISION = 9; // matches addMessage() in src/lib/firebase/messages.js
|
||||
|
||||
const app = initializeApp(firebaseConfig);
|
||||
const db = getFirestore(app);
|
||||
|
||||
const snapshot = await getDocs(collection(db, 'messages'));
|
||||
console.log(`found ${snapshot.docs.length} message(s)`);
|
||||
|
||||
let updated = 0;
|
||||
let skipped = 0;
|
||||
|
||||
for (const docSnap of snapshot.docs) {
|
||||
const data = docSnap.data();
|
||||
|
||||
if (typeof data.lat !== 'number' || typeof data.lng !== 'number') {
|
||||
console.warn(`skipping ${docSnap.id}: missing lat/lng`);
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
const newGeohash = ngeohash.encode(data.lat, data.lng, NEW_PRECISION);
|
||||
|
||||
if (data.geohash === newGeohash) {
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// ONLY the geohash field is written - everything else on the doc is
|
||||
// left exactly as it was.
|
||||
await updateDoc(doc(db, 'messages', docSnap.id), { geohash: newGeohash });
|
||||
console.log(`${docSnap.id}: ${data.geohash} -> ${newGeohash}`);
|
||||
updated++;
|
||||
}
|
||||
|
||||
console.log(`done. updated ${updated}, skipped ${skipped}`);
|
||||
Reference in New Issue
Block a user