fix: authentication issues when using multiple tabs (@fehmer) (#6790)

fixes #6279

- store the last use "remember login" state in localstorage
- initialize firebase auth with correct persistence (LOCAL if "remember
me" is set, SESSION otherwise)


initialization of `Auth` needs to by awaited. This required some
refactoring. During debugging it was useful to have easier control over
the `Auth` object.

Summary of the refactoring:

- don't expose firebase `App` or `Auth` (except for email-handler)
- initialise firebase in async method that can be awaited to ensure
setup is done before any call to firebase
- move `authStateChanged` handling from account-controller to our
firebase module which then calls `account-controller.readyFunction`.
- update all direct calls to `Auth` to use functions of our firebase
module
- move error handling and interpretation of `FirebaseError` to our
module and removed duplicate code
- use tryCatch helper on refactored code instead of native `try...
catch`

---------

Co-authored-by: Miodec <jack@monkeytype.com>
Co-authored-by: Lukas <dev@mardybum.de>
Co-authored-by: Seif Soliman <byseif21@gmail.com>
This commit is contained in:
Christian Fehmer 2025-08-11 13:11:51 +02:00 committed by GitHub
parent 541f29ce94
commit e838f71c78
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 729 additions and 519 deletions

View file

@ -95,7 +95,7 @@
"color-blend": "4.0.0",
"damerau-levenshtein": "1.0.8",
"date-fns": "3.6.0",
"firebase": "10.12.4",
"firebase": "12.0.0",
"hangul-js": "0.2.6",
"howler": "2.2.3",
"html2canvas": "1.4.1",

View file

@ -166,7 +166,7 @@
</body>
<script type="module">
import $ from "jquery";
import { Auth } from "./ts/firebase";
import { _Auth as Auth } from "./ts/firebase";
import {
applyActionCode,
verifyPasswordResetCode,

View file

@ -4,9 +4,8 @@ import {
tsRestFetchApi,
type ApiFetcherArgs,
} from "@ts-rest/core";
import { getIdToken } from "firebase/auth";
import { envConfig } from "../../constants/env-config";
import { getAuthenticatedUser, isAuthenticated } from "../../firebase";
import { getIdToken } from "../../firebase";
import {
COMPATIBILITY_CHECK,
COMPATIBILITY_CHECK_HEADER,
@ -30,8 +29,8 @@ function buildApi(timeout: number): (args: ApiFetcherArgs) => Promise<{
}> {
return async (request: ApiFetcherArgs) => {
try {
if (isAuthenticated()) {
const token = await getIdToken(getAuthenticatedUser());
const token = await getIdToken();
if (token !== null) {
request.headers["Authorization"] = `Bearer ${token}`;
}

View file

@ -22,38 +22,38 @@ import * as AccountSettings from "../pages/account-settings";
import {
GoogleAuthProvider,
GithubAuthProvider,
browserSessionPersistence,
browserLocalPersistence,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signInWithPopup,
setPersistence,
updateProfile,
linkWithPopup,
getAdditionalUserInfo,
User as UserType,
Unsubscribe,
AuthProvider,
} from "firebase/auth";
import { Auth, getAuthenticatedUser, isAuthenticated } from "../firebase";
import { dispatch as dispatchSignUpEvent } from "../observables/google-sign-up-event";
import {
isAuthAvailable,
getAuthenticatedUser,
isAuthenticated,
signOut as authSignOut,
signInWithEmailAndPassword,
createUserWithEmailAndPassword,
signInWithPopup,
resetIgnoreAuthCallback,
} from "../firebase";
import {
hideFavoriteQuoteLength,
showFavoriteQuoteLength,
} from "../test/test-config";
import * as ConnectionState from "../states/connection";
import { navigate } from "./route-controller";
import { FirebaseError } from "firebase/app";
import * as PSA from "../elements/psa";
import { getActiveFunboxesWithFunction } from "../test/funbox/list";
import { Snapshot } from "../constants/default-snapshot";
import * as Sentry from "../sentry";
import { tryCatch } from "@monkeytype/util/trycatch";
export const gmailProvider = new GoogleAuthProvider();
export const githubProvider = new GithubAuthProvider();
async function sendVerificationEmail(): Promise<void> {
if (Auth === undefined) {
if (!isAuthAvailable()) {
Notifications.add("Authentication uninitialized", -1, {
duration: 3,
});
@ -200,7 +200,7 @@ export async function loadUser(_user: UserType): Promise<void> {
}
}
async function readyFunction(
export async function onAuthStateChanged(
authInitialisedAndConnected: boolean,
user: UserType | null
): Promise<void> {
@ -217,10 +217,14 @@ async function readyFunction(
if (window.location.pathname === "/account") {
window.history.replaceState("", "", "/login");
}
Settings.hideAccountSection();
AccountButton.update(undefined);
DB.setSnapshot(undefined);
Sentry.clearUser();
setTimeout(() => {
hideFavoriteQuoteLength();
}, 125);
PageTransition.set(false);
navigate();
}
@ -242,20 +246,8 @@ async function readyFunction(
AccountSettings.updateUI();
}
let disableAuthListener: Unsubscribe;
if (Auth && ConnectionState.get()) {
disableAuthListener = Auth?.onAuthStateChanged(function (user) {
void readyFunction(true, user);
});
} else {
$((): void => {
void readyFunction(false, null);
});
}
export async function signIn(email: string, password: string): Promise<void> {
if (Auth === undefined) {
if (!isAuthAvailable()) {
Notifications.add("Authentication uninitialized", -1);
return;
}
@ -266,7 +258,6 @@ export async function signIn(email: string, password: string): Promise<void> {
return;
}
disableAuthListener();
LoginPage.showPreloader();
LoginPage.disableInputs();
LoginPage.disableSignUpButton();
@ -279,45 +270,25 @@ export async function signIn(email: string, password: string): Promise<void> {
return;
}
const persistence = ($(".pageLogin .login #rememberMe input").prop(
const rememberMe = $(".pageLogin .login #rememberMe input").prop(
"checked"
) as boolean)
? browserLocalPersistence
: browserSessionPersistence;
) as boolean;
await setPersistence(Auth, persistence);
return signInWithEmailAndPassword(Auth, email, password)
.then(async (e) => {
await loadUser(e.user);
})
.catch(function (error: unknown) {
console.error(error);
let message = Misc.createErrorMessage(
error,
"Failed to sign in with email and password"
);
if (error instanceof FirebaseError) {
if (error.code === "auth/wrong-password") {
message = "Incorrect password";
} else if (error.code === "auth/user-not-found") {
message = "User not found";
} else if (error.code === "auth/invalid-email") {
message =
"Invalid email format (make sure you are using your email to login - not your username)";
} else if (error.code === "auth/invalid-credential") {
message =
"Email/password is incorrect or your account does not have password authentication enabled.";
}
}
Notifications.add(message, -1);
LoginPage.hidePreloader();
LoginPage.enableInputs();
LoginPage.updateSignupButton();
});
const { error } = await tryCatch(
signInWithEmailAndPassword(email, password, rememberMe)
);
if (error !== null) {
Notifications.add(error.message, -1);
LoginPage.hidePreloader();
LoginPage.enableInputs();
LoginPage.updateSignupButton();
return;
}
}
async function signInWithProvider(provider: AuthProvider): Promise<void> {
if (Auth === undefined) {
if (!isAuthAvailable()) {
Notifications.add("Authentication uninitialized", -1, {
duration: 3,
});
@ -333,61 +304,21 @@ async function signInWithProvider(provider: AuthProvider): Promise<void> {
LoginPage.showPreloader();
LoginPage.disableInputs();
LoginPage.disableSignUpButton();
disableAuthListener();
const persistence = ($(".pageLogin .login #rememberMe input").prop(
const rememberMe = $(".pageLogin .login #rememberMe input").prop(
"checked"
) as boolean)
? browserLocalPersistence
: browserSessionPersistence;
) as boolean;
await setPersistence(Auth, persistence);
signInWithPopup(Auth, provider)
.then(async (signedInUser) => {
if (getAdditionalUserInfo(signedInUser)?.isNewUser) {
dispatchSignUpEvent(signedInUser, true);
} else {
await loadUser(signedInUser.user);
}
})
.catch((error: unknown) => {
console.log(error);
let message = Misc.createErrorMessage(
error,
"Failed to sign in with popup"
);
if (error instanceof FirebaseError) {
if (error.code === "auth/wrong-password") {
message = "Incorrect password";
} else if (error.code === "auth/user-not-found") {
message = "User not found";
} else if (error.code === "auth/invalid-email") {
message =
"Invalid email format (make sure you are using your email to login - not your username)";
} else if (error.code === "auth/popup-closed-by-user") {
message = "";
// message = "Popup closed by user";
// return;
} else if (error.code === "auth/popup-blocked") {
message =
"Sign in popup was blocked by the browser. Check the address bar for a blocked popup icon, or update your browser settings to allow popups.";
} else if (error.code === "auth/user-cancelled") {
message = "";
// message = "User refused to sign in";
// return;
} else if (
error.code === "auth/account-exists-with-different-credential"
) {
message =
"Account already exists, but its using a different authentication method. Try signing in with a different method";
}
}
if (message !== "") {
Notifications.add(message, -1);
}
LoginPage.hidePreloader();
LoginPage.enableInputs();
LoginPage.updateSignupButton();
});
const { error } = await tryCatch(signInWithPopup(provider, rememberMe));
if (error !== null) {
if (error.message !== "") {
Notifications.add(error.message, -1);
}
LoginPage.hidePreloader();
LoginPage.enableInputs();
LoginPage.updateSignupButton();
return;
}
}
async function signInWithGoogle(): Promise<void> {
@ -416,60 +347,43 @@ async function addAuthProvider(
});
return;
}
if (Auth === undefined) {
if (!isAuthAvailable()) {
Notifications.add("Authentication uninitialized", -1, {
duration: 3,
});
return;
}
Loader.show();
if (!isAuthenticated()) return;
linkWithPopup(getAuthenticatedUser(), provider)
.then(function () {
Loader.hide();
Notifications.add(`${providerName} authentication added`, 1);
AccountSettings.updateUI();
})
.catch(function (error: unknown) {
Loader.hide();
const message = Misc.createErrorMessage(
error,
`Failed to add ${providerName} authentication`
);
Notifications.add(message, -1);
});
const user = getAuthenticatedUser();
if (!user) return;
try {
await linkWithPopup(user, provider);
Loader.hide();
Notifications.add(`${providerName} authentication added`, 1);
AccountSettings.updateUI();
} catch (error) {
Loader.hide();
const message = Misc.createErrorMessage(
error,
`Failed to add ${providerName} authentication`
);
Notifications.add(message, -1);
}
}
export function signOut(): void {
if (Auth === undefined) {
if (!isAuthAvailable()) {
Notifications.add("Authentication uninitialized", -1, {
duration: 3,
});
return;
}
if (!isAuthenticated()) return;
Auth.signOut()
.then(function () {
Notifications.add("Signed out", 0, {
duration: 2,
});
Sentry.clearUser();
Settings.hideAccountSection();
AccountButton.update(undefined);
navigate("/login");
DB.setSnapshot(undefined);
setTimeout(() => {
hideFavoriteQuoteLength();
}, 125);
})
.catch(function (error: unknown) {
const message = Misc.createErrorMessage(error, `Failed to sign out`);
Notifications.add(message, -1);
});
void authSignOut();
}
async function signUp(): Promise<void> {
if (Auth === undefined) {
if (!isAuthAvailable()) {
Notifications.add("Authentication uninitialized", -1, {
duration: 3,
});
@ -551,11 +465,8 @@ async function signUp(): Promise<void> {
return;
}
disableAuthListener();
try {
const createdAuthUser = await createUserWithEmailAndPassword(
Auth,
email,
password
);
@ -575,7 +486,8 @@ async function signUp(): Promise<void> {
await updateProfile(createdAuthUser.user, { displayName: nname });
await sendVerificationEmail();
LoginPage.hidePreloader();
await loadUser(createdAuthUser.user);
await onAuthStateChanged(true, createdAuthUser.user);
resetIgnoreAuthCallback();
Notifications.add("Account created", 1);
} catch (e) {
@ -617,7 +529,7 @@ $(".pageLogin .login button.signInWithGitHub").on("click", () => {
});
$("nav .accountButtonAndMenu .menu button.signOut").on("click", () => {
if (Auth === undefined) {
if (!isAuthAvailable()) {
Notifications.add("Authentication uninitialized", -1, {
duration: 3,
});

View file

@ -1,10 +1,9 @@
import {
Analytics as AnalyticsType,
getAnalytics,
logEvent,
setAnalyticsCollectionEnabled,
} from "firebase/analytics";
import { app as firebaseApp } from "../firebase";
import { getAnalytics } from "../firebase";
import { createErrorMessage } from "../utils/misc";
let analytics: AnalyticsType;
@ -27,7 +26,7 @@ export function activateAnalytics(): void {
}
console.log("Activating Analytics");
try {
analytics = getAnalytics(firebaseApp);
analytics = getAnalytics();
setAnalyticsCollectionEnabled(analytics, true);
$("body").append(`
<script

View file

@ -1,7 +1,7 @@
import * as PageController from "./page-controller";
import * as TestUI from "../test/test-ui";
import * as PageTransition from "../states/page-transition";
import { Auth, isAuthenticated } from "../firebase";
import { isAuthAvailable, isAuthenticated } from "../firebase";
import { isFunboxActive } from "../test/funbox/list";
import * as TestState from "../test/test-state";
import * as Notifications from "../elements/notifications";
@ -83,10 +83,11 @@ const routes: Route[] = [
{
path: "/login",
load: (): void => {
if (!Auth) {
if (!isAuthAvailable()) {
navigate("/");
return;
}
if (isAuthenticated()) {
navigate("/account");
return;
@ -97,10 +98,11 @@ const routes: Route[] = [
{
path: "/account",
load: (_params, options): void => {
if (!Auth) {
if (!isAuthAvailable()) {
navigate("/");
return;
}
void PageController.change("account", {
data: options.data,
});
@ -109,10 +111,11 @@ const routes: Route[] = [
{
path: "/account-settings",
load: (_params, options): void => {
if (!Auth) {
if (!isAuthAvailable()) {
navigate("/");
return;
}
if (!isAuthenticated()) {
navigate("/login");
return;

View file

@ -14,7 +14,7 @@ import Format from "../utils/format";
import { UserProfile, RankAndCount } from "@monkeytype/schemas/users";
import { abbreviateNumber, convertRemToPixels } from "../utils/numbers";
import { secondsToString } from "../utils/date-and-time";
import { Auth } from "../firebase";
import { getAuthenticatedUser } from "../firebase";
import { Snapshot } from "../constants/default-snapshot";
import { getAvatarElement } from "../utils/discord-avatar";
@ -320,7 +320,7 @@ export async function update(
}
}
if (profile.uid === Auth?.currentUser?.uid) {
if (profile.uid === getAuthenticatedUser()?.uid) {
profileElement.find(".userReportButton").addClass("hidden");
} else {
profileElement.find(".userReportButton").removeClass("hidden");

View file

@ -1,45 +1,242 @@
// Import the functions you need from the SDKs you need
import { FirebaseApp, initializeApp } from "firebase/app";
import { getAuth, Auth as AuthType, User } from "firebase/auth";
// eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
// oxlint-disable ban-ts-comment
// @ts-ignore as far as i remember this is for CI
// eslint-disable-next-line import/no-unresolved
import {
FirebaseApp,
FirebaseError,
getApp,
getApps,
initializeApp,
} from "firebase/app";
import {
getAuth,
Auth as AuthType,
User,
setPersistence as firebaseSetPersistence,
browserSessionPersistence,
signInWithEmailAndPassword as firebaseSignInWithEmailAndPassword,
signInWithPopup as firebaseSignInWithPopup,
createUserWithEmailAndPassword as firebaseCreateUserWithEmailAndPassword,
getIdToken as firebaseGetIdToken,
UserCredential,
AuthProvider,
onAuthStateChanged,
indexedDBLocalPersistence,
getAdditionalUserInfo,
} from "firebase/auth";
import { firebaseConfig } from "./constants/firebase-config";
import * as Notifications from "./elements/notifications";
import { createErrorMessage, isDevEnvironment } from "./utils/misc";
import {
createErrorMessage,
isDevEnvironment,
promiseWithResolvers,
} from "./utils/misc";
// Initialize Firebase
export let app: FirebaseApp | undefined;
export let Auth: AuthType | undefined;
import {
Analytics as AnalyticsType,
getAnalytics as firebaseGetAnalytics,
} from "firebase/analytics";
import { tryCatch } from "@monkeytype/util/trycatch";
import { dispatch as dispatchSignUpEvent } from "./observables/google-sign-up-event";
let app: FirebaseApp | undefined;
let Auth: AuthType | undefined;
/**
* ignore auth callback. This is used during signup with google/github where we need to create the user on the backend first.
*/
let ignoreAuthCallback: boolean = false;
type ReadyCallback = (success: boolean, user: User | null) => Promise<void>;
let readyCallback: ReadyCallback | undefined;
const { promise: authPromise, resolve: resolveAuthPromise } =
promiseWithResolvers();
export async function init(callback: ReadyCallback): Promise<void> {
try {
readyCallback = callback;
app = getApps().length === 0 ? initializeApp(firebaseConfig) : getApp();
Auth = getAuth(app);
const rememberMe =
window.localStorage.getItem("firebasePersistence") === "LOCAL";
await setPersistence(rememberMe, false);
onAuthStateChanged(Auth, async (user) => {
if (!ignoreAuthCallback) {
await callback(true, user);
}
});
resolveAuthPromise();
} catch (e) {
app = undefined;
Auth = undefined;
console.error("Authentication failed to initialize", e);
await callback(false, null);
if (isDevEnvironment()) {
Notifications.addPSA(
createErrorMessage(e, "Authentication uninitialized") +
" Check your firebase-config.ts",
0,
undefined,
false
);
}
}
}
export function isAuthenticated(): boolean {
return Auth?.currentUser !== undefined && Auth?.currentUser !== null;
}
export function getAuthenticatedUser(): User {
const user = Auth?.currentUser;
if (user === undefined || user === null)
throw new Error(
"User authentication is required but no user is logged in."
);
return user;
/**
*
* @returns the current user if authenticated, else `null`
*/
export function getAuthenticatedUser(): User | null {
return Auth?.currentUser ?? null;
}
try {
app = initializeApp(firebaseConfig);
Auth = getAuth(app);
} catch (e) {
app = undefined;
Auth = undefined;
console.error("Authentication failed to initialize", e);
if (isDevEnvironment()) {
Notifications.addPSA(
createErrorMessage(e, "Authentication uninitialized") +
" Check your firebase-config.ts",
0,
undefined,
false
export function getAnalytics(): AnalyticsType {
return firebaseGetAnalytics(app);
}
export function isAuthAvailable(): boolean {
return Auth !== undefined;
}
export async function signOut(): Promise<void> {
console.log("auth signout");
await Auth?.signOut();
}
export async function signInWithEmailAndPassword(
email: string,
password: string,
rememberMe: boolean
): Promise<UserCredential> {
if (Auth === undefined) throw new Error("Authentication uninitialized");
await setPersistence(rememberMe, true);
const { data: result, error } = await tryCatch(
firebaseSignInWithEmailAndPassword(Auth, email, password)
);
if (error !== null) {
console.error(error);
throw translateFirebaseError(
error,
"Failed to sign in with email and password"
);
}
return result;
}
export async function signInWithPopup(
provider: AuthProvider,
rememberMe: boolean
): Promise<void> {
if (Auth === undefined) throw new Error("Authentication uninitialized");
await setPersistence(rememberMe, true);
ignoreAuthCallback = true;
const { data: signedInUser, error } = await tryCatch(
firebaseSignInWithPopup(Auth, provider)
);
if (error !== null) {
ignoreAuthCallback = false;
console.log(error);
throw translateFirebaseError(error, "Failed to sign in with popup");
}
const additionalUserInfo = getAdditionalUserInfo(signedInUser);
if (additionalUserInfo?.isNewUser) {
dispatchSignUpEvent(signedInUser, true);
} else {
ignoreAuthCallback = false;
await readyCallback?.(true, signedInUser.user);
}
}
export async function createUserWithEmailAndPassword(
email: string,
password: string
): Promise<UserCredential> {
if (Auth === undefined) throw new Error("Authentication uninitialized");
ignoreAuthCallback = true;
const result = await firebaseCreateUserWithEmailAndPassword(
Auth,
email,
password
);
return result;
}
export async function getIdToken(): Promise<string | null> {
const user = await getAuthenticatedUser();
if (user === null) return null;
return firebaseGetIdToken(user);
}
async function setPersistence(
rememberMe: boolean,
store = false
): Promise<void> {
if (Auth === undefined) throw new Error("Authentication uninitialized");
const persistence = rememberMe
? indexedDBLocalPersistence
: browserSessionPersistence;
if (store) {
window.localStorage.setItem(
"firebasePersistence",
rememberMe ? "LOCAL" : "SESSION"
);
}
await firebaseSetPersistence(Auth, persistence);
}
function translateFirebaseError(
error: Error | FirebaseError,
defaultMessage: string
): Error {
let message = createErrorMessage(error, defaultMessage);
if (error instanceof FirebaseError) {
if (error.code === "auth/wrong-password") {
message = "Incorrect password";
} else if (error.code === "auth/user-not-found") {
message = "User not found";
} else if (error.code === "auth/invalid-email") {
message =
"Invalid email format (make sure you are using your email to login - not your username)";
} else if (error.code === "auth/invalid-credential") {
message =
"Email/password is incorrect or your account does not have password authentication enabled.";
} else if (error.code === "auth/popup-closed-by-user") {
message = "";
// message = "Popup closed by user";
// return;
} else if (error.code === "auth/popup-blocked") {
message =
"Sign in popup was blocked by the browser. Check the address bar for a blocked popup icon, or update your browser settings to allow popups.";
} else if (error.code === "auth/user-cancelled") {
message = "";
// message = "User refused to sign in";
// return;
} else if (error.code === "auth/account-exists-with-different-credential") {
message =
"Account already exists, but its using a different authentication method. Try signing in with a different method";
}
}
return new Error(message, { cause: error });
}
export function resetIgnoreAuthCallback(): void {
ignoreAuthCallback = false;
}
export { authPromise };
//TODO refactor email-handler
export const _Auth = Auth;

View file

@ -14,7 +14,7 @@ import "./event-handlers/login";
import "./modals/google-sign-up";
import "./firebase";
import { init } from "./firebase";
import * as Logger from "./utils/logger";
import * as DB from "./db";
import "./ui";
@ -25,7 +25,7 @@ import * as TestStats from "./test/test-stats";
import * as Replay from "./test/replay";
import * as TestTimer from "./test/test-timer";
import * as Result from "./test/result";
import "./controllers/account-controller";
import { onAuthStateChanged } from "./controllers/account-controller";
import { enable } from "./states/glarses-mode";
import "./test/caps-warning";
import "./modals/simple-modals";
@ -78,6 +78,7 @@ function addToGlobal(items: Record<string, unknown>): void {
void loadFromLocalStorage();
void VersionButton.update();
Focus.set(true, true);
void init(onAuthStateChanged);
const accepted = Cookies.getAcceptedCookies();
if (accepted === null) {

View file

@ -15,6 +15,7 @@ import * as Loader from "../elements/loader";
import { subscribe as subscribeToSignUpEvent } from "../observables/google-sign-up-event";
import { InputIndicator } from "../elements/input-indicator";
import AnimatedModal from "../utils/animated-modal";
import { resetIgnoreAuthCallback } from "../firebase";
let signedInUser: UserCredential | undefined = undefined;
@ -51,6 +52,7 @@ function show(credential: UserCredential): void {
async function hide(): Promise<void> {
void modal.hide({
afterAnimation: async () => {
resetIgnoreAuthCallback();
if (signedInUser !== undefined) {
Notifications.add("Sign up process cancelled", 0, {
duration: 5,

View file

@ -3,7 +3,7 @@ import AnimatedModal from "../utils/animated-modal";
import * as TestLogic from "../test/test-logic";
import * as Notifications from "../elements/notifications";
import { CompletedEvent } from "@monkeytype/schemas/results";
import { Auth } from "../firebase";
import { getAuthenticatedUser } from "../firebase";
import { syncNotSignedInLastResult } from "../utils/results";
function reset(): void {
@ -99,9 +99,10 @@ export function show(): void {
);
return;
}
reset();
void modal.show({
beforeAnimation: async (): Promise<void> => {
reset();
fillData();
},
});
@ -117,7 +118,10 @@ const modal = new AnimatedModal({
modalEl
.querySelector("button.save")
?.addEventListener("click", async () => {
void syncNotSignedInLastResult(Auth?.currentUser?.uid as string);
const user = getAuthenticatedUser();
if (user !== null) {
void syncNotSignedInLastResult(user.uid);
}
hide();
});
modalEl.querySelector("button.discard")?.addEventListener("click", () => {

View file

@ -8,7 +8,11 @@ import * as ThemePicker from "../elements/settings/theme-picker";
import * as CustomText from "../test/custom-text";
import * as AccountButton from "../elements/account-button";
import { FirebaseError } from "firebase/app";
import { Auth, isAuthenticated, getAuthenticatedUser } from "../firebase";
import {
isAuthenticated,
getAuthenticatedUser,
isAuthAvailable,
} from "../firebase";
import {
EmailAuthProvider,
User,
@ -133,7 +137,7 @@ function isUsingGoogleAuthentication(): boolean {
function isUsingAuthentication(authProvider: AuthMethod): boolean {
return (
Auth?.currentUser?.providerData.some(
getAuthenticatedUser()?.providerData.some(
(p) => p.providerId === authProvider
) || false
);
@ -142,20 +146,21 @@ function isUsingAuthentication(authProvider: AuthMethod): boolean {
async function reauthenticate(
options: ReauthenticateOptions
): Promise<ReauthSuccess | ReauthFailed> {
if (Auth === undefined) {
if (!isAuthAvailable()) {
return {
status: -1,
message: "Authentication is not initialized",
};
}
if (!isAuthenticated()) {
const user = getAuthenticatedUser();
if (user === null) {
return {
status: -1,
message: "User is not signed in",
};
}
const user = getAuthenticatedUser();
const authMethod = getPreferredAuthenticationMethod(options.excludeMethod);
try {

View file

@ -29,8 +29,8 @@ function updateAuthenticationSections(): void {
pageElement.find(".section.googleAuthSettings button").addClass("hidden");
pageElement.find(".section.githubAuthSettings button").addClass("hidden");
if (!isAuthenticated()) return;
const user = getAuthenticatedUser();
if (user === null) return;
const passwordProvider = user.providerData.some(
(provider) => provider.providerId === "password"

View file

@ -22,7 +22,7 @@ import * as Skeleton from "../utils/skeleton";
import type { ScaleChartOptions, LinearScaleOptions } from "chart.js";
import * as ConfigEvent from "../observables/config-event";
import * as ActivePage from "../states/active-page";
import { Auth } from "../firebase";
import { getAuthenticatedUser } from "../firebase";
import * as Loader from "../elements/loader";
import * as ResultBatches from "../elements/result-batches";
import Format from "../utils/format";
@ -1370,7 +1370,7 @@ export const page = new Page({
void update().then(() => {
void updateChartColors();
$(".pageAccount .content .accountVerificatinNotice").remove();
if (Auth?.currentUser?.emailVerified === false) {
if (getAuthenticatedUser()?.emailVerified === false) {
$(".pageAccount .content").prepend(
`<div class="accountVerificatinNotice"><i class="fas icon fa-exclamation-triangle"></i><p>Your email address is still not verified</p><button class="sendVerificationEmail">resend verification email</button></div>`
);

View file

@ -9,7 +9,7 @@ import { capitalizeFirstLetter } from "../utils/strings";
import Ape from "../ape";
import * as Notifications from "../elements/notifications";
import Format from "../utils/format";
import { Auth, isAuthenticated } from "../firebase";
import { getAuthenticatedUser, isAuthenticated } from "../firebase";
import * as DB from "../db";
import {
endOfDay,
@ -549,12 +549,12 @@ function fillTable(): void {
if (state.type === "allTime" || state.type === "daily") {
for (const entry of state.data) {
const me = Auth?.currentUser?.uid === entry.uid;
const me = getAuthenticatedUser()?.uid === entry.uid;
table.append(buildTableRow(entry, me));
}
} else if (state.type === "weekly") {
for (const entry of state.data) {
const me = Auth?.currentUser?.uid === entry.uid;
const me = getAuthenticatedUser()?.uid === entry.uid;
table.append(buildWeeklyTableRow(entry, me));
}
}
@ -1187,20 +1187,17 @@ function handleJumpButton(action: Action, page?: number): void {
state.page = page;
} else if (action === "userPage") {
if (isAuthenticated()) {
const user = Auth?.currentUser;
if (user) {
const rank = state.userData?.rank;
if (isSafeNumber(rank)) {
// - 1 to make sure position 50 with page size 50 is on the first page (page 0)
const page = Math.floor((rank - 1) / state.pageSize);
const rank = state.userData?.rank;
if (isSafeNumber(rank)) {
// - 1 to make sure position 50 with page size 50 is on the first page (page 0)
const page = Math.floor((rank - 1) / state.pageSize);
if (state.page === page) {
return;
}
state.page = page;
state.scrollToUserAfterFill = true;
if (state.page === page) {
return;
}
state.page = page;
state.scrollToUserAfterFill = true;
}
}
} else {

View file

@ -8,9 +8,11 @@ import Konami from "konami";
import * as ServerConfiguration from "./ape/server-configuration";
import { getActiveFunboxesWithFunction } from "./test/funbox/list";
import { loadPromise } from "./config";
import { authPromise } from "./firebase";
$(async (): Promise<void> => {
await loadPromise;
await authPromise;
//this line goes back to pretty much the beginning of the project and im pretty sure its here
//to make sure the initial theme application doesnt animate the background color

View file

@ -49,7 +49,7 @@ import * as Last10Average from "../elements/last-10-average";
import * as Monkey from "./monkey";
import objectHash from "object-hash";
import * as AnalyticsController from "../controllers/analytics-controller";
import { Auth, isAuthenticated } from "../firebase";
import { getAuthenticatedUser, isAuthenticated } from "../firebase";
import * as AdController from "../controllers/ad-controller";
import * as TestConfig from "./test-config";
import * as ConnectionState from "../states/connection";
@ -1188,10 +1188,18 @@ export async function finish(difficultyFailed = false): Promise<void> {
return;
}
// because of the dont save check above, we know the user is signed in
// we check here again so that typescript doesnt complain
const user = getAuthenticatedUser();
if (!user) {
return;
}
// user is logged in
TestStats.resetIncomplete();
completedEvent.uid = Auth?.currentUser?.uid as string;
completedEvent.uid = user.uid;
Result.updateRateQuote(TestWords.currentQuote);
AccountButton.loading(true);

655
pnpm-lock.yaml generated
View file

@ -310,8 +310,8 @@ importers:
specifier: 3.6.0
version: 3.6.0
firebase:
specifier: 10.12.4
version: 10.12.4
specifier: 12.0.0
version: 12.0.0
hangul-js:
specifier: 0.2.6
version: 0.2.6
@ -1727,67 +1727,85 @@ packages:
resolution: {integrity: sha512-7PQA7EH43S0CxcOa9OeAnaeA0oQ+e/DHNPZwSQM9CQHW76jle5+OvLdibRp/Aafs9KXbLhxyjOTkRjWUbQEd3Q==}
engines: {node: '>=14'}
'@fastify/busboy@2.1.1':
resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
engines: {node: '>=14'}
'@fastify/error@2.0.0':
resolution: {integrity: sha512-wI3fpfDT0t7p8E6dA2eTECzzOd+bZsZCJ2Hcv+Onn2b7ZwK3RwD27uW2QDaMtQhAfWQQP+WNK7nKf0twLsBf9w==}
'@firebase/analytics-compat@0.2.12':
resolution: {integrity: sha512-rXWnOAdEHbvBPLNjFLu3U0yDZVIAi+C0DL+RkUEOirfSqAeQaKzBCATeBw6+K7FVpEnknhm4tZrvVUVtJjShMw==}
'@firebase/ai@2.0.0':
resolution: {integrity: sha512-N/aSHjqOpU+KkYU3piMkbcuxzvqsOvxflLUXBAkYAPAz8wjE2Ye3BQDgKHEYuhMmEWqj6LFgEBUN8wwc6dfMTw==}
engines: {node: '>=20.0.0'}
peerDependencies:
'@firebase/app': 0.x
'@firebase/app-types': 0.x
'@firebase/analytics-compat@0.2.24':
resolution: {integrity: sha512-jE+kJnPG86XSqGQGhXXYt1tpTbCTED8OQJ/PQ90SEw14CuxRxx/H+lFbWA1rlFtFSsTCptAJtgyRBwr/f00vsw==}
peerDependencies:
'@firebase/app-compat': 0.x
'@firebase/analytics-types@0.8.2':
resolution: {integrity: sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw==}
'@firebase/analytics-types@0.8.3':
resolution: {integrity: sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg==}
'@firebase/analytics@0.10.6':
resolution: {integrity: sha512-sB59EwcAvLt0fINGfMWmcRKcdUiYhE4AJNdDXSCSDo4D/ZXFRmb6qwX9YesKHXFB59XTLT03mAjqQcDrdym9qA==}
'@firebase/analytics@0.10.18':
resolution: {integrity: sha512-iN7IgLvM06iFk8BeFoWqvVpRFW3Z70f+Qe2PfCJ7vPIgLPjHXDE774DhCT5Y2/ZU/ZbXPDPD60x/XPWEoZLNdg==}
peerDependencies:
'@firebase/app': 0.x
'@firebase/app-check-compat@0.3.13':
resolution: {integrity: sha512-1sbS5Apq7dLys1KYdNQsmZLFIjJoFP9Mv4bzIcdXuTkWQjr3X2qAvwiTslC6prVAUMiTV0eM9eicdQIXVsiSRw==}
'@firebase/app-check-compat@0.4.0':
resolution: {integrity: sha512-UfK2Q8RJNjYM/8MFORltZRG9lJj11k0nW84rrffiKvcJxLf1jf6IEjCIkCamykHE73C6BwqhVfhIBs69GXQV0g==}
engines: {node: '>=20.0.0'}
peerDependencies:
'@firebase/app-compat': 0.x
'@firebase/app-check-interop-types@0.3.2':
resolution: {integrity: sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ==}
'@firebase/app-check-types@0.5.2':
resolution: {integrity: sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA==}
'@firebase/app-check-interop-types@0.3.3':
resolution: {integrity: sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==}
'@firebase/app-check@0.8.6':
resolution: {integrity: sha512-uSzl0/SDw54hwuORWHDtldb9kK/QEVZOcoPn2mlIjMrJOLDug/6kcqnIN3IHzwmPyf23Epg0AGBktvG2FugW4w==}
'@firebase/app-check-types@0.5.3':
resolution: {integrity: sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng==}
'@firebase/app-check@0.11.0':
resolution: {integrity: sha512-XAvALQayUMBJo58U/rxW02IhsesaxxfWVmVkauZvGEz3vOAjMEQnzFlyblqkc2iAaO82uJ2ZVyZv9XzPfxjJ6w==}
engines: {node: '>=20.0.0'}
peerDependencies:
'@firebase/app': 0.x
'@firebase/app-compat@0.2.37':
resolution: {integrity: sha512-yiQLYT9LYQHuJGu/msuBLFtdWWTJ3Pz04E9gSeWykSB+8s0XXJJqfqQlghH7CcQ3KnJZR+Wuc3zSMcY3a+dn6Q==}
'@firebase/app-compat@0.5.0':
resolution: {integrity: sha512-nUnNpOeRj0KZzVzHsyuyrmZKKHfykZ8mn40FtG28DeSTWeM5b/2P242Va4bmQpJsy5y32vfv50+jvdckrpzy7Q==}
engines: {node: '>=20.0.0'}
'@firebase/app-types@0.9.2':
resolution: {integrity: sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==}
'@firebase/app@0.10.7':
resolution: {integrity: sha512-7OCd53B+wnk/onbMLn/vM10pDjw97zzWUD8m3swtLYKJIrL+gDZ7HZ4xcbBLw7OB8ikzu8k1ORNjRe2itgAy4g==}
'@firebase/app-types@0.9.3':
resolution: {integrity: sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==}
'@firebase/auth-compat@0.5.10':
resolution: {integrity: sha512-epDhgNIXmhl9DPuTW9Ec5NDJJKMFIdXBXiQI9O0xNHveow/ETtBCY86srzF7iCacqsd30CcpLwwXlhk8Y19Olg==}
'@firebase/app@0.14.0':
resolution: {integrity: sha512-APIAeKvRNFWKJLjIL8wLDjh7u8g6ZjaeVmItyqSjCdEkJj14UuVlus74D8ofsOMWh45HEwxwkd96GYbi+CImEg==}
engines: {node: '>=20.0.0'}
'@firebase/auth-compat@0.6.0':
resolution: {integrity: sha512-J0lGSxXlG/lYVi45wbpPhcWiWUMXevY4fvLZsN1GHh+po7TZVng+figdHBVhFheaiipU8HZyc7ljw1jNojM2nw==}
engines: {node: '>=20.0.0'}
peerDependencies:
'@firebase/app-compat': 0.x
'@firebase/auth-interop-types@0.2.3':
resolution: {integrity: sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==}
'@firebase/auth-types@0.12.2':
resolution: {integrity: sha512-qsEBaRMoGvHO10unlDJhaKSuPn4pyoTtlQuP1ghZfzB6rNQPuhp/N/DcFZxm9i4v0SogjCbf9reWupwIvfmH6w==}
'@firebase/auth-interop-types@0.2.4':
resolution: {integrity: sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==}
'@firebase/auth-types@0.13.0':
resolution: {integrity: sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg==}
peerDependencies:
'@firebase/app-types': 0.x
'@firebase/util': 1.x
'@firebase/auth@1.7.5':
resolution: {integrity: sha512-DMFR1OA/f1/voeuFbSORg9AP36pMgOoSb/DRgiDalLmIJsDTlQNMCu+givjMP4s/XL85+tBk2MerYnK/AscJjw==}
'@firebase/auth@1.11.0':
resolution: {integrity: sha512-5j7+ua93X+IRcJ1oMDTClTo85l7Xe40WSkoJ+shzPrX7OISlVWLdE1mKC57PSD+/LfAbdhJmvKixINBw2ESK6w==}
engines: {node: '>=20.0.0'}
peerDependencies:
'@firebase/app': 0.x
'@react-native-async-storage/async-storage': ^1.18.1
@ -1798,130 +1816,156 @@ packages:
'@firebase/component@0.6.8':
resolution: {integrity: sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==}
'@firebase/component@0.7.0':
resolution: {integrity: sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==}
engines: {node: '>=20.0.0'}
'@firebase/data-connect@0.3.11':
resolution: {integrity: sha512-G258eLzAD6im9Bsw+Qm1Z+P4x0PGNQ45yeUuuqe5M9B1rn0RJvvsQCRHXgE52Z+n9+WX1OJd/crcuunvOGc7Vw==}
peerDependencies:
'@firebase/app': 0.x
'@firebase/database-compat@1.0.6':
resolution: {integrity: sha512-1OGA0sLY47mkXjhICCrUTXEYFnSSXoiXWm1SHsN62b+Lzs5aKA3aWTjTUmYIoK93kDAMPkYpulSv8jcbH4Hwew==}
'@firebase/database-compat@2.1.0':
resolution: {integrity: sha512-8nYc43RqxScsePVd1qe1xxvWNf0OBnbwHxmXJ7MHSuuTVYFO3eLyLW3PiCKJ9fHnmIz4p4LbieXwz+qtr9PZDg==}
engines: {node: '>=20.0.0'}
'@firebase/database-types@1.0.16':
resolution: {integrity: sha512-xkQLQfU5De7+SPhEGAXFBnDryUWhhlFXelEg2YeZOQMCdoe7dL64DDAd77SQsR+6uoXIZY5MB4y/inCs4GTfcw==}
'@firebase/database-types@1.0.4':
resolution: {integrity: sha512-mz9ZzbH6euFXbcBo+enuJ36I5dR5w+enJHHjy9Y5ThCdKUseqfDjW3vCp1YxE9zygFCSjJJ/z1cQ+zodvUcwPQ==}
'@firebase/database@1.0.6':
resolution: {integrity: sha512-nrexUEG/fpVlHtWKkyfhTC3834kZ1WS7voNyqbBsBCqHXQOvznN5Z0L3nxBqdXSJyltNAf4ndFlQqm5gZiEczQ==}
'@firebase/firestore-compat@0.3.33':
resolution: {integrity: sha512-i42a2l31N95CwYEB7zmfK0FS1mrO6pwOLwxavCrwu1BCFrVVVQhUheTPIda/iGguK/2Nog0RaIR1bo7QkZEz3g==}
'@firebase/database@1.1.0':
resolution: {integrity: sha512-gM6MJFae3pTyNLoc9VcJNuaUDej0ctdjn3cVtILo3D5lpp0dmUHHLFN/pUKe7ImyeB1KAvRlEYxvIHNF04Filg==}
engines: {node: '>=20.0.0'}
'@firebase/firestore-compat@0.4.0':
resolution: {integrity: sha512-4O7v4VFeSEwAZtLjsaj33YrMHMRjplOIYC2CiYsF6o/MboOhrhe01VrTt8iY9Y5EwjRHuRz4pS6jMBT8LfQYJA==}
engines: {node: '>=20.0.0'}
peerDependencies:
'@firebase/app-compat': 0.x
'@firebase/firestore-types@3.0.2':
resolution: {integrity: sha512-wp1A+t5rI2Qc/2q7r2ZpjUXkRVPtGMd6zCLsiWurjsQpqPgFin3AhNibKcIzoF2rnToNa/XYtyWXuifjOOwDgg==}
'@firebase/firestore-types@3.0.3':
resolution: {integrity: sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==}
peerDependencies:
'@firebase/app-types': 0.x
'@firebase/util': 1.x
'@firebase/firestore@4.6.4':
resolution: {integrity: sha512-vk2MoH5HxYEhiNg1l+yBXq1Fkhue/11bFg4HdlTv6BJHcTnnAj2a+/afPpatcW4MOdYA3Tv+d5nGzWbbOC1SHw==}
engines: {node: '>=10.10.0'}
'@firebase/firestore@4.9.0':
resolution: {integrity: sha512-5zl0+/h1GvlCSLt06RMwqFsd7uqRtnNZt4sW99k2rKRd6k/ECObIWlEnvthm2cuOSnUmwZknFqtmd1qyYSLUuQ==}
engines: {node: '>=20.0.0'}
peerDependencies:
'@firebase/app': 0.x
'@firebase/functions-compat@0.3.12':
resolution: {integrity: sha512-r3XUb5VlITWpML46JymfJPkK6I9j4SNlO7qWIXUc0TUmkv0oAfVoiIt1F83/NuMZXaGr4YWA/794nVSy4GV8tw==}
'@firebase/functions-compat@0.4.0':
resolution: {integrity: sha512-VPgtvoGFywWbQqtvgJnVWIDFSHV1WE6Hmyi5EGI+P+56EskiGkmnw6lEqc/MEUfGpPGdvmc4I9XMU81uj766/g==}
engines: {node: '>=20.0.0'}
peerDependencies:
'@firebase/app-compat': 0.x
'@firebase/functions-types@0.6.2':
resolution: {integrity: sha512-0KiJ9lZ28nS2iJJvimpY4nNccV21rkQyor5Iheu/nq8aKXJqtJdeSlZDspjPSBBiHRzo7/GMUttegnsEITqR+w==}
'@firebase/functions-types@0.6.3':
resolution: {integrity: sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg==}
'@firebase/functions@0.11.6':
resolution: {integrity: sha512-GPfIBPtpwQvsC7SQbgaUjLTdja0CsNwMoKSgrzA1FGGRk4NX6qO7VQU6XCwBiAFWbpbQex6QWkSMsCzLx1uibQ==}
'@firebase/functions@0.13.0':
resolution: {integrity: sha512-2/LH5xIbD8aaLOWSFHAwwAybgSzHIM0dB5oVOL0zZnxFG1LctX2bc1NIAaPk1T+Zo9aVkLKUlB5fTXTkVUQprQ==}
engines: {node: '>=20.0.0'}
peerDependencies:
'@firebase/app': 0.x
'@firebase/installations-compat@0.2.8':
resolution: {integrity: sha512-pI2q8JFHB7yIq/szmhzGSWXtOvtzl6tCUmyykv5C8vvfOVJUH6mP4M4iwjbK8S1JotKd/K70+JWyYlxgQ0Kpyw==}
'@firebase/installations-compat@0.2.19':
resolution: {integrity: sha512-khfzIY3EI5LePePo7vT19/VEIH1E3iYsHknI/6ek9T8QCozAZshWT9CjlwOzZrKvTHMeNcbpo/VSOSIWDSjWdQ==}
peerDependencies:
'@firebase/app-compat': 0.x
'@firebase/installations-types@0.5.2':
resolution: {integrity: sha512-que84TqGRZJpJKHBlF2pkvc1YcXrtEDOVGiDjovP/a3s6W4nlbohGXEsBJo0JCeeg/UG9A+DEZVDUV9GpklUzA==}
'@firebase/installations-types@0.5.3':
resolution: {integrity: sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==}
peerDependencies:
'@firebase/app-types': 0.x
'@firebase/installations@0.6.8':
resolution: {integrity: sha512-57V374qdb2+wT5v7+ntpLXBjZkO6WRgmAUbVkRfFTM/4t980p0FesbqTAcOIiM8U866UeuuuF8lYH70D3jM/jQ==}
'@firebase/installations@0.6.19':
resolution: {integrity: sha512-nGDmiwKLI1lerhwfwSHvMR9RZuIH5/8E3kgUWnVRqqL7kGVSktjLTWEMva7oh5yxQ3zXfIlIwJwMcaM5bK5j8Q==}
peerDependencies:
'@firebase/app': 0.x
'@firebase/logger@0.4.2':
resolution: {integrity: sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==}
'@firebase/messaging-compat@0.2.10':
resolution: {integrity: sha512-FXQm7rcowkDm8kFLduHV35IRYCRo+Ng0PIp/t1+EBuEbyplaKkGjZ932pE+owf/XR+G/60ku2QRBptRGLXZydg==}
'@firebase/logger@0.5.0':
resolution: {integrity: sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==}
engines: {node: '>=20.0.0'}
'@firebase/messaging-compat@0.2.23':
resolution: {integrity: sha512-SN857v/kBUvlQ9X/UjAqBoQ2FEaL1ZozpnmL1ByTe57iXkmnVVFm9KqAsTfmf+OEwWI4kJJe9NObtN/w22lUgg==}
peerDependencies:
'@firebase/app-compat': 0.x
'@firebase/messaging-interop-types@0.2.2':
resolution: {integrity: sha512-l68HXbuD2PPzDUOFb3aG+nZj5KA3INcPwlocwLZOzPp9rFM9yeuI9YLl6DQfguTX5eAGxO0doTR+rDLDvQb5tA==}
'@firebase/messaging-interop-types@0.2.3':
resolution: {integrity: sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q==}
'@firebase/messaging@0.12.10':
resolution: {integrity: sha512-fGbxJPKpl2DIKNJGhbk4mYPcM+qE2gl91r6xPoiol/mN88F5Ym6UeRdMVZah+pijh9WxM55alTYwXuW40r1Y2Q==}
'@firebase/messaging@0.12.23':
resolution: {integrity: sha512-cfuzv47XxqW4HH/OcR5rM+AlQd1xL/VhuaeW/wzMW1LFrsFcTn0GND/hak1vkQc2th8UisBcrkVcQAnOnKwYxg==}
peerDependencies:
'@firebase/app': 0.x
'@firebase/performance-compat@0.2.8':
resolution: {integrity: sha512-o7TFClRVJd3VIBoY7KZQqtCeW0PC6v9uBzM6Lfw3Nc9D7hM6OonqecYvh7NwJ6R14k+xM27frLS4BcCvFHKw2A==}
'@firebase/performance-compat@0.2.21':
resolution: {integrity: sha512-OQfYRsIQiEf9ez1SOMLb5TRevBHNIyA2x1GI1H10lZ432W96AK5r4LTM+SNApg84dxOuHt6RWSQWY7TPWffKXg==}
peerDependencies:
'@firebase/app-compat': 0.x
'@firebase/performance-types@0.2.2':
resolution: {integrity: sha512-gVq0/lAClVH5STrIdKnHnCo2UcPLjJlDUoEB/tB4KM+hAeHUxWKnpT0nemUPvxZ5nbdY/pybeyMe8Cs29gEcHA==}
'@firebase/performance-types@0.2.3':
resolution: {integrity: sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ==}
'@firebase/performance@0.6.8':
resolution: {integrity: sha512-F+alziiIZ6Yn8FG47mxwljq+4XkgkT2uJIFRlkyViUQRLzrogaUJW6u/+6ZrePXnouKlKIwzqos3PVJraPEcCA==}
'@firebase/performance@0.7.8':
resolution: {integrity: sha512-k6xfNM/CdTl4RaV4gT/lH53NU+wP33JiN0pUeNBzGVNvfXZ3HbCkoISE3M/XaiOwHgded1l6XfLHa4zHgm0Wyg==}
peerDependencies:
'@firebase/app': 0.x
'@firebase/remote-config-compat@0.2.8':
resolution: {integrity: sha512-UxSFOp6dzFj2AHB8Bq/BYtbq5iFyizKx4Rd6WxAdaKYM8cnPMeK+l2v+Oogtjae+AeyHRI+MfL2acsfVe5cd2A==}
'@firebase/remote-config-compat@0.2.19':
resolution: {integrity: sha512-y7PZAb0l5+5oIgLJr88TNSelxuASGlXyAKj+3pUc4fDuRIdPNBoONMHaIUa9rlffBR5dErmaD2wUBJ7Z1a513Q==}
peerDependencies:
'@firebase/app-compat': 0.x
'@firebase/remote-config-types@0.3.2':
resolution: {integrity: sha512-0BC4+Ud7y2aPTyhXJTMTFfrGGLqdYXrUB9sJVAB8NiqJswDTc4/2qrE/yfUbnQJhbSi6ZaTTBKyG3n1nplssaA==}
'@firebase/remote-config-types@0.4.0':
resolution: {integrity: sha512-7p3mRE/ldCNYt8fmWMQ/MSGRmXYlJ15Rvs9Rk17t8p0WwZDbeK7eRmoI1tvCPaDzn9Oqh+yD6Lw+sGLsLg4kKg==}
'@firebase/remote-config@0.4.8':
resolution: {integrity: sha512-AMLqe6wfIRnjc6FkCWOSUjhc1fSTEf8o+cv1NolFvbiJ/tU+TqN4pI7pT+MIKQzNiq5fxLehkOx+xtAQBxPJKQ==}
'@firebase/remote-config@0.6.6':
resolution: {integrity: sha512-Yelp5xd8hM4NO1G1SuWrIk4h5K42mNwC98eWZ9YLVu6Z0S6hFk1mxotAdCRmH2luH8FASlYgLLq6OQLZ4nbnCA==}
peerDependencies:
'@firebase/app': 0.x
'@firebase/storage-compat@0.3.9':
resolution: {integrity: sha512-WWgAp5bTW961oIsCc9+98m4MIVKpEqztAlIngfHfwO/x3DYoBPRl/awMRG3CAXyVxG+7B7oHC5IsnqM+vTwx2A==}
'@firebase/storage-compat@0.4.0':
resolution: {integrity: sha512-vDzhgGczr1OfcOy285YAPur5pWDEvD67w4thyeCUh6Ys0izN9fNYtA1MJERmNBfqjqu0lg0FM5GLbw0Il21M+g==}
engines: {node: '>=20.0.0'}
peerDependencies:
'@firebase/app-compat': 0.x
'@firebase/storage-types@0.8.2':
resolution: {integrity: sha512-0vWu99rdey0g53lA7IShoA2Lol1jfnPovzLDUBuon65K7uKG9G+L5uO05brD9pMw+l4HRFw23ah3GwTGpEav6g==}
'@firebase/storage-types@0.8.3':
resolution: {integrity: sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==}
peerDependencies:
'@firebase/app-types': 0.x
'@firebase/util': 1.x
'@firebase/storage@0.12.6':
resolution: {integrity: sha512-Zgb9WuehJxzhj7pGXUvkAEaH+3HvLjD9xSZ9nepuXf5f8378xME7oGJtREr/RnepdDA5YW0XIxe0QQBNHpe1nw==}
'@firebase/storage@0.14.0':
resolution: {integrity: sha512-xWWbb15o6/pWEw8H01UQ1dC5U3rf8QTAzOChYyCpafV6Xki7KVp3Yaw2nSklUwHEziSWE9KoZJS7iYeyqWnYFA==}
engines: {node: '>=20.0.0'}
peerDependencies:
'@firebase/app': 0.x
'@firebase/util@1.13.0':
resolution: {integrity: sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==}
engines: {node: '>=20.0.0'}
'@firebase/util@1.9.7':
resolution: {integrity: sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==}
'@firebase/vertexai-preview@0.0.3':
resolution: {integrity: sha512-KVtUWLp+ScgiwkDKAvNkVucAyhLVQp6C6lhnVEuIg4mWhWcS3oerjAeVhZT4uNofKwWxRsOaB2Yec7DMTXlQPQ==}
engines: {node: '>=18.0.0'}
peerDependencies:
'@firebase/app': 0.x
'@firebase/app-types': 0.x
'@firebase/webchannel-wrapper@1.0.1':
resolution: {integrity: sha512-jmEnr/pk0yVkA7mIlHNnxCi+wWzOFUg0WyIotgkKAb2u1J7fAeDBcVNSTjTihbAYNusCLQdW5s9IJ5qwnEufcQ==}
'@firebase/webchannel-wrapper@1.0.4':
resolution: {integrity: sha512-6m8+P+dE/RPl4OPzjTxcTbQ0rGeRyeTvAi9KwIffBVCiAMKrfXfLZaqD1F+m8t4B5/Q5aHsMozOgirkH1F5oMQ==}
'@fortawesome/fontawesome-free@5.15.4':
resolution: {integrity: sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==}
@ -5253,8 +5297,8 @@ packages:
engines: {node: '>=18.0.0 || >=20.0.0'}
hasBin: true
firebase@10.12.4:
resolution: {integrity: sha512-SQz49NMpwG4MLTPZ9C8jBp7IyS2haTvsIvjclgu+v/jvzNtjZoxIcoF6A13EIfBHmJ5eiuVlvttxElOf7LnJew==}
firebase@12.0.0:
resolution: {integrity: sha512-KV+OrMJpi2uXlqL2zaCcXb7YuQbY/gMIWT1hf8hKeTW1bSumWaHT5qfmn0WTpHwKQa3QEVOtZR2ta9EchcmYuw==}
flagged-respawn@1.0.1:
resolution: {integrity: sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==}
@ -8606,9 +8650,6 @@ packages:
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
safevalues@0.6.0:
resolution: {integrity: sha512-MZ7DcTOcIoPXN36/UONVE9BT0pmwlCr9WcS7Pj/q4FxOwr33FkWC0CUWj/THQXYWxf/F7urbhaHaOeFPSqGqHA==}
sass-lookup@6.0.1:
resolution: {integrity: sha512-nl9Wxbj9RjEJA5SSV0hSDoU2zYGtE+ANaDS4OFUR7nYrquvBFvPKZZtQHe3lvnxCcylEDV00KUijjdMTUElcVQ==}
engines: {node: '>=18'}
@ -9664,10 +9705,6 @@ packages:
undici-types@5.26.5:
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
undici@5.28.4:
resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==}
engines: {node: '>=14.0'}
undici@7.12.0:
resolution: {integrity: sha512-GrKEsc3ughskmGA9jevVlIOPMiiAHJ4OFUtaAH+NhfTUSiZ1wMPIQqQvAJUrJspFXJt3EBWgpAeoHEDVT1IBug==}
engines: {node: '>=20.18.1'}
@ -10091,6 +10128,9 @@ packages:
resolution: {integrity: sha512-kfqDxt5dTB1JhqsCUQVFDj0rmY+4HLwGQIsLPbyrsN9y9WV/1oFDSx3BQ4GfCv9X+jVeQ7rouTqwK53rA/7t8A==}
engines: {node: '>=10.0.0'}
web-vitals@4.2.4:
resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==}
webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
@ -11522,85 +11562,94 @@ snapshots:
dependencies:
text-decoding: 1.0.0
'@fastify/busboy@2.1.1': {}
'@fastify/error@2.0.0': {}
'@firebase/analytics-compat@0.2.12(@firebase/app-compat@0.2.37)(@firebase/app@0.10.7)':
'@firebase/ai@2.0.0(@firebase/app-types@0.9.3)(@firebase/app@0.14.0)':
dependencies:
'@firebase/analytics': 0.10.6(@firebase/app@0.10.7)
'@firebase/analytics-types': 0.8.2
'@firebase/app-compat': 0.2.37
'@firebase/component': 0.6.8
'@firebase/util': 1.9.7
'@firebase/app': 0.14.0
'@firebase/app-check-interop-types': 0.3.3
'@firebase/app-types': 0.9.3
'@firebase/component': 0.7.0
'@firebase/logger': 0.5.0
'@firebase/util': 1.13.0
tslib: 2.6.3
'@firebase/analytics-compat@0.2.24(@firebase/app-compat@0.5.0)(@firebase/app@0.14.0)':
dependencies:
'@firebase/analytics': 0.10.18(@firebase/app@0.14.0)
'@firebase/analytics-types': 0.8.3
'@firebase/app-compat': 0.5.0
'@firebase/component': 0.7.0
'@firebase/util': 1.13.0
tslib: 2.6.3
transitivePeerDependencies:
- '@firebase/app'
'@firebase/analytics-types@0.8.2': {}
'@firebase/analytics-types@0.8.3': {}
'@firebase/analytics@0.10.6(@firebase/app@0.10.7)':
'@firebase/analytics@0.10.18(@firebase/app@0.14.0)':
dependencies:
'@firebase/app': 0.10.7
'@firebase/component': 0.6.8
'@firebase/installations': 0.6.8(@firebase/app@0.10.7)
'@firebase/logger': 0.4.2
'@firebase/util': 1.9.7
safevalues: 0.6.0
'@firebase/app': 0.14.0
'@firebase/component': 0.7.0
'@firebase/installations': 0.6.19(@firebase/app@0.14.0)
'@firebase/logger': 0.5.0
'@firebase/util': 1.13.0
tslib: 2.6.3
'@firebase/app-check-compat@0.3.13(@firebase/app-compat@0.2.37)(@firebase/app@0.10.7)':
'@firebase/app-check-compat@0.4.0(@firebase/app-compat@0.5.0)(@firebase/app@0.14.0)':
dependencies:
'@firebase/app-check': 0.8.6(@firebase/app@0.10.7)
'@firebase/app-check-types': 0.5.2
'@firebase/app-compat': 0.2.37
'@firebase/component': 0.6.8
'@firebase/logger': 0.4.2
'@firebase/util': 1.9.7
'@firebase/app-check': 0.11.0(@firebase/app@0.14.0)
'@firebase/app-check-types': 0.5.3
'@firebase/app-compat': 0.5.0
'@firebase/component': 0.7.0
'@firebase/logger': 0.5.0
'@firebase/util': 1.13.0
tslib: 2.6.3
transitivePeerDependencies:
- '@firebase/app'
'@firebase/app-check-interop-types@0.3.2': {}
'@firebase/app-check-types@0.5.2': {}
'@firebase/app-check-interop-types@0.3.3': {}
'@firebase/app-check@0.8.6(@firebase/app@0.10.7)':
'@firebase/app-check-types@0.5.3': {}
'@firebase/app-check@0.11.0(@firebase/app@0.14.0)':
dependencies:
'@firebase/app': 0.10.7
'@firebase/component': 0.6.8
'@firebase/logger': 0.4.2
'@firebase/util': 1.9.7
safevalues: 0.6.0
'@firebase/app': 0.14.0
'@firebase/component': 0.7.0
'@firebase/logger': 0.5.0
'@firebase/util': 1.13.0
tslib: 2.6.3
'@firebase/app-compat@0.2.37':
'@firebase/app-compat@0.5.0':
dependencies:
'@firebase/app': 0.10.7
'@firebase/component': 0.6.8
'@firebase/logger': 0.4.2
'@firebase/util': 1.9.7
'@firebase/app': 0.14.0
'@firebase/component': 0.7.0
'@firebase/logger': 0.5.0
'@firebase/util': 1.13.0
tslib: 2.6.3
'@firebase/app-types@0.9.2': {}
'@firebase/app@0.10.7':
'@firebase/app-types@0.9.3': {}
'@firebase/app@0.14.0':
dependencies:
'@firebase/component': 0.6.8
'@firebase/logger': 0.4.2
'@firebase/util': 1.9.7
'@firebase/component': 0.7.0
'@firebase/logger': 0.5.0
'@firebase/util': 1.13.0
idb: 7.1.1
tslib: 2.6.3
'@firebase/auth-compat@0.5.10(@firebase/app-compat@0.2.37)(@firebase/app-types@0.9.2)(@firebase/app@0.10.7)':
'@firebase/auth-compat@0.6.0(@firebase/app-compat@0.5.0)(@firebase/app-types@0.9.3)(@firebase/app@0.14.0)':
dependencies:
'@firebase/app-compat': 0.2.37
'@firebase/auth': 1.7.5(@firebase/app@0.10.7)
'@firebase/auth-types': 0.12.2(@firebase/app-types@0.9.2)(@firebase/util@1.9.7)
'@firebase/component': 0.6.8
'@firebase/util': 1.9.7
'@firebase/app-compat': 0.5.0
'@firebase/auth': 1.11.0(@firebase/app@0.14.0)
'@firebase/auth-types': 0.13.0(@firebase/app-types@0.9.3)(@firebase/util@1.13.0)
'@firebase/component': 0.7.0
'@firebase/util': 1.13.0
tslib: 2.6.3
undici: 5.28.4
transitivePeerDependencies:
- '@firebase/app'
- '@firebase/app-types'
@ -11608,25 +11657,40 @@ snapshots:
'@firebase/auth-interop-types@0.2.3': {}
'@firebase/auth-types@0.12.2(@firebase/app-types@0.9.2)(@firebase/util@1.9.7)':
dependencies:
'@firebase/app-types': 0.9.2
'@firebase/util': 1.9.7
'@firebase/auth-interop-types@0.2.4': {}
'@firebase/auth@1.7.5(@firebase/app@0.10.7)':
'@firebase/auth-types@0.13.0(@firebase/app-types@0.9.3)(@firebase/util@1.13.0)':
dependencies:
'@firebase/app': 0.10.7
'@firebase/component': 0.6.8
'@firebase/logger': 0.4.2
'@firebase/util': 1.9.7
'@firebase/app-types': 0.9.3
'@firebase/util': 1.13.0
'@firebase/auth@1.11.0(@firebase/app@0.14.0)':
dependencies:
'@firebase/app': 0.14.0
'@firebase/component': 0.7.0
'@firebase/logger': 0.5.0
'@firebase/util': 1.13.0
tslib: 2.6.3
undici: 5.28.4
'@firebase/component@0.6.8':
dependencies:
'@firebase/util': 1.9.7
tslib: 2.6.3
'@firebase/component@0.7.0':
dependencies:
'@firebase/util': 1.13.0
tslib: 2.6.3
'@firebase/data-connect@0.3.11(@firebase/app@0.14.0)':
dependencies:
'@firebase/app': 0.14.0
'@firebase/auth-interop-types': 0.2.4
'@firebase/component': 0.7.0
'@firebase/logger': 0.5.0
'@firebase/util': 1.13.0
tslib: 2.6.3
'@firebase/database-compat@1.0.6':
dependencies:
'@firebase/component': 0.6.8
@ -11636,6 +11700,20 @@ snapshots:
'@firebase/util': 1.9.7
tslib: 2.6.3
'@firebase/database-compat@2.1.0':
dependencies:
'@firebase/component': 0.7.0
'@firebase/database': 1.1.0
'@firebase/database-types': 1.0.16
'@firebase/logger': 0.5.0
'@firebase/util': 1.13.0
tslib: 2.6.3
'@firebase/database-types@1.0.16':
dependencies:
'@firebase/app-types': 0.9.3
'@firebase/util': 1.13.0
'@firebase/database-types@1.0.4':
dependencies:
'@firebase/app-types': 0.9.2
@ -11651,80 +11729,88 @@ snapshots:
faye-websocket: 0.11.4
tslib: 2.6.3
'@firebase/firestore-compat@0.3.33(@firebase/app-compat@0.2.37)(@firebase/app-types@0.9.2)(@firebase/app@0.10.7)':
'@firebase/database@1.1.0':
dependencies:
'@firebase/app-compat': 0.2.37
'@firebase/component': 0.6.8
'@firebase/firestore': 4.6.4(@firebase/app@0.10.7)
'@firebase/firestore-types': 3.0.2(@firebase/app-types@0.9.2)(@firebase/util@1.9.7)
'@firebase/util': 1.9.7
'@firebase/app-check-interop-types': 0.3.3
'@firebase/auth-interop-types': 0.2.4
'@firebase/component': 0.7.0
'@firebase/logger': 0.5.0
'@firebase/util': 1.13.0
faye-websocket: 0.11.4
tslib: 2.6.3
'@firebase/firestore-compat@0.4.0(@firebase/app-compat@0.5.0)(@firebase/app-types@0.9.3)(@firebase/app@0.14.0)':
dependencies:
'@firebase/app-compat': 0.5.0
'@firebase/component': 0.7.0
'@firebase/firestore': 4.9.0(@firebase/app@0.14.0)
'@firebase/firestore-types': 3.0.3(@firebase/app-types@0.9.3)(@firebase/util@1.13.0)
'@firebase/util': 1.13.0
tslib: 2.6.3
transitivePeerDependencies:
- '@firebase/app'
- '@firebase/app-types'
'@firebase/firestore-types@3.0.2(@firebase/app-types@0.9.2)(@firebase/util@1.9.7)':
'@firebase/firestore-types@3.0.3(@firebase/app-types@0.9.3)(@firebase/util@1.13.0)':
dependencies:
'@firebase/app-types': 0.9.2
'@firebase/util': 1.9.7
'@firebase/app-types': 0.9.3
'@firebase/util': 1.13.0
'@firebase/firestore@4.6.4(@firebase/app@0.10.7)':
'@firebase/firestore@4.9.0(@firebase/app@0.14.0)':
dependencies:
'@firebase/app': 0.10.7
'@firebase/component': 0.6.8
'@firebase/logger': 0.4.2
'@firebase/util': 1.9.7
'@firebase/webchannel-wrapper': 1.0.1
'@firebase/app': 0.14.0
'@firebase/component': 0.7.0
'@firebase/logger': 0.5.0
'@firebase/util': 1.13.0
'@firebase/webchannel-wrapper': 1.0.4
'@grpc/grpc-js': 1.9.15
'@grpc/proto-loader': 0.7.13
tslib: 2.6.3
undici: 5.28.4
'@firebase/functions-compat@0.3.12(@firebase/app-compat@0.2.37)(@firebase/app@0.10.7)':
'@firebase/functions-compat@0.4.0(@firebase/app-compat@0.5.0)(@firebase/app@0.14.0)':
dependencies:
'@firebase/app-compat': 0.2.37
'@firebase/component': 0.6.8
'@firebase/functions': 0.11.6(@firebase/app@0.10.7)
'@firebase/functions-types': 0.6.2
'@firebase/util': 1.9.7
'@firebase/app-compat': 0.5.0
'@firebase/component': 0.7.0
'@firebase/functions': 0.13.0(@firebase/app@0.14.0)
'@firebase/functions-types': 0.6.3
'@firebase/util': 1.13.0
tslib: 2.6.3
transitivePeerDependencies:
- '@firebase/app'
'@firebase/functions-types@0.6.2': {}
'@firebase/functions-types@0.6.3': {}
'@firebase/functions@0.11.6(@firebase/app@0.10.7)':
'@firebase/functions@0.13.0(@firebase/app@0.14.0)':
dependencies:
'@firebase/app': 0.10.7
'@firebase/app-check-interop-types': 0.3.2
'@firebase/auth-interop-types': 0.2.3
'@firebase/component': 0.6.8
'@firebase/messaging-interop-types': 0.2.2
'@firebase/util': 1.9.7
'@firebase/app': 0.14.0
'@firebase/app-check-interop-types': 0.3.3
'@firebase/auth-interop-types': 0.2.4
'@firebase/component': 0.7.0
'@firebase/messaging-interop-types': 0.2.3
'@firebase/util': 1.13.0
tslib: 2.6.3
undici: 5.28.4
'@firebase/installations-compat@0.2.8(@firebase/app-compat@0.2.37)(@firebase/app-types@0.9.2)(@firebase/app@0.10.7)':
'@firebase/installations-compat@0.2.19(@firebase/app-compat@0.5.0)(@firebase/app-types@0.9.3)(@firebase/app@0.14.0)':
dependencies:
'@firebase/app-compat': 0.2.37
'@firebase/component': 0.6.8
'@firebase/installations': 0.6.8(@firebase/app@0.10.7)
'@firebase/installations-types': 0.5.2(@firebase/app-types@0.9.2)
'@firebase/util': 1.9.7
'@firebase/app-compat': 0.5.0
'@firebase/component': 0.7.0
'@firebase/installations': 0.6.19(@firebase/app@0.14.0)
'@firebase/installations-types': 0.5.3(@firebase/app-types@0.9.3)
'@firebase/util': 1.13.0
tslib: 2.6.3
transitivePeerDependencies:
- '@firebase/app'
- '@firebase/app-types'
'@firebase/installations-types@0.5.2(@firebase/app-types@0.9.2)':
'@firebase/installations-types@0.5.3(@firebase/app-types@0.9.3)':
dependencies:
'@firebase/app-types': 0.9.2
'@firebase/app-types': 0.9.3
'@firebase/installations@0.6.8(@firebase/app@0.10.7)':
'@firebase/installations@0.6.19(@firebase/app@0.14.0)':
dependencies:
'@firebase/app': 0.10.7
'@firebase/component': 0.6.8
'@firebase/util': 1.9.7
'@firebase/app': 0.14.0
'@firebase/component': 0.7.0
'@firebase/util': 1.13.0
idb: 7.1.1
tslib: 2.6.3
@ -11732,114 +11818,112 @@ snapshots:
dependencies:
tslib: 2.6.3
'@firebase/messaging-compat@0.2.10(@firebase/app-compat@0.2.37)(@firebase/app@0.10.7)':
'@firebase/logger@0.5.0':
dependencies:
'@firebase/app-compat': 0.2.37
'@firebase/component': 0.6.8
'@firebase/messaging': 0.12.10(@firebase/app@0.10.7)
'@firebase/util': 1.9.7
tslib: 2.6.3
'@firebase/messaging-compat@0.2.23(@firebase/app-compat@0.5.0)(@firebase/app@0.14.0)':
dependencies:
'@firebase/app-compat': 0.5.0
'@firebase/component': 0.7.0
'@firebase/messaging': 0.12.23(@firebase/app@0.14.0)
'@firebase/util': 1.13.0
tslib: 2.6.3
transitivePeerDependencies:
- '@firebase/app'
'@firebase/messaging-interop-types@0.2.2': {}
'@firebase/messaging-interop-types@0.2.3': {}
'@firebase/messaging@0.12.10(@firebase/app@0.10.7)':
'@firebase/messaging@0.12.23(@firebase/app@0.14.0)':
dependencies:
'@firebase/app': 0.10.7
'@firebase/component': 0.6.8
'@firebase/installations': 0.6.8(@firebase/app@0.10.7)
'@firebase/messaging-interop-types': 0.2.2
'@firebase/util': 1.9.7
'@firebase/app': 0.14.0
'@firebase/component': 0.7.0
'@firebase/installations': 0.6.19(@firebase/app@0.14.0)
'@firebase/messaging-interop-types': 0.2.3
'@firebase/util': 1.13.0
idb: 7.1.1
tslib: 2.6.3
'@firebase/performance-compat@0.2.8(@firebase/app-compat@0.2.37)(@firebase/app@0.10.7)':
'@firebase/performance-compat@0.2.21(@firebase/app-compat@0.5.0)(@firebase/app@0.14.0)':
dependencies:
'@firebase/app-compat': 0.2.37
'@firebase/component': 0.6.8
'@firebase/logger': 0.4.2
'@firebase/performance': 0.6.8(@firebase/app@0.10.7)
'@firebase/performance-types': 0.2.2
'@firebase/util': 1.9.7
'@firebase/app-compat': 0.5.0
'@firebase/component': 0.7.0
'@firebase/logger': 0.5.0
'@firebase/performance': 0.7.8(@firebase/app@0.14.0)
'@firebase/performance-types': 0.2.3
'@firebase/util': 1.13.0
tslib: 2.6.3
transitivePeerDependencies:
- '@firebase/app'
'@firebase/performance-types@0.2.2': {}
'@firebase/performance-types@0.2.3': {}
'@firebase/performance@0.6.8(@firebase/app@0.10.7)':
'@firebase/performance@0.7.8(@firebase/app@0.14.0)':
dependencies:
'@firebase/app': 0.10.7
'@firebase/component': 0.6.8
'@firebase/installations': 0.6.8(@firebase/app@0.10.7)
'@firebase/logger': 0.4.2
'@firebase/util': 1.9.7
'@firebase/app': 0.14.0
'@firebase/component': 0.7.0
'@firebase/installations': 0.6.19(@firebase/app@0.14.0)
'@firebase/logger': 0.5.0
'@firebase/util': 1.13.0
tslib: 2.6.3
web-vitals: 4.2.4
'@firebase/remote-config-compat@0.2.8(@firebase/app-compat@0.2.37)(@firebase/app@0.10.7)':
'@firebase/remote-config-compat@0.2.19(@firebase/app-compat@0.5.0)(@firebase/app@0.14.0)':
dependencies:
'@firebase/app-compat': 0.2.37
'@firebase/component': 0.6.8
'@firebase/logger': 0.4.2
'@firebase/remote-config': 0.4.8(@firebase/app@0.10.7)
'@firebase/remote-config-types': 0.3.2
'@firebase/util': 1.9.7
'@firebase/app-compat': 0.5.0
'@firebase/component': 0.7.0
'@firebase/logger': 0.5.0
'@firebase/remote-config': 0.6.6(@firebase/app@0.14.0)
'@firebase/remote-config-types': 0.4.0
'@firebase/util': 1.13.0
tslib: 2.6.3
transitivePeerDependencies:
- '@firebase/app'
'@firebase/remote-config-types@0.3.2': {}
'@firebase/remote-config-types@0.4.0': {}
'@firebase/remote-config@0.4.8(@firebase/app@0.10.7)':
'@firebase/remote-config@0.6.6(@firebase/app@0.14.0)':
dependencies:
'@firebase/app': 0.10.7
'@firebase/component': 0.6.8
'@firebase/installations': 0.6.8(@firebase/app@0.10.7)
'@firebase/logger': 0.4.2
'@firebase/util': 1.9.7
'@firebase/app': 0.14.0
'@firebase/component': 0.7.0
'@firebase/installations': 0.6.19(@firebase/app@0.14.0)
'@firebase/logger': 0.5.0
'@firebase/util': 1.13.0
tslib: 2.6.3
'@firebase/storage-compat@0.3.9(@firebase/app-compat@0.2.37)(@firebase/app-types@0.9.2)(@firebase/app@0.10.7)':
'@firebase/storage-compat@0.4.0(@firebase/app-compat@0.5.0)(@firebase/app-types@0.9.3)(@firebase/app@0.14.0)':
dependencies:
'@firebase/app-compat': 0.2.37
'@firebase/component': 0.6.8
'@firebase/storage': 0.12.6(@firebase/app@0.10.7)
'@firebase/storage-types': 0.8.2(@firebase/app-types@0.9.2)(@firebase/util@1.9.7)
'@firebase/util': 1.9.7
'@firebase/app-compat': 0.5.0
'@firebase/component': 0.7.0
'@firebase/storage': 0.14.0(@firebase/app@0.14.0)
'@firebase/storage-types': 0.8.3(@firebase/app-types@0.9.3)(@firebase/util@1.13.0)
'@firebase/util': 1.13.0
tslib: 2.6.3
transitivePeerDependencies:
- '@firebase/app'
- '@firebase/app-types'
'@firebase/storage-types@0.8.2(@firebase/app-types@0.9.2)(@firebase/util@1.9.7)':
'@firebase/storage-types@0.8.3(@firebase/app-types@0.9.3)(@firebase/util@1.13.0)':
dependencies:
'@firebase/app-types': 0.9.2
'@firebase/util': 1.9.7
'@firebase/app-types': 0.9.3
'@firebase/util': 1.13.0
'@firebase/storage@0.12.6(@firebase/app@0.10.7)':
'@firebase/storage@0.14.0(@firebase/app@0.14.0)':
dependencies:
'@firebase/app': 0.14.0
'@firebase/component': 0.7.0
'@firebase/util': 1.13.0
tslib: 2.6.3
'@firebase/util@1.13.0':
dependencies:
'@firebase/app': 0.10.7
'@firebase/component': 0.6.8
'@firebase/util': 1.9.7
tslib: 2.6.3
undici: 5.28.4
'@firebase/util@1.9.7':
dependencies:
tslib: 2.6.3
'@firebase/vertexai-preview@0.0.3(@firebase/app-types@0.9.2)(@firebase/app@0.10.7)':
dependencies:
'@firebase/app': 0.10.7
'@firebase/app-check-interop-types': 0.3.2
'@firebase/app-types': 0.9.2
'@firebase/component': 0.6.8
'@firebase/logger': 0.4.2
'@firebase/util': 1.9.7
tslib: 2.6.3
'@firebase/webchannel-wrapper@1.0.1': {}
'@firebase/webchannel-wrapper@1.0.4': {}
'@fortawesome/fontawesome-free@5.15.4': {}
@ -15966,35 +16050,36 @@ snapshots:
- supports-color
- utf-8-validate
firebase@10.12.4:
firebase@12.0.0:
dependencies:
'@firebase/analytics': 0.10.6(@firebase/app@0.10.7)
'@firebase/analytics-compat': 0.2.12(@firebase/app-compat@0.2.37)(@firebase/app@0.10.7)
'@firebase/app': 0.10.7
'@firebase/app-check': 0.8.6(@firebase/app@0.10.7)
'@firebase/app-check-compat': 0.3.13(@firebase/app-compat@0.2.37)(@firebase/app@0.10.7)
'@firebase/app-compat': 0.2.37
'@firebase/app-types': 0.9.2
'@firebase/auth': 1.7.5(@firebase/app@0.10.7)
'@firebase/auth-compat': 0.5.10(@firebase/app-compat@0.2.37)(@firebase/app-types@0.9.2)(@firebase/app@0.10.7)
'@firebase/database': 1.0.6
'@firebase/database-compat': 1.0.6
'@firebase/firestore': 4.6.4(@firebase/app@0.10.7)
'@firebase/firestore-compat': 0.3.33(@firebase/app-compat@0.2.37)(@firebase/app-types@0.9.2)(@firebase/app@0.10.7)
'@firebase/functions': 0.11.6(@firebase/app@0.10.7)
'@firebase/functions-compat': 0.3.12(@firebase/app-compat@0.2.37)(@firebase/app@0.10.7)
'@firebase/installations': 0.6.8(@firebase/app@0.10.7)
'@firebase/installations-compat': 0.2.8(@firebase/app-compat@0.2.37)(@firebase/app-types@0.9.2)(@firebase/app@0.10.7)
'@firebase/messaging': 0.12.10(@firebase/app@0.10.7)
'@firebase/messaging-compat': 0.2.10(@firebase/app-compat@0.2.37)(@firebase/app@0.10.7)
'@firebase/performance': 0.6.8(@firebase/app@0.10.7)
'@firebase/performance-compat': 0.2.8(@firebase/app-compat@0.2.37)(@firebase/app@0.10.7)
'@firebase/remote-config': 0.4.8(@firebase/app@0.10.7)
'@firebase/remote-config-compat': 0.2.8(@firebase/app-compat@0.2.37)(@firebase/app@0.10.7)
'@firebase/storage': 0.12.6(@firebase/app@0.10.7)
'@firebase/storage-compat': 0.3.9(@firebase/app-compat@0.2.37)(@firebase/app-types@0.9.2)(@firebase/app@0.10.7)
'@firebase/util': 1.9.7
'@firebase/vertexai-preview': 0.0.3(@firebase/app-types@0.9.2)(@firebase/app@0.10.7)
'@firebase/ai': 2.0.0(@firebase/app-types@0.9.3)(@firebase/app@0.14.0)
'@firebase/analytics': 0.10.18(@firebase/app@0.14.0)
'@firebase/analytics-compat': 0.2.24(@firebase/app-compat@0.5.0)(@firebase/app@0.14.0)
'@firebase/app': 0.14.0
'@firebase/app-check': 0.11.0(@firebase/app@0.14.0)
'@firebase/app-check-compat': 0.4.0(@firebase/app-compat@0.5.0)(@firebase/app@0.14.0)
'@firebase/app-compat': 0.5.0
'@firebase/app-types': 0.9.3
'@firebase/auth': 1.11.0(@firebase/app@0.14.0)
'@firebase/auth-compat': 0.6.0(@firebase/app-compat@0.5.0)(@firebase/app-types@0.9.3)(@firebase/app@0.14.0)
'@firebase/data-connect': 0.3.11(@firebase/app@0.14.0)
'@firebase/database': 1.1.0
'@firebase/database-compat': 2.1.0
'@firebase/firestore': 4.9.0(@firebase/app@0.14.0)
'@firebase/firestore-compat': 0.4.0(@firebase/app-compat@0.5.0)(@firebase/app-types@0.9.3)(@firebase/app@0.14.0)
'@firebase/functions': 0.13.0(@firebase/app@0.14.0)
'@firebase/functions-compat': 0.4.0(@firebase/app-compat@0.5.0)(@firebase/app@0.14.0)
'@firebase/installations': 0.6.19(@firebase/app@0.14.0)
'@firebase/installations-compat': 0.2.19(@firebase/app-compat@0.5.0)(@firebase/app-types@0.9.3)(@firebase/app@0.14.0)
'@firebase/messaging': 0.12.23(@firebase/app@0.14.0)
'@firebase/messaging-compat': 0.2.23(@firebase/app-compat@0.5.0)(@firebase/app@0.14.0)
'@firebase/performance': 0.7.8(@firebase/app@0.14.0)
'@firebase/performance-compat': 0.2.21(@firebase/app-compat@0.5.0)(@firebase/app@0.14.0)
'@firebase/remote-config': 0.6.6(@firebase/app@0.14.0)
'@firebase/remote-config-compat': 0.2.19(@firebase/app-compat@0.5.0)(@firebase/app@0.14.0)
'@firebase/storage': 0.14.0(@firebase/app@0.14.0)
'@firebase/storage-compat': 0.4.0(@firebase/app-compat@0.5.0)(@firebase/app-types@0.9.3)(@firebase/app@0.14.0)
'@firebase/util': 1.13.0
transitivePeerDependencies:
- '@react-native-async-storage/async-storage'
@ -19836,8 +19921,6 @@ snapshots:
safer-buffer@2.1.2: {}
safevalues@0.6.0: {}
sass-lookup@6.0.1:
dependencies:
commander: 12.1.0
@ -21155,10 +21238,6 @@ snapshots:
undici-types@5.26.5: {}
undici@5.28.4:
dependencies:
'@fastify/busboy': 2.1.1
undici@7.12.0: {}
unescape-js@1.1.4:
@ -21642,6 +21721,8 @@ snapshots:
transitivePeerDependencies:
- encoding
web-vitals@4.2.4: {}
webidl-conversions@3.0.1: {}
webidl-conversions@4.0.2: {}