Files
Compass/backend/scripts/clear_firebase.ts
2026-06-09 21:42:03 +02:00

92 lines
3.1 KiB
TypeScript

import chalk from 'chalk'
import * as admin from 'firebase-admin'
import {initAdmin} from 'shared/init-admin'
import {isProd} from 'common/envs/is-prod'
// Deletes ALL Firebase Auth users. DEV ONLY.
//
// Used by ./scripts/dev_db_clear_firebase.sh as part of the dev DB reset flow.
// This is destructive and irreversible, so it hard-refuses to run against prod:
// - bails if ENVIRONMENT is not 'dev'
// - bails if isProd() is true
// - bails if the initialized Firebase project is the prod project
//
// Firebase project ids (see common/envs/is-prod.ts + init-admin.ts):
const DEV_FIREBASE_PROJECT_ID = 'compass-57c3c'
async function main() {
// 1. Refuse anything that isn't an explicit dev run.
const env = process.env.ENVIRONMENT?.toUpperCase()
if (env !== 'DEV') {
throw new Error(
`Refusing to clear Firebase users: ENVIRONMENT is "${process.env.ENVIRONMENT ?? '(unset)'}", expected "dev". ` +
`This script is DEV ONLY.`,
)
}
initAdmin()
// 2. Belt-and-suspenders: refuse if the resolved config looks like prod.
if (isProd()) {
throw new Error(
'Refusing to clear Firebase users: isProd() returned true. This script is DEV ONLY.',
)
}
const projectId = admin.app().options.projectId
console.log({projectId})
if (projectId !== DEV_FIREBASE_PROJECT_ID) {
throw new Error(
`Refusing to clear Firebase users: initialized Firebase project is the PROD project ` +
`("${projectId}"). This script is DEV ONLY.`,
)
}
const auth = admin.app().auth()
console.log(
chalk.cyan(`Clearing all Firebase Auth users on project "${projectId ?? '(unknown)'}"…`),
)
let totalDeleted = 0
let totalFailed = 0
// listUsers returns up to 1000 per page; deleteUsers accepts up to 1000 uids.
// Re-list from the start after each delete batch instead of paging, since
// deletions shift the page tokens.
for (;;) {
const {users} = await auth.listUsers(1000)
if (users.length === 0) break
const uids = users.map((u) => u.uid)
const result = await auth.deleteUsers(uids)
totalDeleted += result.successCount
totalFailed += result.failureCount
for (const err of result.errors) {
console.error(chalk.red(` [ERROR] uid=${uids[err.index]}${err.error.message}`))
}
console.log(
chalk.blue(
` Deleted ${result.successCount}/${uids.length} in this batch (running total: ${totalDeleted})`,
),
)
// If a whole batch fails, stop to avoid an infinite loop.
if (result.successCount === 0) break
}
console.log(chalk.cyan('\n── Firebase clear complete ─────────────────────────'))
console.log(chalk.green(` Deleted : ${totalDeleted}`))
console.log(chalk.red(` Failed : ${totalFailed}`))
console.log(chalk.cyan('────────────────────────────────────────────────────'))
process.exit(totalFailed > 0 ? 1 : 0)
}
main().catch((err) => {
console.error(chalk.red(err instanceof Error ? err.message : err))
process.exit(1)
})