Spaces:
Running
Running
Download src/firebase.ts from caustino/CUSIPstudio: direct link, hf CLI and curl.
- Browser
- Download file 5.15 kB
-
https://huggingface.co/spaces/caustino/CUSIPstudio/resolve/main/src/firebase.ts
- Command line
-
hf download hf://spaces/caustino/CUSIPstudio/src/firebase.ts
-
curl -L -o firebase.ts https://huggingface.co/spaces/caustino/CUSIPstudio/resolve/main/src/firebase.ts
5.15 kB
| import { initializeApp } from 'firebase/app'; | |
| import { | |
| getAuth, | |
| signInWithPopup, | |
| GoogleAuthProvider, | |
| onAuthStateChanged, | |
| User, | |
| signOut | |
| } from 'firebase/auth'; | |
| export type { User }; | |
| import { | |
| getFirestore, | |
| doc, | |
| getDocFromServer, | |
| collection, | |
| addDoc, | |
| setDoc, | |
| getDocs, | |
| onSnapshot | |
| } from 'firebase/firestore'; | |
| import firebaseConfig from '../firebase-applet-config.json'; | |
| // Initialize Firebase | |
| const app = initializeApp(firebaseConfig); | |
| // Initialize Firestore with explicit databaseId from config | |
| export const db = getFirestore(app, firebaseConfig.firestoreDatabaseId); | |
| // Initialize Auth | |
| export const auth = getAuth(app); | |
| // Google Workspace Scopes | |
| export const WORKSPACE_SCOPES = [ | |
| 'https://www.googleapis.com/auth/drive.file', | |
| 'https://www.googleapis.com/auth/drive', | |
| 'https://www.googleapis.com/auth/drive.readonly', | |
| 'https://www.googleapis.com/auth/spreadsheets', | |
| 'https://www.googleapis.com/auth/spreadsheets.readonly', | |
| 'https://mail.google.com/', | |
| 'https://www.googleapis.com/auth/gmail.compose', | |
| 'https://www.googleapis.com/auth/gmail.modify', | |
| 'https://www.googleapis.com/auth/gmail.readonly', | |
| 'https://www.googleapis.com/auth/gmail.send', | |
| 'https://www.googleapis.com/auth/calendar', | |
| 'https://www.googleapis.com/auth/calendar.events', | |
| 'https://www.googleapis.com/auth/calendar.readonly', | |
| 'https://www.googleapis.com/auth/documents', | |
| 'https://www.googleapis.com/auth/documents.readonly', | |
| 'https://www.googleapis.com/auth/chat.messages', | |
| 'https://www.googleapis.com/auth/chat.messages.create', | |
| 'https://www.googleapis.com/auth/chat.spaces', | |
| 'https://www.googleapis.com/auth/chat.spaces.readonly', | |
| 'https://www.googleapis.com/auth/meetings.space.created', | |
| 'https://www.googleapis.com/auth/meetings.space.readonly' | |
| ]; | |
| const provider = new GoogleAuthProvider(); | |
| WORKSPACE_SCOPES.forEach(scope => provider.addScope(scope)); | |
| // In-memory token management (strictly not stored in localStorage) | |
| let isSigningIn = false; | |
| let cachedAccessToken: string | null = null; | |
| // Auth listener | |
| export const initAuth = ( | |
| onAuthSuccess?: (user: User, token: string) => void, | |
| onAuthFailure?: () => void | |
| ) => { | |
| return onAuthStateChanged(auth, async (user: User | null) => { | |
| if (user) { | |
| if (cachedAccessToken) { | |
| if (onAuthSuccess) onAuthSuccess(user, cachedAccessToken); | |
| } else if (!isSigningIn) { | |
| cachedAccessToken = null; | |
| if (onAuthFailure) onAuthFailure(); | |
| } | |
| } else { | |
| cachedAccessToken = null; | |
| if (onAuthFailure) onAuthFailure(); | |
| } | |
| }); | |
| }; | |
| // Sign in with Google Popup | |
| export const googleSignIn = async (): Promise<{ user: User; accessToken: string } | null> => { | |
| try { | |
| isSigningIn = true; | |
| const result = await signInWithPopup(auth, provider); | |
| const credential = GoogleAuthProvider.credentialFromResult(result); | |
| if (!credential?.accessToken) { | |
| throw new Error('Failed to obtain Google Workspace access token.'); | |
| } | |
| cachedAccessToken = credential.accessToken; | |
| return { user: result.user, accessToken: cachedAccessToken }; | |
| } catch (error: any) { | |
| console.error('Google Sign-in Error:', error); | |
| throw error; | |
| } finally { | |
| isSigningIn = false; | |
| } | |
| }; | |
| export const getAccessToken = (): string | null => { | |
| return cachedAccessToken; | |
| }; | |
| export const logout = async () => { | |
| await signOut(auth); | |
| cachedAccessToken = null; | |
| }; | |
| // Error handling standard required by Firebase skill | |
| export enum OperationType { | |
| CREATE = 'create', | |
| UPDATE = 'update', | |
| DELETE = 'delete', | |
| LIST = 'list', | |
| GET = 'get', | |
| WRITE = 'write', | |
| } | |
| export interface FirestoreErrorInfo { | |
| error: string; | |
| operationType: OperationType; | |
| path: string | null; | |
| authInfo: { | |
| userId?: string | null; | |
| email?: string | null; | |
| emailVerified?: boolean | null; | |
| isAnonymous?: boolean | null; | |
| tenantId?: string | null; | |
| providerInfo?: { | |
| providerId?: string | null; | |
| email?: string | null; | |
| }[]; | |
| }; | |
| } | |
| export function handleFirestoreError(error: unknown, operationType: OperationType, path: string | null): never { | |
| const errInfo: FirestoreErrorInfo = { | |
| error: error instanceof Error ? error.message : String(error), | |
| authInfo: { | |
| userId: auth.currentUser?.uid, | |
| email: auth.currentUser?.email, | |
| emailVerified: auth.currentUser?.emailVerified, | |
| isAnonymous: auth.currentUser?.isAnonymous, | |
| tenantId: auth.currentUser?.tenantId, | |
| providerInfo: auth.currentUser?.providerData?.map(provider => ({ | |
| providerId: provider.providerId, | |
| email: provider.email, | |
| })) || [] | |
| }, | |
| operationType, | |
| path | |
| }; | |
| console.error('Firestore Error: ', JSON.stringify(errInfo)); | |
| throw new Error(JSON.stringify(errInfo)); | |
| } | |
| // Test connection on app load | |
| export async function testFirestoreConnection() { | |
| try { | |
| await getDocFromServer(doc(db, 'test', 'connection')); | |
| } catch (error: any) { | |
| if (error instanceof Error && error.message.includes('the client is offline')) { | |
| console.warn("Firestore client appears offline. Please check network connection."); | |
| } | |
| } | |
| } | |
| testFirestoreConnection(); | |