MotorSignal-App/website/lib/firebase-client.ts

36 lines
1.9 KiB
TypeScript

import { getApp, getApps, initializeApp } from 'firebase/app';
import { connectAuthEmulator, getAuth, GoogleAuthProvider } from 'firebase/auth';
import { connectFirestoreEmulator, getFirestore } from 'firebase/firestore';
import { getFirebaseClientConfig } from './firebase-config';
// Explicit local QA opt-in. A separate app/project prevents reusing a rider's
// production session, and loopback endpoints cannot send fixtures to production.
const useEmulators = process.env.NEXT_PUBLIC_FIREBASE_EMULATORS === 'true';
const qaProject = process.env.NEXT_PUBLIC_FIREBASE_QA_PROJECT_ID;
const authEmulatorPort = Number(process.env.NEXT_PUBLIC_FIREBASE_AUTH_EMULATOR_PORT ?? 9099);
const firestoreEmulatorPort = Number(process.env.NEXT_PUBLIC_FIREBASE_FIRESTORE_EMULATOR_PORT ?? 8088);
if (useEmulators && (!qaProject?.startsWith('demo-') ||
(typeof window !== 'undefined' && !['localhost', '127.0.0.1', '[::1]'].includes(window.location.hostname)))) {
throw new Error('Firebase QA requires a demo- project and a loopback website origin.');
}
if (useEmulators && (![authEmulatorPort, firestoreEmulatorPort].every((port) =>
Number.isInteger(port) && port >= 1 && port <= 65535))) {
throw new Error('Firebase QA emulator ports must be valid TCP ports.');
}
const existingQaApp = getApps().find((candidate) => candidate.name === 'motorsignal-local-qa');
const app = useEmulators
? existingQaApp ?? initializeApp({ apiKey: 'demo-key', projectId: qaProject, authDomain: 'localhost' }, 'motorsignal-local-qa')
: getApps().some((candidate) => candidate.name === '[DEFAULT]')
? getApp()
: initializeApp(getFirebaseClientConfig());
export const firebaseAuth = getAuth(app);
export const googleProvider = new GoogleAuthProvider();
export const firestore = getFirestore(app);
if (useEmulators && !existingQaApp) {
connectAuthEmulator(firebaseAuth, `http://127.0.0.1:${authEmulatorPort}`);
connectFirestoreEmulator(firestore, '127.0.0.1', firestoreEmulatorPort);
}