mirror of
https://github.com/cline/cline.git
synced 2026-09-16 21:01:52 +08:00
moving firebase auth logic to webview because nodejs firebase token refresh is not supported
This commit is contained in:
@@ -14,7 +14,7 @@ import { selectImages } from "../../integrations/misc/process-images"
|
||||
import { getTheme } from "../../integrations/theme/getTheme"
|
||||
import WorkspaceTracker from "../../integrations/workspace/WorkspaceTracker"
|
||||
import { McpHub } from "../../services/mcp/McpHub"
|
||||
import { FirebaseAuthManager, UserInfo } from "../../services/auth/FirebaseAuthManager"
|
||||
import { UserInfo } from "../../shared/UserInfo"
|
||||
import { ApiProvider, ModelInfo } from "../../shared/api"
|
||||
import { findLast } from "../../shared/array"
|
||||
import { ExtensionMessage, ExtensionState, Platform } from "../../shared/ExtensionMessage"
|
||||
@@ -105,7 +105,6 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
private cline?: Cline
|
||||
workspaceTracker?: WorkspaceTracker
|
||||
mcpHub?: McpHub
|
||||
private authManager: FirebaseAuthManager
|
||||
private latestAnnouncementId = "jan-20-2025" // update to some unique identifier when we add a new announcement
|
||||
|
||||
constructor(
|
||||
@@ -116,7 +115,6 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
ClineProvider.activeInstances.add(this)
|
||||
this.workspaceTracker = new WorkspaceTracker(this)
|
||||
this.mcpHub = new McpHub(this)
|
||||
this.authManager = new FirebaseAuthManager(this)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -142,7 +140,6 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
this.workspaceTracker = undefined
|
||||
this.mcpHub?.dispose()
|
||||
this.mcpHub = undefined
|
||||
this.authManager.dispose()
|
||||
this.outputChannel.appendLine("Disposed all disposables")
|
||||
ClineProvider.activeInstances.delete(this)
|
||||
}
|
||||
@@ -150,7 +147,6 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
// Auth methods
|
||||
async handleSignOut() {
|
||||
try {
|
||||
await this.authManager.signOut()
|
||||
await this.storeSecret("authToken", undefined)
|
||||
await this.storeSecret("clineApiKey", undefined)
|
||||
await this.updateGlobalState("apiProvider", "openrouter")
|
||||
@@ -358,7 +354,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; font-src ${webview.cspSource}; style-src ${webview.cspSource} 'unsafe-inline'; img-src ${webview.cspSource} https: data:; script-src 'nonce-${nonce}';">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; connect-src https://identitytoolkit.googleapis.com https://*.firebaseauth.com https://*.firebaseio.com https://*.googleapis.com https://*.firebase.com; font-src ${webview.cspSource}; style-src ${webview.cspSource} 'unsafe-inline'; img-src ${webview.cspSource} https: data:; script-src 'nonce-${nonce}' 'unsafe-eval';">
|
||||
<link rel="stylesheet" type="text/css" href="${stylesUri}">
|
||||
<link href="${codiconsUri}" rel="stylesheet" />
|
||||
<title>Cline</title>
|
||||
@@ -382,6 +378,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
webview.onDidReceiveMessage(
|
||||
async (message: WebviewMessage) => {
|
||||
switch (message.type) {
|
||||
case "authStateChanged":
|
||||
await this.setUserInfo(message.user || undefined)
|
||||
await this.postStateToWebview()
|
||||
break
|
||||
case "webviewDidLaunch":
|
||||
this.postStateToWebview()
|
||||
this.workspaceTracker?.populateFilePaths() // don't await
|
||||
@@ -987,12 +987,14 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
|
||||
async handleAuthCallback(customToken: string, apiKey: string) {
|
||||
try {
|
||||
// Store the custom token for future re-authentication
|
||||
await this.storeSecret("authToken", customToken)
|
||||
// Store API key for API calls
|
||||
await this.storeSecret("clineApiKey", apiKey)
|
||||
|
||||
// Sign in with Firebase using the custom token
|
||||
await this.authManager.signInWithCustomToken(customToken)
|
||||
// Send custom token to webview for Firebase auth
|
||||
await this.postMessageToWebview({
|
||||
type: "authCallback",
|
||||
customToken,
|
||||
})
|
||||
|
||||
const clineProvider: ApiProvider = "cline"
|
||||
await this.updateGlobalState("apiProvider", clineProvider)
|
||||
|
||||
@@ -1,338 +0,0 @@
|
||||
import { initializeApp } from "firebase/app"
|
||||
import {
|
||||
Auth,
|
||||
User,
|
||||
browserLocalPersistence,
|
||||
getAuth,
|
||||
onAuthStateChanged,
|
||||
setPersistence,
|
||||
signInWithCustomToken,
|
||||
signOut,
|
||||
AuthError as FirebaseAuthError,
|
||||
} from "firebase/auth"
|
||||
import * as vscode from "vscode"
|
||||
import { ClineProvider } from "../../core/webview/ClineProvider"
|
||||
import { firebaseConfig } from "./config"
|
||||
|
||||
enum AuthErrorType {
|
||||
Network = "network",
|
||||
InvalidToken = "invalid_token",
|
||||
ExpiredToken = "expired_token",
|
||||
TokenMismatch = "token_mismatch",
|
||||
Other = "other",
|
||||
}
|
||||
|
||||
interface AuthError {
|
||||
type: AuthErrorType
|
||||
message: string
|
||||
originalError?: any
|
||||
}
|
||||
|
||||
interface RetryConfig {
|
||||
maxAttempts: number
|
||||
baseDelay: number // in ms
|
||||
maxDelay: number // in ms
|
||||
}
|
||||
|
||||
const DEFAULT_RETRY_CONFIG: RetryConfig = {
|
||||
maxAttempts: 3,
|
||||
baseDelay: 1000,
|
||||
maxDelay: 10000,
|
||||
}
|
||||
|
||||
export interface UserInfo {
|
||||
displayName: string | null
|
||||
email: string | null
|
||||
photoURL: string | null
|
||||
}
|
||||
|
||||
export class FirebaseAuthManager {
|
||||
private providerRef: WeakRef<ClineProvider>
|
||||
private auth: Auth
|
||||
private disposables: vscode.Disposable[] = []
|
||||
private isInitialAuthState = true
|
||||
|
||||
constructor(provider: ClineProvider) {
|
||||
console.log("Initializing FirebaseAuthManager", { provider })
|
||||
this.providerRef = new WeakRef(provider)
|
||||
|
||||
try {
|
||||
const app = initializeApp(firebaseConfig)
|
||||
this.auth = getAuth(app)
|
||||
console.log("Firebase app initialized", { appConfig: firebaseConfig })
|
||||
|
||||
// Set persistence to LOCAL to maintain auth state across sessions
|
||||
this.setupPersistence()
|
||||
|
||||
// Auth state listener
|
||||
const unsubscribe = onAuthStateChanged(this.auth, this.handleAuthStateChange.bind(this))
|
||||
this.disposables.push({ dispose: () => unsubscribe() })
|
||||
console.log("Auth state change listener added")
|
||||
} catch (error) {
|
||||
console.error("Error initializing FirebaseAuthManager:", error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
private async setupPersistence() {
|
||||
try {
|
||||
await this.retryWithBackoff(async () => {
|
||||
await setPersistence(this.auth, browserLocalPersistence)
|
||||
console.log("Firebase persistence set to LOCAL")
|
||||
})
|
||||
} catch (error) {
|
||||
const authError = this.classifyError(error)
|
||||
console.error("Failed to set persistence after retries:", authError)
|
||||
// Don't throw - persistence failure shouldn't prevent auth initialization
|
||||
// But we should log it clearly for debugging
|
||||
vscode.window.showErrorMessage(
|
||||
"Warning: Failed to set authentication persistence. You may need to log in more frequently.",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private classifyError(error: any): AuthError {
|
||||
console.log("Classifying auth error:", error)
|
||||
|
||||
if (error?.code === "auth/network-request-failed") {
|
||||
return {
|
||||
type: AuthErrorType.Network,
|
||||
message: "Network error during authentication",
|
||||
originalError: error,
|
||||
}
|
||||
}
|
||||
|
||||
// Only consider a token invalid if it's explicitly invalid or malformed
|
||||
if (error?.code === "auth/invalid-custom-token" || error?.code === "auth/argument-error") {
|
||||
return {
|
||||
type: AuthErrorType.InvalidToken,
|
||||
message: "Invalid authentication token format",
|
||||
originalError: error,
|
||||
}
|
||||
}
|
||||
|
||||
// Token mismatch indicates the token might be for a different project/environment
|
||||
if (error?.code === "auth/custom-token-mismatch") {
|
||||
return {
|
||||
type: AuthErrorType.TokenMismatch,
|
||||
message: "Token mismatch - may be for different environment",
|
||||
originalError: error,
|
||||
}
|
||||
}
|
||||
|
||||
// Handle expired tokens separately
|
||||
if (error?.code === "auth/user-token-expired") {
|
||||
return {
|
||||
type: AuthErrorType.ExpiredToken,
|
||||
message: "Authentication token has expired",
|
||||
originalError: error,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: AuthErrorType.Other,
|
||||
message: error?.message || "Unknown authentication error",
|
||||
originalError: error,
|
||||
}
|
||||
}
|
||||
|
||||
private async delay(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms))
|
||||
}
|
||||
|
||||
private async retryWithBackoff<T>(operation: () => Promise<T>, config: RetryConfig = DEFAULT_RETRY_CONFIG): Promise<T> {
|
||||
let lastError: any
|
||||
|
||||
for (let attempt = 1; attempt <= config.maxAttempts; attempt++) {
|
||||
try {
|
||||
console.log(`Attempting operation (attempt ${attempt}/${config.maxAttempts})`)
|
||||
return await operation()
|
||||
} catch (error) {
|
||||
lastError = error
|
||||
const authError = this.classifyError(error)
|
||||
|
||||
// Don't retry for token-related errors
|
||||
if (
|
||||
authError.type === AuthErrorType.InvalidToken ||
|
||||
authError.type === AuthErrorType.TokenMismatch ||
|
||||
authError.type === AuthErrorType.ExpiredToken
|
||||
) {
|
||||
console.log("Token-related error - not retrying:", authError)
|
||||
throw error
|
||||
}
|
||||
|
||||
if (attempt === config.maxAttempts) {
|
||||
console.error(`All ${config.maxAttempts} attempts failed:`, authError)
|
||||
throw error
|
||||
}
|
||||
|
||||
// Calculate delay with exponential backoff
|
||||
const delay = Math.min(config.baseDelay * Math.pow(2, attempt - 1), config.maxDelay)
|
||||
|
||||
console.log(`Attempt ${attempt} failed, retrying in ${delay}ms:`, authError)
|
||||
await this.delay(delay)
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError
|
||||
}
|
||||
|
||||
private async cleanupFailedAuth(provider: ClineProvider, error: AuthError) {
|
||||
console.log("Cleaning up failed authentication state", { errorType: error.type })
|
||||
try {
|
||||
// Clear user info since it's no longer valid
|
||||
await provider.setUserInfo(undefined)
|
||||
console.log("User info cleared")
|
||||
|
||||
// We no longer clear the auth token here - it will only be cleared on explicit user logout
|
||||
// Instead, we just sign out of Firebase if needed
|
||||
if (
|
||||
error.type === AuthErrorType.InvalidToken ||
|
||||
error.type === AuthErrorType.TokenMismatch ||
|
||||
error.type === AuthErrorType.ExpiredToken
|
||||
) {
|
||||
console.log("Auth error detected - signing out but preserving token")
|
||||
await this.signOut()
|
||||
}
|
||||
} catch (cleanupError) {
|
||||
console.error("Error during auth state cleanup:", cleanupError)
|
||||
}
|
||||
}
|
||||
|
||||
private async restoreSession() {
|
||||
console.log("[restoreSession] Attempting to restore session")
|
||||
const provider = this.providerRef.deref()
|
||||
if (!provider) {
|
||||
console.log("[restoreSession] Provider reference lost during session restore")
|
||||
return
|
||||
}
|
||||
|
||||
// Get the auth state from the provider's state, which is loaded when the webview launches
|
||||
const { apiConfiguration } = await provider.getState()
|
||||
const storedToken = apiConfiguration?.authToken
|
||||
console.log("[restoreSession] Auth state from provider:", {
|
||||
hasToken: !!storedToken,
|
||||
hasClineApiKey: !!apiConfiguration?.clineApiKey,
|
||||
})
|
||||
|
||||
if (storedToken && apiConfiguration?.clineApiKey) {
|
||||
console.log("Found stored custom token, attempting to restore session")
|
||||
try {
|
||||
await this.retryWithBackoff(async () => {
|
||||
await this.signInWithCustomToken(storedToken)
|
||||
console.log("Session restored successfully with custom token")
|
||||
})
|
||||
} catch (error) {
|
||||
const authError = this.classifyError(error)
|
||||
console.error("Failed to restore session with custom token:", authError)
|
||||
|
||||
// Clean up Firebase auth state but preserve the token
|
||||
await this.cleanupFailedAuth(provider, authError)
|
||||
|
||||
if (authError.type === AuthErrorType.Network) {
|
||||
// For network errors, throw to allow retry
|
||||
console.log("Network error during session restore - will retry later")
|
||||
throw error
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log("No stored custom token found")
|
||||
}
|
||||
}
|
||||
|
||||
getCurrentUser(): User | null {
|
||||
return this.auth.currentUser
|
||||
}
|
||||
|
||||
private async handleAuthStateChange(user: User | null) {
|
||||
console.log("Auth state changed", {
|
||||
user: user
|
||||
? {
|
||||
uid: user.uid,
|
||||
email: user.email,
|
||||
emailVerified: user.emailVerified,
|
||||
isAnonymous: user.isAnonymous,
|
||||
metadata: user.metadata,
|
||||
}
|
||||
: null,
|
||||
isInitialState: this.isInitialAuthState,
|
||||
})
|
||||
|
||||
const provider = this.providerRef.deref()
|
||||
if (!provider) {
|
||||
console.error("Provider reference lost during auth state change")
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
if (user) {
|
||||
console.log("User signed in", {
|
||||
userId: user.uid,
|
||||
lastLoginAt: user.metadata.lastSignInTime,
|
||||
createdAt: user.metadata.creationTime,
|
||||
})
|
||||
|
||||
// Store public user info in state
|
||||
const userInfo = {
|
||||
displayName: user.displayName,
|
||||
email: user.email,
|
||||
photoURL: user.photoURL,
|
||||
}
|
||||
await provider.setUserInfo(userInfo)
|
||||
console.log("User info set in provider", { userInfo })
|
||||
} else if (!this.isInitialAuthState) {
|
||||
// Only clear user info if this isn't the initial null state
|
||||
console.log("User signed out (not initial state)")
|
||||
await provider.setUserInfo(undefined)
|
||||
} else {
|
||||
console.log("Initial auth state is null, attempting session restore")
|
||||
this.isInitialAuthState = false
|
||||
try {
|
||||
await this.restoreSession()
|
||||
} catch (error) {
|
||||
const authError = this.classifyError(error)
|
||||
if (authError.type === AuthErrorType.Network) {
|
||||
console.log("Session restore failed due to network error - will retry on next auth state change")
|
||||
// Keep isInitialAuthState true so we retry on next change
|
||||
this.isInitialAuthState = true
|
||||
} else {
|
||||
console.error("Session restore failed with non-network error:", authError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await provider.postStateToWebview()
|
||||
console.log("Webview state updated after auth state change")
|
||||
} catch (error) {
|
||||
console.error("Error handling auth state change:", error)
|
||||
// Attempt to clean up state if something went wrong
|
||||
const authError = this.classifyError(error)
|
||||
await this.cleanupFailedAuth(provider, authError)
|
||||
}
|
||||
}
|
||||
|
||||
async signInWithCustomToken(token: string) {
|
||||
console.log("Signing in with custom token")
|
||||
try {
|
||||
await this.retryWithBackoff(async () => {
|
||||
await signInWithCustomToken(this.auth, token)
|
||||
console.log("Successfully signed in with custom token")
|
||||
})
|
||||
} catch (error) {
|
||||
const authError = this.classifyError(error)
|
||||
console.error("Failed to sign in with custom token:", authError)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async signOut() {
|
||||
console.log("Signing out")
|
||||
this.isInitialAuthState = false // Ensure we treat the next null state as a real sign out
|
||||
await signOut(this.auth)
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.disposables.forEach((d) => d.dispose())
|
||||
console.log("Disposables disposed", { count: this.disposables.length })
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ export interface ExtensionMessage {
|
||||
| "vsCodeLmModels"
|
||||
| "requestVsCodeLmModels"
|
||||
| "emailSubscribed"
|
||||
| "authCallback"
|
||||
text?: string
|
||||
action?:
|
||||
| "chatButtonClicked"
|
||||
@@ -46,6 +47,7 @@ export interface ExtensionMessage {
|
||||
openRouterModels?: Record<string, ModelInfo>
|
||||
openAiModels?: string[]
|
||||
mcpServers?: McpServer[]
|
||||
customToken?: string
|
||||
}
|
||||
|
||||
export type Platform = "aix" | "darwin" | "freebsd" | "linux" | "openbsd" | "sunos" | "win32" | "unknown"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export interface UserInfo {
|
||||
displayName: string | null
|
||||
email: string | null
|
||||
photoURL: string | null
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { ApiConfiguration } from "./api"
|
||||
import { AutoApprovalSettings } from "./AutoApprovalSettings"
|
||||
import { BrowserSettings } from "./BrowserSettings"
|
||||
import { ChatSettings } from "./ChatSettings"
|
||||
import { UserInfo } from "./UserInfo"
|
||||
|
||||
export interface WebviewMessage {
|
||||
type:
|
||||
@@ -42,6 +43,8 @@ export interface WebviewMessage {
|
||||
| "accountLoginClicked"
|
||||
| "accountLogoutClicked"
|
||||
| "subscribeEmail"
|
||||
| "authStateChanged"
|
||||
| "authCallback"
|
||||
// | "relaunchChromeDebugMode"
|
||||
text?: string
|
||||
disabled?: boolean
|
||||
@@ -58,6 +61,10 @@ export interface WebviewMessage {
|
||||
serverName?: string
|
||||
toolName?: string
|
||||
autoApprove?: boolean
|
||||
|
||||
// For auth
|
||||
user?: UserInfo | null
|
||||
customToken?: string
|
||||
}
|
||||
|
||||
export type ClineAskResponse = "yesButtonClicked" | "noButtonClicked" | "messageResponse"
|
||||
|
||||
Generated
+758
@@ -11,6 +11,7 @@
|
||||
"@vscode/webview-ui-toolkit": "^1.4.0",
|
||||
"debounce": "^2.1.1",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"firebase": "^11.3.0",
|
||||
"fuse.js": "^7.0.0",
|
||||
"pretty-bytes": "^6.1.1",
|
||||
"react": "^18.3.1",
|
||||
@@ -3001,6 +3002,641 @@
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/analytics": {
|
||||
"version": "0.10.11",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.11.tgz",
|
||||
"integrity": "sha512-zwuPiRE0+hgcS95JZbJ6DFQN4xYFO8IyGxpeePTV51YJMwCf3lkBa6FnZ/iXIqDKcBPMgMuuEZozI0BJWaLEYg==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/installations": "0.6.12",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/analytics-compat": {
|
||||
"version": "0.2.17",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.17.tgz",
|
||||
"integrity": "sha512-SJNVOeTvzdqZQvXFzj7yAirXnYcLDxh57wBFROfeowq/kRN1AqOw1tG6U4OiFOEhqi7s3xLze/LMkZatk2IEww==",
|
||||
"dependencies": {
|
||||
"@firebase/analytics": "0.10.11",
|
||||
"@firebase/analytics-types": "0.8.3",
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/analytics-types": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.3.tgz",
|
||||
"integrity": "sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg=="
|
||||
},
|
||||
"node_modules/@firebase/app": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.11.0.tgz",
|
||||
"integrity": "sha512-FaPl2RB2iClQK4IIAN4ruhzyGNRcvAwXk0Ltqdt55RiTmQ4aM2EAJicgI8QNQd2JIkeCT1K8JKsEba3T1/J7FA==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/util": "1.10.3",
|
||||
"idb": "7.1.1",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/app-check": {
|
||||
"version": "0.8.11",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.11.tgz",
|
||||
"integrity": "sha512-42zIfRI08/7bQqczAy7sY2JqZYEv3a1eNa4fLFdtJ54vNevbBIRSEA3fZgRqWFNHalh5ohsBXdrYgFqaRIuCcQ==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/app-check-compat": {
|
||||
"version": "0.3.18",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.18.tgz",
|
||||
"integrity": "sha512-qjozwnwYmAIdrsVGrJk+hnF1WBois54IhZR6gO0wtZQoTvWL/GtiA2F31TIgAhF0ayUiZhztOv1RfC7YyrZGDQ==",
|
||||
"dependencies": {
|
||||
"@firebase/app-check": "0.8.11",
|
||||
"@firebase/app-check-types": "0.5.3",
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/app-check-interop-types": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz",
|
||||
"integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A=="
|
||||
},
|
||||
"node_modules/@firebase/app-check-types": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.3.tgz",
|
||||
"integrity": "sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng=="
|
||||
},
|
||||
"node_modules/@firebase/app-compat": {
|
||||
"version": "0.2.49",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.49.tgz",
|
||||
"integrity": "sha512-vf838b9WrHs2GH6NfsvA27a3ngDzCnR7oxmc5LJHaJ7mWSCuce1iDRJ2B6raJ6SH9592XXvtW+kzRcPYhC/LoA==",
|
||||
"dependencies": {
|
||||
"@firebase/app": "0.11.0",
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/app-types": {
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz",
|
||||
"integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw=="
|
||||
},
|
||||
"node_modules/@firebase/auth": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.9.0.tgz",
|
||||
"integrity": "sha512-Xz2mbEYauF689qXG/4HppS2+/yGo9R7B6eNUBh3H2+XpAZTGdx8d8TFsW/BMTAK9Q95NB0pb1Bbvfx0lwofq8Q==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x",
|
||||
"@react-native-async-storage/async-storage": "^1.18.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@react-native-async-storage/async-storage": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/auth-compat": {
|
||||
"version": "0.5.18",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.18.tgz",
|
||||
"integrity": "sha512-dFBev8AMNb2AgIt9afwf/Ku4/0Wq9R9OFSeBB/xjyJt+RfQ9PnNWqU2oFphews23byLg6jle8twRA7iOYfRGRw==",
|
||||
"dependencies": {
|
||||
"@firebase/auth": "1.9.0",
|
||||
"@firebase/auth-types": "0.13.0",
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/auth-interop-types": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz",
|
||||
"integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA=="
|
||||
},
|
||||
"node_modules/@firebase/auth-types": {
|
||||
"version": "0.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.13.0.tgz",
|
||||
"integrity": "sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg==",
|
||||
"peerDependencies": {
|
||||
"@firebase/app-types": "0.x",
|
||||
"@firebase/util": "1.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/component": {
|
||||
"version": "0.6.12",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.12.tgz",
|
||||
"integrity": "sha512-YnxqjtohLbnb7raXt2YuA44cC1wA9GiehM/cmxrsoxKlFxBLy2V0OkRSj9gpngAE0UoJ421Wlav9ycO7lTPAUw==",
|
||||
"dependencies": {
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/data-connect": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.3.0.tgz",
|
||||
"integrity": "sha512-inbLq0JyQD/d02Al3Lso0Hc8z1BVpB3dYSMFcQkeKhYyjn5bspLczLdasPbCOEUp8MOkLblLZhJuRs7Q/spFnw==",
|
||||
"dependencies": {
|
||||
"@firebase/auth-interop-types": "0.2.4",
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/database": {
|
||||
"version": "1.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.12.tgz",
|
||||
"integrity": "sha512-psFl5t6rSFHq3i3fnU1QQlc4BB9Hnhh8TgEqvQlPPm8kDLw8gYxvjqYw3c5CZW0+zKR837nwT6im/wtJUivMKw==",
|
||||
"dependencies": {
|
||||
"@firebase/app-check-interop-types": "0.3.3",
|
||||
"@firebase/auth-interop-types": "0.2.4",
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/util": "1.10.3",
|
||||
"faye-websocket": "0.11.4",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/database-compat": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.3.tgz",
|
||||
"integrity": "sha512-uHGQrSUeJvsDfA+IyHW5O4vdRPsCksEzv4T4Jins+bmQgYy20ZESU4x01xrQCn/nzqKHuQMEW99CoCO7D+5NiQ==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/database": "1.0.12",
|
||||
"@firebase/database-types": "1.0.8",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/database-types": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.8.tgz",
|
||||
"integrity": "sha512-6lPWIGeufhUq1heofZULyVvWFhD01TUrkkB9vyhmksjZ4XF7NaivQp9rICMk7QNhqwa+uDCaj4j+Q8qqcSVZ9g==",
|
||||
"dependencies": {
|
||||
"@firebase/app-types": "0.9.3",
|
||||
"@firebase/util": "1.10.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/firestore": {
|
||||
"version": "4.7.7",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.7.tgz",
|
||||
"integrity": "sha512-DDYBjqSyd2vD3SjfRqI2Q9Ua1N0URP+1P0/SnNdVSp0/S5mkbaklIX/eU+199ze0XXnC61RYLqi6KYTYtGoz2A==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/util": "1.10.3",
|
||||
"@firebase/webchannel-wrapper": "1.0.3",
|
||||
"@grpc/grpc-js": "~1.9.0",
|
||||
"@grpc/proto-loader": "^0.7.8",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/firestore-compat": {
|
||||
"version": "0.3.42",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.42.tgz",
|
||||
"integrity": "sha512-L/JqnVw7Bf+2jcCmW1nCiknkIVVM5RIR4rHE1UrtInAvP9vo8pUhFEZVzbwX71SuCoHOwjiaPDvVSeOFachokg==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/firestore": "4.7.7",
|
||||
"@firebase/firestore-types": "3.0.3",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/firestore-types": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.3.tgz",
|
||||
"integrity": "sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==",
|
||||
"peerDependencies": {
|
||||
"@firebase/app-types": "0.x",
|
||||
"@firebase/util": "1.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/functions": {
|
||||
"version": "0.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.12.2.tgz",
|
||||
"integrity": "sha512-iKpFDoCYk/Qm+Qwv5ynRb9/yq64QOt0A0+t9NuekyAZnSoV56kSNq/PmsVmBauar5SlmEjhHk6QKdMBP9S0gXA==",
|
||||
"dependencies": {
|
||||
"@firebase/app-check-interop-types": "0.3.3",
|
||||
"@firebase/auth-interop-types": "0.2.4",
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/messaging-interop-types": "0.2.3",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/functions-compat": {
|
||||
"version": "0.3.19",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.19.tgz",
|
||||
"integrity": "sha512-uw4tR8NcJCDu86UD63Za8A8SgFgmAVFb1XsGlkuBY7gpLyZWEFavWnwRkZ/8cUwpqUhp/SptXFZ1WFJSnOokLw==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/functions": "0.12.2",
|
||||
"@firebase/functions-types": "0.6.3",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/functions-types": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.3.tgz",
|
||||
"integrity": "sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg=="
|
||||
},
|
||||
"node_modules/@firebase/installations": {
|
||||
"version": "0.6.12",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.12.tgz",
|
||||
"integrity": "sha512-ES/WpuAV2k2YtBTvdaknEo7IY8vaGjIjS3zhnHSAIvY9KwTR8XZFXOJoZ3nSkjN1A5R4MtEh+07drnzPDg9vaw==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/util": "1.10.3",
|
||||
"idb": "7.1.1",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/installations-compat": {
|
||||
"version": "0.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.12.tgz",
|
||||
"integrity": "sha512-RhcGknkxmFu92F6Jb3rXxv6a4sytPjJGifRZj8MSURPuv2Xu+/AispCXEfY1ZraobhEHTG5HLGsP6R4l9qB5aA==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/installations": "0.6.12",
|
||||
"@firebase/installations-types": "0.5.3",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/installations-types": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.3.tgz",
|
||||
"integrity": "sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==",
|
||||
"peerDependencies": {
|
||||
"@firebase/app-types": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/logger": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz",
|
||||
"integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/messaging": {
|
||||
"version": "0.12.16",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.16.tgz",
|
||||
"integrity": "sha512-VJ8sCEIeP3+XkfbJA7410WhYGHdloYFZXoHe/vt+vNVDGw8JQPTQSVTRvjrUprEf5I4Tbcnpr2H34lS6zhCHSA==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/installations": "0.6.12",
|
||||
"@firebase/messaging-interop-types": "0.2.3",
|
||||
"@firebase/util": "1.10.3",
|
||||
"idb": "7.1.1",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/messaging-compat": {
|
||||
"version": "0.2.16",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.16.tgz",
|
||||
"integrity": "sha512-9HZZ88Ig3zQ0ok/Pwt4gQcNsOhoEy8hDHoGsV1am6ulgMuGuDVD2gl11Lere2ksL+msM12Lddi2x/7TCqmODZw==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/messaging": "0.12.16",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/messaging-interop-types": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz",
|
||||
"integrity": "sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q=="
|
||||
},
|
||||
"node_modules/@firebase/performance": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.7.0.tgz",
|
||||
"integrity": "sha512-L91PwYuiJdKXKSRqsWNicvTppAJVzKjye03UlegeD6TkpKjb93T8AmJ9B0Mt0bcWHCNtnnRBCdSCvD2U9GZDjw==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/installations": "0.6.12",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0",
|
||||
"web-vitals": "^4.2.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/performance-compat": {
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.13.tgz",
|
||||
"integrity": "sha512-pB0SMQj2TLQ6roDcX0YQDWvUnVgsVOl0VnUvyT/VBdCUuQYDHobZsPEuQsoEqmPA44KS/Gl0oyKqf+I8UPtRgw==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/performance": "0.7.0",
|
||||
"@firebase/performance-types": "0.2.3",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/performance-types": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.3.tgz",
|
||||
"integrity": "sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ=="
|
||||
},
|
||||
"node_modules/@firebase/performance/node_modules/web-vitals": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz",
|
||||
"integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw=="
|
||||
},
|
||||
"node_modules/@firebase/remote-config": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.5.0.tgz",
|
||||
"integrity": "sha512-weiEbpBp5PBJTHUWR4GwI7ZacaAg68BKha5QnZ8Go65W4oQjEWqCW/rfskABI/OkrGijlL3CUmCB/SA6mVo0qA==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/installations": "0.6.12",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/remote-config-compat": {
|
||||
"version": "0.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.12.tgz",
|
||||
"integrity": "sha512-91jLWPtubIuPBngg9SzwvNCWzhMLcyBccmt7TNZP+y1cuYFNOWWHKUXQ3IrxCLB7WwLqQaEu7fTDAjHsTyBsSw==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/remote-config": "0.5.0",
|
||||
"@firebase/remote-config-types": "0.4.0",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/remote-config-types": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.4.0.tgz",
|
||||
"integrity": "sha512-7p3mRE/ldCNYt8fmWMQ/MSGRmXYlJ15Rvs9Rk17t8p0WwZDbeK7eRmoI1tvCPaDzn9Oqh+yD6Lw+sGLsLg4kKg=="
|
||||
},
|
||||
"node_modules/@firebase/storage": {
|
||||
"version": "0.13.6",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.6.tgz",
|
||||
"integrity": "sha512-BEJLYQzVgAoglRl5VRIRZ91RRBZgS/O37/PSGQJBYNuoLmFZUrtwrlLTOAwG776NlO9VQR+K2j15/36Lr2EqHA==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/storage-compat": {
|
||||
"version": "0.3.16",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.16.tgz",
|
||||
"integrity": "sha512-EeMuok/s0r938lEomia8XILEqSYULm7HcYZ/GTZLDWur0kMf2ktuPVZiTdRiwEV3Iki7FtQO5txrQ/0pLRVLAw==",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/storage": "0.13.6",
|
||||
"@firebase/storage-types": "0.8.3",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/storage-types": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.3.tgz",
|
||||
"integrity": "sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==",
|
||||
"peerDependencies": {
|
||||
"@firebase/app-types": "0.x",
|
||||
"@firebase/util": "1.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/util": {
|
||||
"version": "1.10.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.3.tgz",
|
||||
"integrity": "sha512-wfoF5LTy0m2ufUapV0ZnpcGQvuavTbJ5Qr1Ze9OJGL70cSMvhDyjS4w2121XdA3lGZSTOsDOyGhpoDtYwck85A==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/vertexai": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.0.4.tgz",
|
||||
"integrity": "sha512-Nkf/r4u166b4Id6zrrW0Qtg1KyZpQvvYchtkebamnHtIfY+Qnt51I/sx4Saos/WrmO8SnrSU850LfmJ7pehYXg==",
|
||||
"dependencies": {
|
||||
"@firebase/app-check-interop-types": "0.3.3",
|
||||
"@firebase/component": "0.6.12",
|
||||
"@firebase/logger": "0.4.4",
|
||||
"@firebase/util": "1.10.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x",
|
||||
"@firebase/app-types": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/webchannel-wrapper": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz",
|
||||
"integrity": "sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ=="
|
||||
},
|
||||
"node_modules/@grpc/grpc-js": {
|
||||
"version": "1.9.15",
|
||||
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz",
|
||||
"integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==",
|
||||
"dependencies": {
|
||||
"@grpc/proto-loader": "^0.7.8",
|
||||
"@types/node": ">=12.12.47"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^8.13.0 || >=10.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@grpc/proto-loader": {
|
||||
"version": "0.7.13",
|
||||
"resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz",
|
||||
"integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==",
|
||||
"dependencies": {
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"long": "^5.0.0",
|
||||
"protobufjs": "^7.2.5",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"bin": {
|
||||
"proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@grpc/proto-loader/node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@grpc/proto-loader/node_modules/yargs": {
|
||||
"version": "17.7.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
|
||||
"dependencies": {
|
||||
"cliui": "^8.0.1",
|
||||
"escalade": "^3.1.1",
|
||||
"get-caller-file": "^2.0.5",
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.3",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^21.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@grpc/proto-loader/node_modules/yargs-parser": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
|
||||
@@ -3780,6 +4416,60 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@protobufjs/aspromise": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
|
||||
"integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="
|
||||
},
|
||||
"node_modules/@protobufjs/base64": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
|
||||
"integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
|
||||
},
|
||||
"node_modules/@protobufjs/codegen": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
|
||||
"integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
|
||||
},
|
||||
"node_modules/@protobufjs/eventemitter": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
|
||||
"integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="
|
||||
},
|
||||
"node_modules/@protobufjs/fetch": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
|
||||
"integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
|
||||
"dependencies": {
|
||||
"@protobufjs/aspromise": "^1.1.1",
|
||||
"@protobufjs/inquire": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@protobufjs/float": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
|
||||
"integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="
|
||||
},
|
||||
"node_modules/@protobufjs/inquire": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
|
||||
"integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="
|
||||
},
|
||||
"node_modules/@protobufjs/path": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
|
||||
"integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="
|
||||
},
|
||||
"node_modules/@protobufjs/pool": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
|
||||
"integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="
|
||||
},
|
||||
"node_modules/@protobufjs/utf8": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
|
||||
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
|
||||
},
|
||||
"node_modules/@rollup/plugin-babel": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
|
||||
@@ -9458,6 +10148,41 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/firebase": {
|
||||
"version": "11.3.0",
|
||||
"resolved": "https://registry.npmjs.org/firebase/-/firebase-11.3.0.tgz",
|
||||
"integrity": "sha512-wLuBsWqg/M3pay2qOOLLKjTQxPUO2yrJgZLt4TKUwA3c3lrFNM2zc40uzD9LQdUk6H9HEK6bXjGPFrpwmu7HzA==",
|
||||
"dependencies": {
|
||||
"@firebase/analytics": "0.10.11",
|
||||
"@firebase/analytics-compat": "0.2.17",
|
||||
"@firebase/app": "0.11.0",
|
||||
"@firebase/app-check": "0.8.11",
|
||||
"@firebase/app-check-compat": "0.3.18",
|
||||
"@firebase/app-compat": "0.2.49",
|
||||
"@firebase/app-types": "0.9.3",
|
||||
"@firebase/auth": "1.9.0",
|
||||
"@firebase/auth-compat": "0.5.18",
|
||||
"@firebase/data-connect": "0.3.0",
|
||||
"@firebase/database": "1.0.12",
|
||||
"@firebase/database-compat": "2.0.3",
|
||||
"@firebase/firestore": "4.7.7",
|
||||
"@firebase/firestore-compat": "0.3.42",
|
||||
"@firebase/functions": "0.12.2",
|
||||
"@firebase/functions-compat": "0.3.19",
|
||||
"@firebase/installations": "0.6.12",
|
||||
"@firebase/installations-compat": "0.2.12",
|
||||
"@firebase/messaging": "0.12.16",
|
||||
"@firebase/messaging-compat": "0.2.16",
|
||||
"@firebase/performance": "0.7.0",
|
||||
"@firebase/performance-compat": "0.2.13",
|
||||
"@firebase/remote-config": "0.5.0",
|
||||
"@firebase/remote-config-compat": "0.2.12",
|
||||
"@firebase/storage": "0.13.6",
|
||||
"@firebase/storage-compat": "0.3.16",
|
||||
"@firebase/util": "1.10.3",
|
||||
"@firebase/vertexai": "1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/flat-cache": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
|
||||
@@ -12888,6 +13613,11 @@
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
||||
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
|
||||
},
|
||||
"node_modules/lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||
@@ -12918,6 +13648,11 @@
|
||||
"integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/long": {
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-5.2.4.tgz",
|
||||
"integrity": "sha512-qtzLbJE8hq7VabR3mISmVGtoXP8KGc2Z/AT8OuqlYD7JTR3oqrgwdjnk07wpj1twXxYmgDXgoKVWUG/fReSzHg=="
|
||||
},
|
||||
"node_modules/loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
@@ -15644,6 +16379,29 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/protobufjs": {
|
||||
"version": "7.4.0",
|
||||
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz",
|
||||
"integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@protobufjs/aspromise": "^1.1.2",
|
||||
"@protobufjs/base64": "^1.1.2",
|
||||
"@protobufjs/codegen": "^2.0.4",
|
||||
"@protobufjs/eventemitter": "^1.1.0",
|
||||
"@protobufjs/fetch": "^1.1.0",
|
||||
"@protobufjs/float": "^1.0.2",
|
||||
"@protobufjs/inquire": "^1.1.0",
|
||||
"@protobufjs/path": "^1.1.2",
|
||||
"@protobufjs/pool": "^1.1.0",
|
||||
"@protobufjs/utf8": "^1.1.0",
|
||||
"@types/node": ">=13.7.0",
|
||||
"long": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-addr": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"@vscode/webview-ui-toolkit": "^1.4.0",
|
||||
"debounce": "^2.1.1",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"firebase": "^11.3.0",
|
||||
"fuse.js": "^7.0.0",
|
||||
"pretty-bytes": "^6.1.1",
|
||||
"react": "^18.3.1",
|
||||
@@ -53,11 +54,11 @@
|
||||
"@testing-library/jest-dom": "^5.17.0",
|
||||
"@testing-library/react": "^15.0.6",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"@types/vscode-webview": "^1.57.5",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/node": "^20.x",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/vscode-webview": "^1.57.5",
|
||||
"jsdom": "^25.0.1",
|
||||
"vitest": "^2.1.9"
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import SettingsView from "./components/settings/SettingsView"
|
||||
import WelcomeView from "./components/welcome/WelcomeView"
|
||||
import AccountView from "./components/account/AccountView"
|
||||
import { ExtensionStateContextProvider, useExtensionState } from "./context/ExtensionStateContext"
|
||||
import { FirebaseAuthProvider } from "./context/FirebaseAuthContext"
|
||||
import { vscode } from "./utils/vscode"
|
||||
import McpView from "./components/mcp/McpView"
|
||||
|
||||
@@ -103,7 +104,9 @@ const AppContent = () => {
|
||||
const App = () => {
|
||||
return (
|
||||
<ExtensionStateContextProvider>
|
||||
<AppContent />
|
||||
<FirebaseAuthProvider>
|
||||
<AppContent />
|
||||
</FirebaseAuthProvider>
|
||||
</ExtensionStateContextProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import { memo } from "react"
|
||||
import { useExtensionState } from "../../context/ExtensionStateContext"
|
||||
import { useFirebaseAuth } from "../../context/FirebaseAuthContext"
|
||||
import { vscode } from "../../utils/vscode"
|
||||
|
||||
type AccountViewProps = {
|
||||
@@ -8,14 +8,17 @@ type AccountViewProps = {
|
||||
}
|
||||
|
||||
const AccountView = ({ onDone }: AccountViewProps) => {
|
||||
const { isLoggedIn, userInfo } = useExtensionState()
|
||||
const { user, handleSignOut } = useFirebaseAuth()
|
||||
|
||||
const handleLogin = () => {
|
||||
vscode.postMessage({ type: "accountLoginClicked" })
|
||||
}
|
||||
|
||||
const handleLogout = () => {
|
||||
// First notify extension to clear API keys and state
|
||||
vscode.postMessage({ type: "accountLogoutClicked" })
|
||||
// Then sign out of Firebase
|
||||
handleSignOut()
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -51,11 +54,11 @@ const AccountView = ({ onDone }: AccountViewProps) => {
|
||||
flexDirection: "column",
|
||||
}}>
|
||||
<div style={{ marginBottom: 5 }}>
|
||||
{isLoggedIn ? (
|
||||
{user ? (
|
||||
<>
|
||||
{userInfo?.photoURL && (
|
||||
{user.photoURL && (
|
||||
<img
|
||||
src={userInfo.photoURL}
|
||||
src={user.photoURL}
|
||||
alt="Profile"
|
||||
style={{
|
||||
width: 48,
|
||||
@@ -66,8 +69,8 @@ const AccountView = ({ onDone }: AccountViewProps) => {
|
||||
/>
|
||||
)}
|
||||
<div style={{ fontSize: "14px", marginBottom: 10 }}>
|
||||
{userInfo?.displayName && <div>{userInfo.displayName}</div>}
|
||||
{userInfo?.email && <div>{userInfo.email}</div>}
|
||||
{user.displayName && <div>{user.displayName}</div>}
|
||||
{user.email && <div>{user.email}</div>}
|
||||
</div>
|
||||
<VSCodeButton onClick={handleLogout}>Log out</VSCodeButton>
|
||||
</>
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
import { User, getAuth, signInWithCustomToken, signOut } from "firebase/auth"
|
||||
import { initializeApp } from "firebase/app"
|
||||
import React, { createContext, useCallback, useContext, useEffect, useState } from "react"
|
||||
import { vscode } from "../utils/vscode"
|
||||
|
||||
// Firebase configuration from extension
|
||||
const firebaseConfig = {
|
||||
apiKey: "AIzaSyDcXAaanNgR2_T0dq2oOl5XyKPksYHppVo",
|
||||
authDomain: "cline-bot.firebaseapp.com",
|
||||
projectId: "cline-bot",
|
||||
storageBucket: "cline-bot.firebasestorage.app",
|
||||
messagingSenderId: "364369702101",
|
||||
appId: "1:364369702101:web:0013885dcf20b43799c65c",
|
||||
measurementId: "G-MDPRELSCD1",
|
||||
}
|
||||
|
||||
interface FirebaseAuthContextType {
|
||||
user: User | null
|
||||
isInitialized: boolean
|
||||
signInWithToken: (token: string) => Promise<void>
|
||||
handleSignOut: () => Promise<void>
|
||||
}
|
||||
|
||||
const FirebaseAuthContext = createContext<FirebaseAuthContextType | undefined>(undefined)
|
||||
|
||||
export const FirebaseAuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const [user, setUser] = useState<User | null>(null)
|
||||
const [isInitialized, setIsInitialized] = useState(false)
|
||||
|
||||
// Initialize Firebase
|
||||
const app = initializeApp(firebaseConfig)
|
||||
const auth = getAuth(app)
|
||||
|
||||
// Handle auth state changes
|
||||
useEffect(() => {
|
||||
const unsubscribe = auth.onAuthStateChanged((user) => {
|
||||
setUser(user)
|
||||
setIsInitialized(true)
|
||||
|
||||
// Sync auth state with extension
|
||||
vscode.postMessage({
|
||||
type: "authStateChanged",
|
||||
user: user
|
||||
? {
|
||||
displayName: user.displayName,
|
||||
email: user.email,
|
||||
photoURL: user.photoURL,
|
||||
}
|
||||
: null,
|
||||
})
|
||||
})
|
||||
|
||||
return () => unsubscribe()
|
||||
}, [auth])
|
||||
|
||||
// Listen for auth callback from extension
|
||||
useEffect(() => {
|
||||
const handleMessage = (event: MessageEvent) => {
|
||||
const message = event.data
|
||||
if (message.type === "authCallback" && message.customToken) {
|
||||
signInWithToken(message.customToken)
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("message", handleMessage)
|
||||
return () => window.removeEventListener("message", handleMessage)
|
||||
}, [])
|
||||
|
||||
const signInWithToken = useCallback(
|
||||
async (token: string) => {
|
||||
try {
|
||||
await signInWithCustomToken(auth, token)
|
||||
console.log("Successfully signed in with custom token")
|
||||
} catch (error) {
|
||||
console.error("Error signing in with custom token:", error)
|
||||
throw error
|
||||
}
|
||||
},
|
||||
[auth],
|
||||
)
|
||||
|
||||
const handleSignOut = useCallback(async () => {
|
||||
try {
|
||||
await signOut(auth)
|
||||
console.log("Successfully signed out of Firebase")
|
||||
} catch (error) {
|
||||
console.error("Error signing out of Firebase:", error)
|
||||
throw error
|
||||
}
|
||||
}, [auth])
|
||||
|
||||
return (
|
||||
<FirebaseAuthContext.Provider value={{ user, isInitialized, signInWithToken, handleSignOut }}>
|
||||
{children}
|
||||
</FirebaseAuthContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useFirebaseAuth = () => {
|
||||
const context = useContext(FirebaseAuthContext)
|
||||
if (context === undefined) {
|
||||
throw new Error("useFirebaseAuth must be used within a FirebaseAuthProvider")
|
||||
}
|
||||
return context
|
||||
}
|
||||
Reference in New Issue
Block a user