From 3f662e7d4fc0bd422fd8c4d406e01d45fc77ad07 Mon Sep 17 00:00:00 2001 From: Aadit Kamat Date: Sun, 25 Feb 2024 21:50:01 -0500 Subject: [PATCH 1/4] Update socket tests (#185) * Update socket tests * Remove unused type * Update comment in socketio.test.ts --------- Co-authored-by: Phoenix <71522316+h1divp@users.noreply.github.com> --- server/src/tests/socketio.test.ts | 294 +++++++++++++++++------------- 1 file changed, 168 insertions(+), 126 deletions(-) diff --git a/server/src/tests/socketio.test.ts b/server/src/tests/socketio.test.ts index 3c79bbaeb..51dc456f7 100644 --- a/server/src/tests/socketio.test.ts +++ b/server/src/tests/socketio.test.ts @@ -1,146 +1,188 @@ // Testing for socket.io endpoints -import { io as io } from 'socket.io-client' -import { v4 as uuidv4 } from 'uuid'; -import { Message } from '../types/Message'; +import { createServer } from "node:http"; +import { io as ioc } from "socket.io-client"; +import { Server } from "socket.io"; +import { v4 as uuidv4 } from "uuid"; -const socket_test_client_port = process.env.socket_test_client_port; -console.log("Socket clients are listening on port", socket_test_client_port) - -const SECONDS_TIMEOUT = 10; const SECONDS_MULTIPLIER = 1000; -const NUM_CLIENTS = 3; // Adjust the number of clients as needed. Do not go over 300 to prevent being blocked by Firebase. -const exampleMsg: Message = { - uid: uuidv4(), // random Ids; not a real UID - msgId: uuidv4(), - msgContent: "MESSAGE CONTENT", - timeSent: 9999, - location: { - lat: 10, - lon: 10 - // Geohash will be calculated by the server since it is not included with the message. +jest.setTimeout(60 * SECONDS_MULTIPLIER); + +describe("socket-load-tests", () => { + let clientSockets = []; + let httpServer; + let httpServerAddr; + let ioServer; + const numClients = 100; // Adjust the number of clients as needed. Do not go over 300 to prevent being blocked by Firebase. + + beforeAll((done) => { + httpServer = createServer().listen(); + httpServerAddr = httpServer.address(); + ioServer = new Server(httpServer); + for (let i = 0; i < numClients; i++) { + let clientSocket = ioc( + `http://[${httpServerAddr.address}]:${httpServerAddr.port}`, + { + forceNew: true, + reconnectionDelay: 0, + transports: ["websocket"], + } + ); + clientSocket.on("connect", () => { + done(); + }); + clientSockets.push(clientSocket); } -} - -jest.setTimeout(SECONDS_TIMEOUT * SECONDS_MULTIPLIER); - -const sleep = (ms) => { - return new Promise(resolve => setTimeout(resolve, ms)); -}; - -const connectClients = async () => { - const clients = []; - - for (let i = 0; i < NUM_CLIENTS; i++) { - const client = io(`http://localhost:${socket_test_client_port}`); - await new Promise(resolve => client.on('connect', resolve)); // Why is this an error? IDK - clients.push(client); - } - - return clients; -}; + done(); + }); -const disconnectClients = (clients) => { - clients.forEach(client => client.disconnect()); -}; + afterAll((done) => { + ioServer.close(); + httpServer.close(); + for (let i = 0; i < numClients; i++) { + clientSockets[i].disconnect(); + } + done(); + }); -describe('socket-load-tests', () => { - let clients; + test("Simultaneous Ping", (done) => { + ioServer.on("ping", (cb) => { + cb("pong"); + }); + for (let i = 0; i < numClients; i++) { + clientSockets[i].emit("ping", (response) => { + expect(response).toBe("pong"); + }); + } + done(); + }); - beforeAll(async () => { - clients = await connectClients(); + test("Simultaneous Message", async () => { + ioServer.on("ping", (cb) => { + cb("pong"); + }); + for (let i = 0; i < numClients; i++) { + clientSockets[i].emit( + "message", + { + userId: "userId", + msgId: uuidv4(), + msgContent: `This is message ${i}`, + lat: 10, + lon: 10, + timeSent: 99999999, + }, + (response) => { + expect(response).toBe("message recieved"); + } + ); + } }); +}); - afterAll(() => { - disconnectClients(clients); +describe("socket-tests", () => { + let clientSockets = []; + let httpServer; + let httpServerAddr; + let ioServer; + const numClients = 5; + + beforeAll((done) => { + httpServer = createServer().listen(); + httpServerAddr = httpServer.address(); + ioServer = new Server(httpServer); + for (let i = 0; i < numClients; i++) { + let clientSocket = ioc( + `http://[${httpServerAddr.address}]:${httpServerAddr.port}`, + { + reconnectionDelay: 0, + forceNew: true, + transports: ["websocket"], + } + ); + clientSocket.on("connect", () => { + done(); + }); + clientSockets.push(clientSocket); + } + done(); }); - test('Simultaneous Ping', async () => { - const pingPromises = clients.map(client => new Promise(resolve => client.emit('ping', resolve))); - const responses = await Promise.all(pingPromises); + afterAll((done) => { + ioServer.close(); + httpServer.close(); + for (let i = 0; i < numClients; i++) { + clientSockets[i].disconnect(); + } + done(); + }); - responses.forEach(response => { - expect(response).toBe('pong'); + test("Ping", (done) => { + ioServer.on("ping", (cb) => { + cb("pong"); + }); + clientSockets[0].emit("ping", (response) => { + expect(response).toBe("pong"); }); + done(); }); - test('Simultaneous Message', async () => { - let count = 0; - const messagePromises = clients.map(client => { - return new Promise(async resolve => { - client.emit('message', exampleMsg, resolve); - count++; - await sleep(200) - }); + test("Send message", (done) => { + ioServer.on("ping", (cb) => { + cb("pong"); }); - - const responses = await Promise.all(messagePromises); - responses.forEach(response => { - expect(response).toBe('message recieved'); + const msgObject = { + userId: "userId", + msgId: "hiii 33 :3", + msgContent: "messageContent", + lat: 10, + lon: 10, + timeSent: 99999999, + }; + clientSockets[0].emit("message", msgObject, (response) => { + expect(response).toBe("message recieved"); }); - }) -}); - -describe("socket-tests", () => { - let user1, user2 - - beforeAll((done) => { - user1 = io(`http://localhost:${socket_test_client_port}`) - user1.on('connect', done) - user2 = io(`http://localhost:${socket_test_client_port}`) - user2.on('connect', done) - }) + done(); + }); - afterAll(() => { - user1.disconnect() - user2.disconnect() - }) + test("Update locations", (done) => { + const userCoords = [ + { lat: 29.64888, lon: -82.3442 }, // Turlington Hall pin on Google Maps + { lat: 29.64881, lon: -82.34429 }, // 8.65 meters SW of user 1 + { lat: 29.64881, lon: -82.34429 }, // 8.65 meters SW of user 1 + { lat: 29.64881, lon: -82.34429 }, // 8.65 meters SW of user 1 + { lat: 29.64881, lon: -82.34429 }, // 8.65 meters SW of user 1 + ]; + + for (let i = 0; i < userCoords.length; i++) { + clientSockets[i].emit("updateLocation", userCoords[0], (response) => { + expect(response).toBe("location updated"); + }); + } + done(); + }); - test('Ping', (done) => { - user1.emit('ping', (response) => { - expect(response).toBe('pong') - done() - }) - }) - test('Send message', (done) => { - user1.emit('message', exampleMsg, (response) => { - expect(response).toBe('message recieved') - done() - }) - }) - test('Update locations', (done) => { - const user1Coords = { lat: 29.64888, lon: -82.34420 } // Turlington Hall pin on Google Maps - const user2Coords = { lat: 29.64881, lon: -82.34429 } // 8.65 meters SW of user 1 - user1.emit('updateLocation', user1Coords, (response) => { - expect(response).toBe("location updated") - }) - user2.emit('updateLocation', user2Coords, (response) => { - expect(response).toBe("location updated") - }) - sleep(5000) - done() - }) - // test('Send message to user', async (done) => { - // // const user2Coords = { lat: 29.64881, lon: -82.34429 } // 8.65 meters SW of user 1 - // const user2Coords = { lat: 29.6489940, lon: -82.344096 } // 8.65 meters SW of user 1 - // const user2Message: Message = { - // uid: user2.id, // a socket id - // msgId: uuidv4(), - // msgContent: "omggg hi!!!! :3", - // timeSent: 9999, - // location: { - // lat: user2Coords.lat, - // lon: user2Coords.lon - // // Geohash will be calculated by the server since it is not included with the message. - // } - // } - // user1.on('message', (message: Message) => { - // console.log(`User 2 recieved message: ${message}`) - // expect(message.msgContent).toBe("omggg hi!!!! :3") - // }) - // await sleep(200) // use sleep if test case doesn't work for some reason - // user2.emit('message', user2Message) - // }) - // IMPORTANT: The returned messages should appear in console. The correct way to use expect() has not been figured out yet for this test. - // TODO: Find a way for expect() to be verified after messages return. -}) + test("Send message to user", (done) => { + const user2Coords = { lat: 29.64881, lon: -82.34429 }; // 8.65 meters SW of user 1 + const user2Message = { + userId: clientSockets[1].id, + msgId: "testid", + msgContent: "omggg hi!!!! :3", + lat: user2Coords.lat, + lon: user2Coords.lon, + timeSent: 999999, + }; + for (let i = 0; i < clientSockets.length; i++) { + if (i != 1) { + clientSockets[i].on("message", (message) => { + console.log(`User 2 recieved message ${message}`); + expect(message).toBe("omggg hi!!!! :3"); + }); + } + } + clientSockets[1].emit("message", user2Message); + done(); + // TODO: This test case will return true, but the sent message is actually never verified. + // The real verification of this message to lead to a pass/fail should be worked on. + }); +}); From d2a224112cf1e092f314356a95653c07b73f3b11 Mon Sep 17 00:00:00 2001 From: Alexander Wang <98280966+AlexanderWangY@users.noreply.github.com> Date: Thu, 29 Feb 2024 00:19:57 -0500 Subject: [PATCH 2/4] Firebase Admin Refactor + JWT feature (#180) * Set up Firebase-Admin in adminInit.ts (#155) * new branch + function fix * small bug fixes * fixes pt2 * JWT WIP * new branch + function fix * small bug fixes * fixes pt2 * JWT WIP * new branch + function fix * small bug fixes * fixes pt2 * JWT WIP * new branch + function fix * small bug fixes * added passport * started auth + admin sdk * removed passport * added private key to gitignore * Delete server/private_keys/private.json --------- Co-authored-by: AlexanderWangY * Refactored most of the actions (#156) * new branch + function fix * small bug fixes * fixes pt2 * JWT WIP * new branch + function fix * small bug fixes * fixes pt2 * JWT WIP * new branch + function fix * small bug fixes * fixes pt2 * JWT WIP * new branch + function fix * small bug fixes * added passport * started auth + admin sdk * removed passport * added private key to gitignore * Delete server/private_keys/private.json * initializing firestore in admin * finished most of action refactoring * Made error case for email in use display correctly in front end (#158) * changed getConnectedUsers to admin * migrated to firebase-admin --------- Co-authored-by: AlexanderWangY Co-authored-by: Mohammed Ali <146048575+Phantom0110@users.noreply.github.com> * Added JWT on top of Firebase-Admin (#178) * Made error case for email in use display correctly in front end * Made error case for email in use display correctly in front end (#158) * Cleaned up useEffect function #159 * Added testing pipeline (#175) * Create main.yml * Update main.yml * Update _layout.tsx * Update main.yml * Update socketio.test.ts * Update socketio.test.ts * Update _layout.tsx * User Context and User Type created and wrapped chat screen (#131) * added user context * Added userID and displayName * moved user and display name generation into UserProvider * Improved UserContext implementation Amongst these changes, the user type on the frontend has been edited in order to prevent hidden functions that would pull information into the UserContext from other contexts. The message type was also modified to keep a new author section with a displayName attribute. An issue should be created for a socket API endpoint for grabbing the displayName, and one to set it in a connectedUser document in the databse. * updated package lock --------- Co-authored-by: h1divp <71522316+h1divp@users.noreply.github.com> * Set up Firebase-Admin in adminInit.ts (#155) * new branch + function fix * small bug fixes * fixes pt2 * JWT WIP * new branch + function fix * small bug fixes * fixes pt2 * JWT WIP * new branch + function fix * small bug fixes * fixes pt2 * JWT WIP * new branch + function fix * small bug fixes * added passport * started auth + admin sdk * removed passport * added private key to gitignore * Delete server/private_keys/private.json --------- Co-authored-by: AlexanderWangY * Refactored most of the actions (#156) * new branch + function fix * small bug fixes * fixes pt2 * JWT WIP * new branch + function fix * small bug fixes * fixes pt2 * JWT WIP * new branch + function fix * small bug fixes * fixes pt2 * JWT WIP * new branch + function fix * small bug fixes * added passport * started auth + admin sdk * removed passport * added private key to gitignore * Delete server/private_keys/private.json * initializing firestore in admin * finished most of action refactoring * Made error case for email in use display correctly in front end (#158) * changed getConnectedUsers to admin * migrated to firebase-admin --------- Co-authored-by: AlexanderWangY Co-authored-by: Mohammed Ali <146048575+Phantom0110@users.noreply.github.com> * added middleware --------- Co-authored-by: Phantom0110 Co-authored-by: Mohammed Ali <146048575+Phantom0110@users.noreply.github.com> Co-authored-by: AaronGibson2 <149017602+AaronGibson2@users.noreply.github.com> Co-authored-by: h1divp <71522316+h1divp@users.noreply.github.com> Co-authored-by: AlexanderWangY * Delete server/src/private_key/private.json * Update main.yml * Updated pipeline to reflect firebase-admin * Update main.yml * Update main.yml * Create subdirectory before creating service account JSON (#187) * Update socket tests (#185) * Update socket tests * Remove unused type * Update comment in socketio.test.ts --------- Co-authored-by: Phoenix <71522316+h1divp@users.noreply.github.com> * Create subdirectory before creating service account JSON --------- Co-authored-by: Phoenix <71522316+h1divp@users.noreply.github.com> * made changes to collection name + socket test load testing * Added socketIo.connect() * Remade collection name changes * updated location of firebase secrets, added comment about it in config_example.md * renamed file to firebaseInit from adminInit * Updated comment --------- Co-authored-by: AlexanderWangY Co-authored-by: Mohammed Ali <146048575+Phantom0110@users.noreply.github.com> Co-authored-by: Phantom0110 Co-authored-by: AaronGibson2 <149017602+AaronGibson2@users.noreply.github.com> Co-authored-by: h1divp <71522316+h1divp@users.noreply.github.com> Co-authored-by: Aadit Kamat --- .github/workflows/main.yml | 11 +- .../Auth/AuthenticationResponse.tsx | 70 +- client/src/components/Auth/LoginScreen.tsx | 15 +- client/src/configs/firebaseConfig.ts | 8 +- client/src/contexts/LocationContext.tsx | 8 +- client/src/contexts/SocketContext.tsx | 53 +- client/src/services/store.ts | 1 - server/.gitignore | 3 + server/config_example.md | 11 +- server/package-lock.json | 1617 ++++++++++++----- server/package.json | 2 +- server/src/actions/createConnectedUser.ts | 9 +- server/src/actions/createMessage.ts | 6 +- server/src/actions/deleteConnectedUser.ts | 17 +- server/src/actions/getConnectedUsers.ts | 31 +- server/src/actions/updateConnectedUser.ts | 25 +- server/src/index.ts | 46 +- server/src/tests/socketio.test.ts | 2 +- server/src/utilities/firebaseInit.ts | 35 +- 19 files changed, 1329 insertions(+), 641 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 63e78b21a..d20bb00ec 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,12 +23,19 @@ jobs: run: npm ci working-directory: server/ - - name: Set up environment variables + - name: Create subdirectory for service account JSON run: | mkdir private_key - echo "${{ secrets.SERVICE_ACCOUNT_SECRET }}" > private_key/private.json working-directory: server/src + - name: Create service account JSON + id: create-service-account-json + uses: jsdaniell/create-json@1.1.2 + with: + name: "private.json" + json: ${{ secrets.SERVICE_ACCOUNT_SECRET }} + dir: 'server/src/private_key/' + - name: Compile TypeScript files run: npx tsc working-directory: server/ diff --git a/client/src/components/Auth/AuthenticationResponse.tsx b/client/src/components/Auth/AuthenticationResponse.tsx index c2955772b..041d7b4b8 100644 --- a/client/src/components/Auth/AuthenticationResponse.tsx +++ b/client/src/components/Auth/AuthenticationResponse.tsx @@ -1,16 +1,18 @@ import React from "react"; -import { StyleSheet, Text, Dimensions, TouchableOpacity} from "react-native"; +import { StyleSheet, Text, Dimensions, TouchableOpacity } from "react-native"; import { FirebaseError } from "firebase/app"; import { User } from "firebase/auth"; //Type to handle Authentication Responses from firebase -export type AuthenticationResponse = { - user: User | null; - error?: undefined; -} | { - user?: undefined; - error: unknown; -} +export type AuthenticationResponse = + | { + user: User | null; + error?: undefined; + } + | { + user?: undefined; + error: unknown; + }; export class CustomError { public code: string; @@ -23,7 +25,10 @@ export class CustomError { } //Custom responses -export const inValidEmailResponse = new CustomError("Invalid Email", "Please provide a valid email address") +export const inValidEmailResponse = new CustomError( + "Invalid Email", + "Please provide a valid email address" +); //Function that decodes the error code const decodeFirebaseError = (error: FirebaseError) => { @@ -47,54 +52,56 @@ const decodeFirebaseError = (error: FirebaseError) => { const decodeCustomError = (error: CustomError) => { return error.message; -} +}; //Function that handles the response depending on type -function handleResponse(response: AuthenticationResponse) { - if(response?.user) { +const handleResponse = (response: AuthenticationResponse) => { + if (response?.user) { + // If the user is not undefined return ""; } - console.log(response.error) - - if(response.error instanceof FirebaseError) { + if (response.error instanceof FirebaseError) { + // If the error is a firebase error return decodeFirebaseError(response.error); } - - if(response.error instanceof CustomError) { + // If the error is a custom error + if (response.error instanceof CustomError) { + // If the error is a custom error return decodeCustomError(response.error); } - return "Unknown error" -} + return "Unknown error"; +}; -//Something +// Authentication Message Component Props interface AuthenticationErrorMessageProps { response: AuthenticationResponse | undefined; onPress?: () => void; } -export const AuthenticationErrorMessage: React.FC = ({ response, onPress }) => { - if( response === undefined ) { +export const AuthenticationErrorMessage: React.FC< + AuthenticationErrorMessageProps +> = ({ response, onPress }) => { + if (response === undefined) { return null; } - const errorMessage = handleResponse(response) + const errorMessage = handleResponse(response); return ( - errorMessage && - + errorMessage && ( + {errorMessage} - + + ) ); -} - +}; const styles = StyleSheet.create({ error_text: { color: "white", fontSize: Dimensions.get("window").height * 0.02, - }, error_container: { display: "flex", @@ -105,7 +112,6 @@ const styles = StyleSheet.create({ marginTop: Dimensions.get("window").height * 0.005, width: Dimensions.get("window").width * 0.9, borderRadius: 10, - padding: 10 - } + padding: 10, + }, }); - diff --git a/client/src/components/Auth/LoginScreen.tsx b/client/src/components/Auth/LoginScreen.tsx index 477af597c..d6bb18018 100644 --- a/client/src/components/Auth/LoginScreen.tsx +++ b/client/src/components/Auth/LoginScreen.tsx @@ -27,17 +27,23 @@ const LoginScreen = () => { const [email, setEmail] = React.useState(""); const [password, setPassword] = React.useState(""); const [authResponse, setAuthResponse] = React.useState(); - const [invalidLogin, invalidateLogin] = React.useState(false); + const [invalidLogin, invalidateLogin] = React.useState(false); // Possbily change this? + // Sign in function with email and password const onHandleSubmit = async () => { + Keyboard.dismiss(); setAuthResponse(await appSignIn(email, password)); + }; + + // Listens for the response from the sign in function + useEffect(() => { if (authResponse?.user) { router.replace("(home)/chatchannel"); } else if (authResponse?.error) { console.log(authResponse.error); invalidateLogin(true); } - }; + }, [authResponse]) useEffect(() => { setEmail(inputEmail?.toString() || ""); // On load of the page, set the email to the inputEmail if they entered it! @@ -76,7 +82,10 @@ const LoginScreen = () => { - setAuthResponse(undefined)} /> + { + setAuthResponse(undefined) + invalidateLogin(false) + }} /> diff --git a/client/src/configs/firebaseConfig.ts b/client/src/configs/firebaseConfig.ts index 28f8c1b95..0468e3797 100644 --- a/client/src/configs/firebaseConfig.ts +++ b/client/src/configs/firebaseConfig.ts @@ -6,10 +6,10 @@ import {API_KEY, AUTH_DOMAIN, PROJECT_ID, STORAGE_BUCKET, MESSAGING_SENDER_ID, A const firebaseConfig = { apiKey: API_KEY || "Mock-Key", authDomain: AUTH_DOMAIN, - projectId: PROJECT_ID, - storageBucket: STORAGE_BUCKET, - messagingSenderId: MESSAGING_SENDER_ID, - appId: APP_ID, + // projectId: PROJECT_ID, + // storageBucket: STORAGE_BUCKET, + // messagingSenderId: MESSAGING_SENDER_ID, + // appId: APP_ID, }; let app; diff --git a/client/src/contexts/LocationContext.tsx b/client/src/contexts/LocationContext.tsx index 6980f9184..104b1c96b 100644 --- a/client/src/contexts/LocationContext.tsx +++ b/client/src/contexts/LocationContext.tsx @@ -17,9 +17,9 @@ const LocationContext = createContext(null); const getLocation = async () => { return await Location.getCurrentPositionAsync({ - accuracy: Location.Accuracy.Balanced + accuracy: Location.Accuracy.Balanced, }); // Change accuracy while testing. Could become .env variable. -} +}; export const useLocation = () => { return useContext(LocationContext); @@ -66,13 +66,13 @@ export const LocationProvider = ({ } catch (error) { console.error("Error fetching location:", error); } - }, Number(LOCATION_REFRESH_RATE)); // Send location every few seconds + }, Number(LOCATION_REFRESH_RATE)); // Fetch location every 3 seconds // Cleanup function to clear interval when component unmounts return () => clearInterval(interval); })(); - return () => console.log("Location dismounted"); + return () => console.log("[LOG]: Cleaning up location useEffect"); }, []); diff --git a/client/src/contexts/SocketContext.tsx b/client/src/contexts/SocketContext.tsx index 47f294a47..17c2e285c 100644 --- a/client/src/contexts/SocketContext.tsx +++ b/client/src/contexts/SocketContext.tsx @@ -2,6 +2,7 @@ import React, { createContext, useContext, useEffect, useState } from "react"; import { io, Socket } from "socket.io-client"; import { useLocation } from "./LocationContext"; import { EXPO_IP } from "@env"; +import { AuthStore } from "../services/store"; const SocketContext = createContext(null); @@ -11,27 +12,57 @@ export const useSocket = () => { export const SocketProvider = ({ children }: { children: React.ReactNode }) => { const [socket, setSocket] = useState(null); + const [mounted, setMounted] = useState(false); const locationContext = useLocation(); + useEffect(() => { - let isMounted = true; + const getToken = async () => { + const token = await AuthStore.getRawState().userAuthInfo?.getIdToken(); + console.log("Token:", token); + return token; + } + + const initializeSocket = async () => { + const token = await getToken(); + const socketIo = io(`http://${EXPO_IP}:8080`, { + auth: { + token: token, + } + }); - const socketIo = io(`http://${EXPO_IP}:8080`); // Hardcoded IP address + socketIo.connect() + setSocket(socketIo); + setMounted(true); + } - socketIo.on("connect", () => { - if (isMounted) { - setSocket(socketIo); - } else { - console.log("Socket not mounted"); - } - }); + if (!mounted) { + initializeSocket(); + } return () => { - isMounted = false; - socket?.disconnect(); + console.log("[LOG]: Cleaning up intializeSocket useEffect"); }; }, []); + // Listen to the socket state and run once the socket is set! + useEffect(() => { + + if (!socket) return; + + socket.on("connect", () => { + console.log("Connected to server"); + } + ); + + return () => { + console.log("[LOG]: Cleaning up sockets and mounted state."); + socket.disconnect(); + setSocket(null); + setMounted(false); + } + }, [socket]); + useEffect(() => { // TODO: Refactor this useEffect into a different file (service?) outside of the context, as it is not part of the purpose of a context. if ( diff --git a/client/src/services/store.ts b/client/src/services/store.ts index 84e9a8b34..9b5321256 100644 --- a/client/src/services/store.ts +++ b/client/src/services/store.ts @@ -32,7 +32,6 @@ export const appSignIn = async (email: string, password: string) => { store.userAuthInfo = response?.user; store.isLoggedin = response?.user ? true : false; }); - return { user: auth.currentUser }; } catch (e) { return { error: e }; diff --git a/server/.gitignore b/server/.gitignore index 59a9766a7..81da29c6f 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -132,6 +132,9 @@ dist # Build files build +# Private Key JSON +./private_key/* + # Other .env build/ diff --git a/server/config_example.md b/server/config_example.md index 184fd8709..8ffb34245 100644 --- a/server/config_example.md +++ b/server/config_example.md @@ -1,13 +1,10 @@ # dotenv config file (copy config to a new file named `.env`) # **Do not delete this file** -# Firebase config -API_KEY = place_your_apiKey_here -AUTH_DOMAIN = place_your_authDomain_here -PROJECT_ID = place_your_projectId_here -STORAGE_BUCKET = place_your_storageBucket_here -MESSAGING_SENDER_ID = place_your_messagingSenderId_here -APP_ID = place_your_appId_here +# To configure firebase: +# - Go to project settings > service accounts, +# - Make a new private key for the Node.js SDK +# - Paste all contents into ".firebase-secrets.json" in server/ # Location message_outreach_radius = 100 # meters diff --git a/server/package-lock.json b/server/package-lock.json index 52a5aafd3..564e301cd 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -13,7 +13,7 @@ "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", - "firebase": "^10.5.0", + "firebase-admin": "^12.0.0", "geofire-common": "^6.0.0", "socket.io": "^4.7.4", "uuid": "^9.0.1" @@ -1804,169 +1804,21 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", - "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==", - "engines": { - "node": ">=14" - } - }, - "node_modules/@firebase/analytics": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.1.tgz", - "integrity": "sha512-5mnH1aQa99J5lZMJwTNzIoRc4yGXHf+fOn+EoEWhCDA3XGPweGHcylCbqq+G1wVJmfILL57fohDMa8ftMZ+44g==", - "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/installations": "0.6.5", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/analytics-compat": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.7.tgz", - "integrity": "sha512-17VCly4P0VFBDqaaal7m1nhyYQwsygtaTpSsnc51sFPRrr9XIYtnD8ficon9fneEGEoJQ2g7OtASvhwX9EbK8g==", - "dependencies": { - "@firebase/analytics": "0.10.1", - "@firebase/analytics-types": "0.8.0", - "@firebase/component": "0.6.5", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/analytics-types": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.0.tgz", - "integrity": "sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw==" - }, - "node_modules/@firebase/app": { - "version": "0.9.27", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.9.27.tgz", - "integrity": "sha512-p2Dvl1ge4kRsyK5+wWcmdAIE9MSwZ0pDKAYB51LZgZuz6wciUZk4E1yAEdkfQlRxuHehn+Ol9WP5Qk2XQZiHGg==", - "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.4", - "idb": "7.1.1", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/app-check": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.2.tgz", - "integrity": "sha512-A2B5+ldOguYAeqW1quFN5qNdruSNRrg4W59ag1Eq6QzxuHNIkrE+TrapfrW/z5NYFjCxAYqr/unVCgmk80Dwcg==", - "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/app-check-compat": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.9.tgz", - "integrity": "sha512-7LxyupQ8XeEHRh72mO+tqm69kHT6KbWi2KtFMGedJ6tNbwzFzojcXESMKN8RpADXbYoQgY3loWMJjMx4r2Zt7w==", - "dependencies": { - "@firebase/app-check": "0.8.2", - "@firebase/app-check-types": "0.5.0", - "@firebase/component": "0.6.5", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, "node_modules/@firebase/app-check-interop-types": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.0.tgz", "integrity": "sha512-xAxHPZPIgFXnI+vb4sbBjZcde7ZluzPPaSK7Lx3/nmuVk4TjZvnL8ONnkd4ERQKL8WePQySU+pRcWkh8rDf5Sg==" }, - "node_modules/@firebase/app-check-types": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.0.tgz", - "integrity": "sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ==" - }, - "node_modules/@firebase/app-compat": { - "version": "0.2.27", - "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.27.tgz", - "integrity": "sha512-SYlqocfUDKPHR6MSFC8hree0BTiWFu5o8wbf6zFlYXyG41w7TcHp4wJi4H/EL5V6cM4kxwruXTJtqXX/fRAZtw==", - "dependencies": { - "@firebase/app": "0.9.27", - "@firebase/component": "0.6.5", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/app-types": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz", "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==" }, - "node_modules/@firebase/auth": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.6.0.tgz", - "integrity": "sha512-Qhl35eJTV6BwvuueTPCY6x8kUlYyzALtjp/Ws0X3fw3AnjVVfuVb7oQ3Xh5VPVfMFhaIuUAd1KXwcAuIklkSDw==", - "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0", - "undici": "5.26.5" - }, - "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.2", - "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.2.tgz", - "integrity": "sha512-pRgje5BPCNR1vXyvGOVXwOHtv88A2WooXfklI8sV7/jWi03ExFqNfpJT26GUo/oD39NoKJ3Kt6rD5gVvdV7lMw==", - "dependencies": { - "@firebase/auth": "1.6.0", - "@firebase/auth-types": "0.12.0", - "@firebase/component": "0.6.5", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0", - "undici": "5.26.5" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, "node_modules/@firebase/auth-interop-types": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz", "integrity": "sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg==" }, - "node_modules/@firebase/auth-types": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.0.tgz", - "integrity": "sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA==", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" - } - }, "node_modules/@firebase/component": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.5.tgz", @@ -2012,291 +1864,208 @@ "@firebase/util": "1.9.4" } }, - "node_modules/@firebase/firestore": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.4.2.tgz", - "integrity": "sha512-YaX6ypa/RzU6OkxzUQlpSxwhOIWdTraCNz7sMsbaSEjjl/pj/QvX6TqjkdWGzuBYh2S6rz7ErhDO0g39oZZw/g==", - "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.4", - "@firebase/webchannel-wrapper": "0.10.5", - "@grpc/grpc-js": "~1.9.0", - "@grpc/proto-loader": "^0.7.8", - "tslib": "^2.1.0", - "undici": "5.26.5" - }, - "engines": { - "node": ">=10.10.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/firestore-compat": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.25.tgz", - "integrity": "sha512-+xI7WmsgZCBhMn/+uhDKcg+lsOUJ9FJyt5PGTzkFPbCsozWfeQZ7eVnfPh0rMkUOf0yIQ924RIe04gwvEIbcoQ==", + "node_modules/@firebase/logger": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz", + "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==", "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/firestore": "4.4.2", - "@firebase/firestore-types": "3.0.0", - "@firebase/util": "1.9.4", "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/firestore-types": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.0.tgz", - "integrity": "sha512-Meg4cIezHo9zLamw0ymFYBD4SMjLb+ZXIbuN7T7ddXN6MGoICmOTq3/ltdCGoDCS2u+H1XJs2u/cYp75jsX9Qw==", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" - } - }, - "node_modules/@firebase/functions": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.1.tgz", - "integrity": "sha512-3uUa1hB79Gmy6E1gHTfzoHeZolBeHc/I/n3+lOCDe6BOos9AHmzRjKygcFE/7VA2FJjitCE0K+OHI6+OuoY8fQ==", - "dependencies": { - "@firebase/app-check-interop-types": "0.3.0", - "@firebase/auth-interop-types": "0.2.1", - "@firebase/component": "0.6.5", - "@firebase/messaging-interop-types": "0.2.0", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0", - "undici": "5.26.5" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/functions-compat": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.7.tgz", - "integrity": "sha512-uXe6Kmku5lNogp3OpPBcOJbSvnaCOn+YxS3zlXKNU6Q/NLwcvO3RY1zwYyctCos2RemEw3KEQ7YdzcECXjHWLw==", + "node_modules/@firebase/util": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.4.tgz", + "integrity": "sha512-WLonYmS1FGHT97TsUmRN3qnTh5TeeoJp1Gg5fithzuAgdZOUtsYECfy7/noQ3llaguios8r5BuXSEiK82+UrxQ==", "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/functions": "0.11.1", - "@firebase/functions-types": "0.6.0", - "@firebase/util": "1.9.4", "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/functions-types": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.0.tgz", - "integrity": "sha512-hfEw5VJtgWXIRf92ImLkgENqpL6IWpYaXVYiRkFY1jJ9+6tIhWM7IzzwbevwIIud/jaxKVdRzD7QBWfPmkwCYw==" - }, - "node_modules/@firebase/installations": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.5.tgz", - "integrity": "sha512-0xxnQWw8rSRzu0ZOCkZaO+MJ0LkDAfwwTB2Z1SxRK6FAz5xkxD1ZUwM0WbCRni49PKubCrZYOJ6yg7tSjU7AKA==", + "node_modules/@google-cloud/firestore": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.3.0.tgz", + "integrity": "sha512-2IftQLAbCuVp0nTd3neeu+d3OYIegJpV/V9R4USQj51LzJcXPe8h8jZ7j3+svSNhJVGy6JsN0T1QqlJdMDhTwg==", + "optional": true, "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/util": "1.9.4", - "idb": "7.1.1", - "tslib": "^2.1.0" + "fast-deep-equal": "^3.1.1", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^4.0.4", + "protobufjs": "^7.2.5" }, - "peerDependencies": { - "@firebase/app": "0.x" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@firebase/installations-compat": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.5.tgz", - "integrity": "sha512-usvoIaog5CHEw082HXLrKAZ1qd4hIC3N/LDe2NqBgI3pkGE/7auLVM4Gn5gvyryp0x8z/IP1+d9fkGUj2OaGLQ==", + "node_modules/@google-cloud/paginator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.0.tgz", + "integrity": "sha512-87aeg6QQcEPxGCOthnpUjvw4xAZ57G7pL8FS0C4e/81fr3FjkpUpibf1s2v5XGyGhUVGF4Jfg7yEcxqn2iUw1w==", + "optional": true, "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/installations": "0.6.5", - "@firebase/installations-types": "0.5.0", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0" + "arrify": "^2.0.0", + "extend": "^3.0.2" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@firebase/installations-types": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.0.tgz", - "integrity": "sha512-9DP+RGfzoI2jH7gY4SlzqvZ+hr7gYzPODrbzVD82Y12kScZ6ZpRg/i3j6rleto8vTFC8n6Len4560FnV1w2IRg==", - "peerDependencies": { - "@firebase/app-types": "0.x" + "node_modules/@google-cloud/projectify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz", + "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==", + "optional": true, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@firebase/logger": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz", - "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==", - "dependencies": { - "tslib": "^2.1.0" + "node_modules/@google-cloud/promisify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", + "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", + "optional": true, + "engines": { + "node": ">=14" } }, - "node_modules/@firebase/messaging": { - "version": "0.12.6", - "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.6.tgz", - "integrity": "sha512-IORsPp9IPWq4j4yEhTOZ6GAGi3gQwGc+4yexmTAlya+qeBRSdRnJg2iIU/aj+tcKDQYr9RQuQPgHHOdFIx//vA==", + "node_modules/@google-cloud/storage": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.7.0.tgz", + "integrity": "sha512-EMCEY+6JiIkx7Dt8NXVGGjy1vRdSGdHkoqZoqjJw7cEBkT7ZkX0c7puedfn1MamnzW5SX4xoa2jVq5u7OWBmkQ==", + "optional": true, "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/installations": "0.6.5", - "@firebase/messaging-interop-types": "0.2.0", - "@firebase/util": "1.9.4", - "idb": "7.1.1", - "tslib": "^2.1.0" + "@google-cloud/paginator": "^5.0.0", + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "^4.0.0", + "abort-controller": "^3.0.0", + "async-retry": "^1.3.3", + "compressible": "^2.0.12", + "duplexify": "^4.0.0", + "ent": "^2.2.0", + "fast-xml-parser": "^4.3.0", + "gaxios": "^6.0.2", + "google-auth-library": "^9.0.0", + "mime": "^3.0.0", + "mime-types": "^2.0.8", + "p-limit": "^3.0.1", + "retry-request": "^7.0.0", + "teeny-request": "^9.0.0", + "uuid": "^8.0.0" }, - "peerDependencies": { - "@firebase/app": "0.x" + "engines": { + "node": ">=14" } }, - "node_modules/@firebase/messaging-compat": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.6.tgz", - "integrity": "sha512-Q2xC1s4L7Vpss7P7Gy6GuIS+xmJrf/vm9+gX76IK1Bo1TjoKwleCLHt1LHkPz5Rvqg5pTgzzI8qqPhBpZosFCg==", - "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/messaging": "0.12.6", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0" + "node_modules/@google-cloud/storage/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "optional": true, + "bin": { + "mime": "cli.js" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "engines": { + "node": ">=10.0.0" } }, - "node_modules/@firebase/messaging-interop-types": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.0.tgz", - "integrity": "sha512-ujA8dcRuVeBixGR9CtegfpU4YmZf3Lt7QYkcj693FFannwNuZgfAYaTmbJ40dtjB81SAu6tbFPL9YLNT15KmOQ==" + "node_modules/@firebase/webchannel-wrapper": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.10.5.tgz", + "integrity": "sha512-eSkJsnhBWv5kCTSU1tSUVl9mpFu+5NXXunZc83le8GMjMlsWwQArSc7cJJ4yl+aDFY0NGLi0AjZWMn1axOrkRg==" }, - "node_modules/@firebase/performance": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.5.tgz", - "integrity": "sha512-OzAGcWhOqEFH9GdwUuY0oC5FSlnMejcnmSAhR+EjpI7exdDvixyLyCR4txjSHYNTbumrFBG+EP8GO11CNXRaJA==", + "node_modules/@google-cloud/firestore": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.3.0.tgz", + "integrity": "sha512-2IftQLAbCuVp0nTd3neeu+d3OYIegJpV/V9R4USQj51LzJcXPe8h8jZ7j3+svSNhJVGy6JsN0T1QqlJdMDhTwg==", + "optional": true, "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/installations": "0.6.5", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0" + "fast-deep-equal": "^3.1.1", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^4.0.4", + "protobufjs": "^7.2.5" }, - "peerDependencies": { - "@firebase/app": "0.x" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@firebase/performance-compat": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.5.tgz", - "integrity": "sha512-jJwJkVyDcIMBaVGrZ6CRGs4m5FCZsWB5QCWYI3FdsHyIa9/TfteNDilxj9wGciF2naFIHDW7TgE69U5dAH9Ktg==", + "node_modules/@google-cloud/paginator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.0.tgz", + "integrity": "sha512-87aeg6QQcEPxGCOthnpUjvw4xAZ57G7pL8FS0C4e/81fr3FjkpUpibf1s2v5XGyGhUVGF4Jfg7yEcxqn2iUw1w==", + "optional": true, "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/logger": "0.4.0", - "@firebase/performance": "0.6.5", - "@firebase/performance-types": "0.2.0", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0" + "arrify": "^2.0.0", + "extend": "^3.0.2" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@firebase/performance-types": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.0.tgz", - "integrity": "sha512-kYrbr8e/CYr1KLrLYZZt2noNnf+pRwDq2KK9Au9jHrBMnb0/C9X9yWSXmZkFt4UIdsQknBq8uBB7fsybZdOBTA==" - }, - "node_modules/@firebase/remote-config": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.5.tgz", - "integrity": "sha512-rGLqc/4OmxrS39RA9kgwa6JmgWytQuMo+B8pFhmGp3d++x2Hf9j+MLQfhOLyyUo64fNw20J19mLXhrXvKHsjZQ==", - "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/installations": "0.6.5", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" + "node_modules/@google-cloud/projectify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz", + "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==", + "optional": true, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@firebase/remote-config-compat": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.5.tgz", - "integrity": "sha512-ImkNnLuGrD/bylBHDJigSY6LMwRrwt37wQbsGZhWG4QQ6KLzHzSf0nnFRRFvkOZodEUE57Ib8l74d6Yn/6TDUQ==", - "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/logger": "0.4.0", - "@firebase/remote-config": "0.4.5", - "@firebase/remote-config-types": "0.3.0", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "node_modules/@google-cloud/promisify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", + "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", + "optional": true, + "engines": { + "node": ">=14" } }, - "node_modules/@firebase/remote-config-types": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.0.tgz", - "integrity": "sha512-RtEH4vdcbXZuZWRZbIRmQVBNsE7VDQpet2qFvq6vwKLBIQRQR5Kh58M4ok3A3US8Sr3rubYnaGqZSurCwI8uMA==" - }, - "node_modules/@firebase/storage": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.12.1.tgz", - "integrity": "sha512-KJ5NV7FUh54TeTlEjdkTTX60ciCKOp9EqlbLnpdcXUYRJg0Z4810TXbilPc1z7fTIG4iPjtdi95bGE9n4dBX8A==", + "node_modules/@google-cloud/storage": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.7.0.tgz", + "integrity": "sha512-EMCEY+6JiIkx7Dt8NXVGGjy1vRdSGdHkoqZoqjJw7cEBkT7ZkX0c7puedfn1MamnzW5SX4xoa2jVq5u7OWBmkQ==", + "optional": true, "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0", - "undici": "5.26.5" + "@google-cloud/paginator": "^5.0.0", + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "^4.0.0", + "abort-controller": "^3.0.0", + "async-retry": "^1.3.3", + "compressible": "^2.0.12", + "duplexify": "^4.0.0", + "ent": "^2.2.0", + "fast-xml-parser": "^4.3.0", + "gaxios": "^6.0.2", + "google-auth-library": "^9.0.0", + "mime": "^3.0.0", + "mime-types": "^2.0.8", + "p-limit": "^3.0.1", + "retry-request": "^7.0.0", + "teeny-request": "^9.0.0", + "uuid": "^8.0.0" }, - "peerDependencies": { - "@firebase/app": "0.x" + "engines": { + "node": ">=14" } }, - "node_modules/@firebase/storage-compat": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.4.tgz", - "integrity": "sha512-Y0m5e2gS/wB9Ioth2X/Sgz76vcxvqgQrCmfa9qwhss/N31kxY2Gks6Frv0nrE18AjVfcSmcfDitqUwxcMOTRSg==", - "dependencies": { - "@firebase/component": "0.6.5", - "@firebase/storage": "0.12.1", - "@firebase/storage-types": "0.8.0", - "@firebase/util": "1.9.4", - "tslib": "^2.1.0" + "node_modules/@google-cloud/storage/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "optional": true, + "bin": { + "mime": "cli.js" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/storage-types": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.0.tgz", - "integrity": "sha512-isRHcGrTs9kITJC0AVehHfpraWFui39MPaU7Eo8QfWlqW7YPymBmRgjDrlOgFdURh6Cdeg07zmkLP5tzTKRSpg==", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" + "engines": { + "node": ">=10.0.0" } }, - "node_modules/@firebase/util": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.4.tgz", - "integrity": "sha512-WLonYmS1FGHT97TsUmRN3qnTh5TeeoJp1Gg5fithzuAgdZOUtsYECfy7/noQ3llaguios8r5BuXSEiK82+UrxQ==", - "dependencies": { - "tslib": "^2.1.0" + "node_modules/@google-cloud/storage/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/@firebase/webchannel-wrapper": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.10.5.tgz", - "integrity": "sha512-eSkJsnhBWv5kCTSU1tSUVl9mpFu+5NXXunZc83le8GMjMlsWwQArSc7cJJ4yl+aDFY0NGLi0AjZWMn1axOrkRg==" - }, "node_modules/@grpc/grpc-js": { "version": "1.9.14", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.14.tgz", @@ -2313,6 +2082,7 @@ "version": "0.7.10", "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz", "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==", + "optional": true, "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", @@ -3030,27 +2800,32 @@ "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==" + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "optional": true }, "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==" + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "optional": true }, "node_modules/@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "optional": true }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "optional": true }, "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==", + "optional": true, "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -3059,27 +2834,32 @@ "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==" + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "optional": true }, "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==" + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "optional": true }, "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==" + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "optional": true }, "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==" + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "optional": true }, "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==" + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "optional": true }, "node_modules/@sinclair/typebox": { "version": "0.27.8", @@ -3110,6 +2890,15 @@ "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "optional": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -3179,17 +2968,21 @@ "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, "dependencies": { "@types/connect": "*", "@types/node": "*" } }, + "node_modules/@types/caseless": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", + "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", + "optional": true + }, "node_modules/@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -3211,7 +3004,6 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -3223,7 +3015,6 @@ "version": "4.17.43", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz", "integrity": "sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==", - "dev": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -3243,8 +3034,7 @@ "node_modules/@types/http-errors": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", @@ -3280,11 +3070,24 @@ "pretty-format": "^29.0.0" } }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz", + "integrity": "sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", + "optional": true + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" }, "node_modules/@types/node": { "version": "20.11.17", @@ -3297,20 +3100,43 @@ "node_modules/@types/qs": { "version": "6.9.11", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", - "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==", - "dev": true + "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==" }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" + }, + "node_modules/@types/request": { + "version": "2.48.12", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz", + "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==", + "optional": true, + "dependencies": { + "@types/caseless": "*", + "@types/node": "*", + "@types/tough-cookie": "*", + "form-data": "^2.5.0" + } + }, + "node_modules/@types/request/node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "optional": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -3320,7 +3146,6 @@ "version": "1.15.5", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", - "dev": true, "dependencies": { "@types/http-errors": "*", "@types/mime": "*", @@ -3333,6 +3158,12 @@ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "optional": true + }, "node_modules/@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -3354,6 +3185,18 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "optional": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -3387,6 +3230,18 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "optional": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -3406,6 +3261,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "devOptional": true, "engines": { "node": ">=8" } @@ -3455,6 +3311,24 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "optional": true, + "dependencies": { + "retry": "0.13.1" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3692,6 +3566,26 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true + }, "node_modules/base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", @@ -3700,6 +3594,15 @@ "node": "^4.5.0 || >= 5.9" } }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "optional": true, + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -3808,6 +3711,11 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -3950,6 +3858,7 @@ "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==", + "devOptional": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -4001,6 +3910,18 @@ "node": ">= 0.8" } }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "optional": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -4299,6 +4220,26 @@ "url": "https://dotenvx.com" } }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "optional": true, + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -4325,7 +4266,8 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "devOptional": true }, "node_modules/encodeurl": { "version": "1.0.2", @@ -4335,6 +4277,15 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/engine.io": { "version": "6.5.4", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", @@ -4384,6 +4335,12 @@ "node": ">= 0.6" } }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", + "optional": true + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -4416,6 +4373,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "devOptional": true, "engines": { "node": ">=6" } @@ -4464,6 +4422,15 @@ "node": ">= 0.6" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "optional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -4566,12 +4533,46 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "optional": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "optional": true + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "node_modules/fast-xml-parser": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.4.tgz", + "integrity": "sha512-utnwm92SyozgA3hhH2I8qldf2lBqm6qHOICawRNRFu1qMe3+oqr+GcXjGqTmXTMGE5T4eC03kr/rlh5C1IRdZA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "optional": true, + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/faye-websocket": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", @@ -4647,37 +4648,70 @@ "node": ">=8" } }, - "node_modules/firebase": { - "version": "10.8.0", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.8.0.tgz", - "integrity": "sha512-UJpC24vw8JFuHEOQyArBGKTUd7+kohLISCzHyn0M/prP0KOTx2io1eyLliEid330QqnWI7FOlPxoU97qecCSfQ==", + "node_modules/firebase-admin": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-12.0.0.tgz", + "integrity": "sha512-wBrrSSsKV++/+O8E7O/C7/wL0nbG/x4Xv4yatz/+sohaZ+LsnWtYUcrd3gZutO86hLpDex7xgyrkKbgulmtVyQ==", "dependencies": { - "@firebase/analytics": "0.10.1", - "@firebase/analytics-compat": "0.2.7", - "@firebase/app": "0.9.27", - "@firebase/app-check": "0.8.2", - "@firebase/app-check-compat": "0.3.9", - "@firebase/app-compat": "0.2.27", - "@firebase/app-types": "0.9.0", - "@firebase/auth": "1.6.0", - "@firebase/auth-compat": "0.5.2", - "@firebase/database": "1.0.3", - "@firebase/database-compat": "1.0.3", - "@firebase/firestore": "4.4.2", - "@firebase/firestore-compat": "0.3.25", - "@firebase/functions": "0.11.1", - "@firebase/functions-compat": "0.3.7", - "@firebase/installations": "0.6.5", - "@firebase/installations-compat": "0.2.5", - "@firebase/messaging": "0.12.6", - "@firebase/messaging-compat": "0.2.6", - "@firebase/performance": "0.6.5", - "@firebase/performance-compat": "0.2.5", - "@firebase/remote-config": "0.4.5", - "@firebase/remote-config-compat": "0.2.5", - "@firebase/storage": "0.12.1", - "@firebase/storage-compat": "0.3.4", - "@firebase/util": "1.9.4" + "@fastify/busboy": "^1.2.1", + "@firebase/database-compat": "^1.0.2", + "@firebase/database-types": "^1.0.0", + "@types/node": "^20.10.3", + "jsonwebtoken": "^9.0.0", + "jwks-rsa": "^3.0.1", + "node-forge": "^1.3.1", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "@google-cloud/firestore": "^7.1.0", + "@google-cloud/storage": "^7.7.0" + } + }, + "node_modules/firebase-admin/node_modules/@fastify/busboy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.2.1.tgz", + "integrity": "sha512-7PQA7EH43S0CxcOa9OeAnaeA0oQ+e/DHNPZwSQM9CQHW76jle5+OvLdibRp/Aafs9KXbLhxyjOTkRjWUbQEd3Q==", + "dependencies": { + "text-decoding": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/firebase-admin": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-12.0.0.tgz", + "integrity": "sha512-wBrrSSsKV++/+O8E7O/C7/wL0nbG/x4Xv4yatz/+sohaZ+LsnWtYUcrd3gZutO86hLpDex7xgyrkKbgulmtVyQ==", + "dependencies": { + "@fastify/busboy": "^1.2.1", + "@firebase/database-compat": "^1.0.2", + "@firebase/database-types": "^1.0.0", + "@types/node": "^20.10.3", + "jsonwebtoken": "^9.0.0", + "jwks-rsa": "^3.0.1", + "node-forge": "^1.3.1", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "@google-cloud/firestore": "^7.1.0", + "@google-cloud/storage": "^7.7.0" + } + }, + "node_modules/firebase-admin/node_modules/@fastify/busboy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.2.1.tgz", + "integrity": "sha512-7PQA7EH43S0CxcOa9OeAnaeA0oQ+e/DHNPZwSQM9CQHW76jle5+OvLdibRp/Aafs9KXbLhxyjOTkRjWUbQEd3Q==", + "dependencies": { + "text-decoding": "^1.0.0" + }, + "engines": { + "node": ">=14" } }, "node_modules/follow-redirects": { @@ -4756,6 +4790,40 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "optional": true + }, + "node_modules/gaxios": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.2.0.tgz", + "integrity": "sha512-H6+bHeoEAU5D6XNc6mPKeN5dLZqEDs9Gpk6I+SZBEzK5So58JVrHPmevNi35fRl1J9Y5TaeLW0kYx3pCJ1U2mQ==", + "optional": true, + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/gcp-metadata": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", + "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", + "optional": true, + "dependencies": { + "gaxios": "^6.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -4774,6 +4842,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "devOptional": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -4837,25 +4906,173 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/google-auth-library": { + "version": "9.6.3", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.6.3.tgz", + "integrity": "sha512-4CacM29MLC2eT9Cey5GDVK4Q8t+MMp8+OEdOaqD9MG6b0dOyLORaaeJMPQ7EESVgm/+z5EKYyFLxgzBJlJgyHQ==", + "optional": true, + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/google-auth-library/node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "optional": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/google-auth-library/node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "optional": true, + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/google-gax": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.3.1.tgz", + "integrity": "sha512-qpSfslpwqToIgQ+Tf3MjWIDjYK4UFIZ0uz6nLtttlW9N1NQA4PhGf9tlGo6KDYJ4rgL2w4CjXVd0z5yeNpN/Iw==", + "optional": true, + "dependencies": { + "@grpc/grpc-js": "~1.10.0", + "@grpc/proto-loader": "^0.7.0", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "google-auth-library": "^9.3.0", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^2.0.0", + "protobufjs": "7.2.6", + "retry-request": "^7.0.0", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/google-gax/node_modules/@grpc/grpc-js": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.1.tgz", + "integrity": "sha512-55ONqFytZExfOIjF1RjXPcVmT/jJqFzbbDqxK9jmRV4nxiYWtL9hENSW1Jfx0SdZfrvoqd44YJ/GJTqfRrawSQ==", + "optional": true, + "dependencies": { + "@grpc/proto-loader": "^0.7.8", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/google-auth-library": { + "version": "9.6.3", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.6.3.tgz", + "integrity": "sha512-4CacM29MLC2eT9Cey5GDVK4Q8t+MMp8+OEdOaqD9MG6b0dOyLORaaeJMPQ7EESVgm/+z5EKYyFLxgzBJlJgyHQ==", + "optional": true, + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/google-auth-library/node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "optional": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/google-auth-library/node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "optional": true, "dependencies": { - "is-glob": "^4.0.1" + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/google-gax": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.3.1.tgz", + "integrity": "sha512-qpSfslpwqToIgQ+Tf3MjWIDjYK4UFIZ0uz6nLtttlW9N1NQA4PhGf9tlGo6KDYJ4rgL2w4CjXVd0z5yeNpN/Iw==", + "optional": true, + "dependencies": { + "@grpc/grpc-js": "~1.10.0", + "@grpc/proto-loader": "^0.7.0", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "google-auth-library": "^9.3.0", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^2.0.0", + "protobufjs": "7.2.6", + "retry-request": "^7.0.0", + "uuid": "^9.0.1" }, "engines": { - "node": ">= 6" + "node": ">=14" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, + "node_modules/google-gax/node_modules/@grpc/grpc-js": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.1.tgz", + "integrity": "sha512-55ONqFytZExfOIjF1RjXPcVmT/jJqFzbbDqxK9jmRV4nxiYWtL9hENSW1Jfx0SdZfrvoqd44YJ/GJTqfRrawSQ==", + "optional": true, + "dependencies": { + "@grpc/proto-loader": "^0.7.8", + "@types/node": ">=12.12.47" + }, "engines": { - "node": ">=4" + "node": "^8.13.0 || >=10.10.0" } }, "node_modules/gopd": { @@ -4875,6 +5092,40 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, + "node_modules/gtoken": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", + "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", + "optional": true, + "dependencies": { + "gaxios": "^6.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/gtoken/node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "optional": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/gtoken/node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "optional": true, + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -4954,6 +5205,45 @@ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "optional": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "optional": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -4974,11 +5264,6 @@ "node": ">=0.10.0" } }, - "node_modules/idb": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", - "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" - }, "node_modules/ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", @@ -5079,6 +5364,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "devOptional": true, "engines": { "node": ">=8" } @@ -5117,7 +5403,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8" }, @@ -6828,6 +7114,14 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jose": { + "version": "4.15.4", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz", + "integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6859,6 +7153,15 @@ "node": ">=4" } }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "optional": true, + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -6877,6 +7180,92 @@ "node": ">=6" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsonwebtoken/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwks-rsa": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.1.0.tgz", + "integrity": "sha512-v7nqlfezb9YfHHzYII3ef2a2j1XnGeSE/bK3WfumaYCqONAIstJbrEGapz4kadScZzEt7zYCN7bucj8C0Mv/Rg==", + "dependencies": { + "@types/express": "^4.17.17", + "@types/jsonwebtoken": "^9.0.2", + "debug": "^4.3.4", + "jose": "^4.14.6", + "limiter": "^1.1.5", + "lru-memoizer": "^2.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -6895,6 +7284,11 @@ "node": ">=6" } }, + "node_modules/limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -6916,7 +7310,18 @@ "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==" + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "optional": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, "node_modules/lodash.debounce": { "version": "4.0.8", @@ -6924,10 +7329,46 @@ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "optional": true }, "node_modules/lru-cache": { "version": "5.1.1", @@ -6938,6 +7379,29 @@ "yallist": "^3.0.2" } }, + "node_modules/lru-memoizer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.2.0.tgz", + "integrity": "sha512-QfOZ6jNkxCcM/BkIPnFsqDhtrazLRsghi9mBwFAzol5GCvj4EkFT899Za3+QwikCg5sRX8JstioBDwOxEyzaNw==", + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "lru-cache": "~4.0.0" + } + }, + "node_modules/lru-memoizer/node_modules/lru-cache": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", + "integrity": "sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw==", + "dependencies": { + "pseudomap": "^1.0.1", + "yallist": "^2.0.0" + } + }, + "node_modules/lru-memoizer/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -7111,6 +7575,34 @@ "node": ">= 0.6" } }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "optional": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -7228,6 +7720,15 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "optional": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -7251,7 +7752,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, + "devOptional": true, "dependencies": { "wrappy": "1" } @@ -7275,7 +7776,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, + "devOptional": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -7464,11 +7965,24 @@ "node": ">= 6" } }, + "node_modules/proto3-json-serializer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.1.tgz", + "integrity": "sha512-8awBvjO+FwkMd6gNoGFZyqkHZXCFd54CIYTb6De7dPaufGJ2XNW+QUNqbMr8MaAocMdb+KpsD4rxEOaTBDCffA==", + "optional": true, + "dependencies": { + "protobufjs": "^7.2.5" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/protobufjs": { "version": "7.2.6", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", "hasInstallScript": true, + "optional": true, "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -7504,6 +8018,11 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -7568,6 +8087,20 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -7655,6 +8188,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -7706,6 +8240,29 @@ "node": ">=10" } }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/retry-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", + "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", + "optional": true, + "dependencies": { + "@types/request": "^2.48.8", + "extend": "^3.0.2", + "teeny-request": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -8025,6 +8582,30 @@ "node": ">= 0.8" } }, + "node_modules/stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "optional": true, + "dependencies": { + "stubs": "^3.0.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "optional": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -8042,6 +8623,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "devOptional": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -8055,6 +8637,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "devOptional": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -8092,6 +8675,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "optional": true + }, + "node_modules/stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", + "optional": true + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -8116,6 +8711,47 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/teeny-request": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", + "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", + "optional": true, + "dependencies": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.9", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/teeny-request/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/teeny-request/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -8130,6 +8766,11 @@ "node": ">=8" } }, + "node_modules/text-decoding": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz", + "integrity": "sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==" + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -8177,6 +8818,12 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "optional": true + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -8277,17 +8924,6 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, - "node_modules/undici": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.26.5.tgz", - "integrity": "sha512-cSb4bPFd5qgR7qr2jYAi0hlX9n5YKK2ONKkLFkxl+v/9BvC0sOpZjBHDBSXc5lWAf5ty9oZdRXytBIHzgUcerw==", - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, - "engines": { - "node": ">=14.0" - } - }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -8371,6 +9007,12 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "optional": true + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -8428,6 +9070,12 @@ "makeerror": "1.0.12" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "optional": true + }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -8449,6 +9097,16 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "optional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -8468,6 +9126,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "devOptional": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -8484,6 +9143,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "devOptional": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -8498,6 +9158,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "devOptional": true, "dependencies": { "color-name": "~1.1.4" }, @@ -8508,13 +9169,14 @@ "node_modules/wrap-ansi/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "devOptional": true }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "devOptional": true }, "node_modules/write-file-atomic": { "version": "4.0.2", @@ -8562,6 +9224,7 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "devOptional": true, "engines": { "node": ">=10" } @@ -8576,6 +9239,7 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "devOptional": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -8593,6 +9257,7 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "devOptional": true, "engines": { "node": ">=12" } @@ -8610,7 +9275,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, + "devOptional": true, "engines": { "node": ">=10" }, diff --git a/server/package.json b/server/package.json index c4dfdf3d6..9af60ca12 100644 --- a/server/package.json +++ b/server/package.json @@ -28,7 +28,7 @@ "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", - "firebase": "^10.5.0", + "firebase-admin": "^12.0.0", "geofire-common": "^6.0.0", "socket.io": "^4.7.4", "uuid": "^9.0.1" diff --git a/server/src/actions/createConnectedUser.ts b/server/src/actions/createConnectedUser.ts index 218606f46..10fd9febd 100644 --- a/server/src/actions/createConnectedUser.ts +++ b/server/src/actions/createConnectedUser.ts @@ -1,14 +1,11 @@ // Uploads a new document in the ConnectedUsers collection. -import { doc, setDoc } from '@firebase/firestore' -import { connectedUsers } from '../utilities/firebaseInit' import { ConnectedUser } from '../types/User' +import { connectedUsersCollection } from '../utilities/firebaseInit'; export const createUser = async (connectedUser: ConnectedUser) => { try { - const ref = doc(connectedUsers, connectedUser.socketId) // Use the socketid as the index - await setDoc(ref, connectedUser) - return true - + await connectedUsersCollection.doc(connectedUser.socketId).set(connectedUser) + console.log('User added to the database') } catch (error) { console.error(error.message) return false diff --git a/server/src/actions/createMessage.ts b/server/src/actions/createMessage.ts index 944e6c1e9..140627c45 100644 --- a/server/src/actions/createMessage.ts +++ b/server/src/actions/createMessage.ts @@ -1,12 +1,10 @@ // Uploads a new document in the Messages collection. -import { doc, setDoc } from '@firebase/firestore' -import { messages } from '../utilities/firebaseInit' import { Message } from '../types/Message' +import { messagesCollection } from '../utilities/firebaseInit' export const createMessage = async (msg : Message) => { try { - const ref = doc(messages, msg.msgId) - const status = await setDoc(ref, msg) + await messagesCollection.doc(msg.msgId).set(msg) return true } catch (error) { diff --git a/server/src/actions/deleteConnectedUser.ts b/server/src/actions/deleteConnectedUser.ts index 6cf469360..bb8d64888 100644 --- a/server/src/actions/deleteConnectedUser.ts +++ b/server/src/actions/deleteConnectedUser.ts @@ -1,20 +1,9 @@ // Delete a ConnectedUser document given a document's index. This should typically be a socketId, but it can also be something else. -import { doc, getDoc, deleteDoc } from '@firebase/firestore' -import { connectedUsers } from '../utilities/firebaseInit' +import { connectedUsersCollection } from '../utilities/firebaseInit' -export const deleteConnectedUserByIndex = async (index: string) => { +export const deleteConnectedUserByUID = async (socketID: string) => { try { - const userRef = doc(connectedUsers, index) - - // The promise returned by deleteDoc will be fulfilled (aka return 'true') both if the document requested for deletion exists or doesn't exist. It is rejected if the program is unable to send this request to Firestore. - // Therefore, we need to check to see if the document exists first, to most accurately know if it will be deleted. - // However, technically, there could be some kind of failure by deleteDoc after this check is performed, where the status of the deletion would then be inaccurately returned. - // TODO: find a way to assuredly know if a document is deleted after deleteDoc is called. - - const userDoc = await getDoc(userRef) - if (!userDoc.exists()) throw Error("[FIREBASE] User does not exist.") - - await deleteDoc(userRef) + await connectedUsersCollection.doc(socketID).delete() return true } catch (error) { diff --git a/server/src/actions/getConnectedUsers.ts b/server/src/actions/getConnectedUsers.ts index a3258abe6..c61657006 100644 --- a/server/src/actions/getConnectedUsers.ts +++ b/server/src/actions/getConnectedUsers.ts @@ -1,6 +1,5 @@ -import { doc, endAt, getDocs, orderBy, query, startAt } from 'firebase/firestore' -import { connectedUsers } from '../utilities/firebaseInit' import { distanceBetween, geohashForLocation, geohashQueryBounds } from 'geofire-common' +import { connectedUsersCollection } from '../utilities/firebaseInit' export const findNearbyUsers = async (centerLat: number, centerLon: number, radius: number) => { // Return an array of nearby userIds (which are also socket ids) given a center latitude and longitude. @@ -18,21 +17,21 @@ export const findNearbyUsers = async (centerLat: number, centerLon: number, radi const promises = [] for (const b of bounds) { - const q = query( - connectedUsers, - orderBy('location.geohash'), - startAt(b[0]), - endAt(b[1]) - ) - - promises.push(getDocs(q)) + const q = connectedUsersCollection + .orderBy('location.geohash') + .startAt(b[0]) + .endAt(b[1]) + + promises.push(q.get()) } // Collect query results and append into a single array const snapshots = await Promise.all(promises) const matchingDocs = [] + for (const snap of snapshots) { + for (const doc of snap.docs) { const lat = doc.get('location.lat') const lon = doc.get('location.lon') @@ -42,18 +41,14 @@ export const findNearbyUsers = async (centerLat: number, centerLon: number, radi const distanceInKm = distanceBetween([lat, lon], [centerLat, centerLon]) const distanceInM = distanceInKm * 1000 if (distanceInM <= radius) { - matchingDocs.push(doc) + matchingDocs.push(doc.get('socketId')) } } } - // Extract userIds from matched documents - const userSocketIds = [] - for (const doc of matchingDocs) { - userSocketIds.push(doc.data()['socketId']) - } - console.log(`getNearbyUsers(): ${userSocketIds.length} users found within ${radius} meters of ${centerLat}, ${centerLon}`) - return userSocketIds + console.log(`getNearbyUsers(): ${matchingDocs.length} users found within ${radius} meters of ${centerLat}, ${centerLon}`) + console.log(matchingDocs) + return matchingDocs } catch (error) { console.error("getNearbyUsers() failed.", error.message) } diff --git a/server/src/actions/updateConnectedUser.ts b/server/src/actions/updateConnectedUser.ts index c151a4d47..59bfe7c54 100644 --- a/server/src/actions/updateConnectedUser.ts +++ b/server/src/actions/updateConnectedUser.ts @@ -1,38 +1,25 @@ -import { doc, getDoc, updateDoc } from '@firebase/firestore' -import { connectedUsers } from '../utilities/firebaseInit' import { geohashForLocation} from 'geofire-common' +import { connectedUsersCollection } from '../utilities/firebaseInit' -export const toggleUserConnectionStatus = async (index: string) => { +export const toggleUserConnectionStatus = async (socketID: string) => { try { - const userRef = doc(connectedUsers, index) - const userDoc = await getDoc(userRef) - - if (!userDoc.exists()) throw Error("[FIREBASE] User does not exist.") - - let status = userDoc.data()['isConnected'] - + let status = connectedUsersCollection.doc(socketID).isConnected // Flip the connection status status = !status - updateDoc(userRef, { isConnected: status }) + await connectedUsersCollection.doc(socketID).update({ isConnected: status }) return true - } catch (error) { console.error(error.message) return false } } -export const updateUserLocation = async (userIndex: string, lat: number, lon: number) => { +export const updateUserLocation = async (socketID: string, lat: number, lon: number) => { try { - const ref = doc(connectedUsers, userIndex) - const userDoc = await getDoc(ref) - - if (!userDoc.exists()) throw Error("[FIREBASE] User does not exist.") - const newHash = geohashForLocation([lat, lon]) - updateDoc(ref, { "location.lat": lat, "location.lon": lon, "location.geohash": newHash }) + await connectedUsersCollection.doc(socketID).update({ "location.lat": lat, "location.lon": lon, "location.geohash": newHash }) return true } catch (error) { console.error(error.message) diff --git a/server/src/index.ts b/server/src/index.ts index 69e9b98f6..c2e4932b2 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -1,30 +1,29 @@ import express from 'express' import 'dotenv/config' import 'geofire-common' - import { Message } from './types/Message'; - import { createMessage } from './actions/createMessage' -// import { deleteMessageById } from './actions/deleteMessage' -// import { getUserById } from './actions/getUsers' import { createUser } from './actions/createConnectedUser' import { toggleUserConnectionStatus, updateUserLocation } from './actions/updateConnectedUser' -import { deleteConnectedUserByIndex } from './actions/deleteConnectedUser' +import { deleteConnectedUserByUID } from './actions/deleteConnectedUser' import {geohashForLocation} from 'geofire-common'; import { findNearbyUsers } from './actions/getConnectedUsers' import { ConnectedUser } from './types/User'; +import { getAuth } from 'firebase-admin/auth'; + const { createServer } = require('http') const { Server } = require('socket.io') - const socket_port = process.env.socket_port const express_port = process.env.express_port const app = express() +// Middleware app.use(express.json()) app.use(express.urlencoded({ extended: true })) + // === SOCKET API === const socketServer = createServer() const io = new Server(socketServer, { @@ -34,7 +33,26 @@ const io = new Server(socketServer, { }, }); -io.on('connection', (socket: any) => { +// Firebase JWT Authorization Custom Middleware +io.use(async (socket, next) => { + const token = socket.handshake.auth.token; + console.log(`[WS] Recieved token: ${token}`) + + if (token) { + const decodedToken = await getAuth().verifyIdToken(token); + const userId = decodedToken.uid; + console.log(`[WS] User <${userId}> authenticated.`); + console.log(decodedToken) + + next(); + } else { + console.error("[WS] User not authenticated.") + next(new Error('User not authenticated.')); + } +}) + + +io.on('connection', async (socket: any) => { console.log(`[WS] User <${socket.id}> connected.`); const defaultConnectedUser: ConnectedUser = { uid: "UID", @@ -50,12 +68,12 @@ io.on('connection', (socket: any) => { geohash: "F" } } // TODO: Send this info from client on connection - createUser(defaultConnectedUser) - toggleUserConnectionStatus(socket.id) + await createUser(defaultConnectedUser) + await toggleUserConnectionStatus(socket.id) socket.on('disconnect', () => { console.log(`[WS] User <${socket.id}> exited.`); - deleteConnectedUserByIndex(socket.id) + deleteConnectedUserByUID(socket.id) }) socket.on('ping', (ack) => { // The (ack) parameter stands for "acknowledgement." This function sends a message back to the originating socket. @@ -98,11 +116,11 @@ io.on('connection', (socket: any) => { console.error("[WS] Error sending message:", error.message) } }) - socket.on('updateLocation', async (message, ack) => { + socket.on('updateLocation', async (location, ack) => { console.log(`[WS] Recieved new location from user <${socket.id}>.`) try { - const lat = Number(message.lat) - const lon = Number(message.lon) + const lat = Number(location.lat) + const lon = Number(location.lon) const success = await updateUserLocation(socket.id, lat, lon) if (success) { console.log("[WS] Location updated in database successfully.") @@ -212,7 +230,7 @@ app.delete('/users', async (req, res) => { const userId = req.query.userId if (typeof userId != "string") throw Error(" [userId] is not a string.") - const success = await deleteConnectedUserByIndex(userId) + const success = await deleteConnectedUserByUID(userId) if (!success) throw Error(" deleteUserById() failed.") console.log(`[EXP] Request returned successfully.`) diff --git a/server/src/tests/socketio.test.ts b/server/src/tests/socketio.test.ts index 51dc456f7..3a882e058 100644 --- a/server/src/tests/socketio.test.ts +++ b/server/src/tests/socketio.test.ts @@ -13,7 +13,7 @@ describe("socket-load-tests", () => { let httpServer; let httpServerAddr; let ioServer; - const numClients = 100; // Adjust the number of clients as needed. Do not go over 300 to prevent being blocked by Firebase. + const numClients = 20; // Adjust the number of clients as needed. Do not go over 300 to prevent being blocked by Firebase. beforeAll((done) => { httpServer = createServer().listen(); diff --git a/server/src/utilities/firebaseInit.ts b/server/src/utilities/firebaseInit.ts index bc5a2b351..beeb3f717 100644 --- a/server/src/utilities/firebaseInit.ts +++ b/server/src/utilities/firebaseInit.ts @@ -1,28 +1,15 @@ -import { initializeApp } from 'firebase/app' -import { getFirestore, CollectionReference, collection, DocumentData } from 'firebase/firestore' -import 'dotenv/config'; +const admin = require('firebase-admin'); +const serviceAccount = require("../../.firebase-secrets.json"); -export const firebaseApp = initializeApp({ - apiKey: process.env.API_KEY, - authDomain: process.env.AUTH_DOMAIN, - projectId: process.env.PROJECT_ID, - storageBucket: process.env.STORAGE_BUCKET, - messagingSenderId: process.env.MESSAGING_SENDER_ID, - appId: process.env.APP_ID -}) +export const adminApp = admin.initializeApp({ + credential: admin.credential.cert(serviceAccount), +}); -export const firestore = getFirestore() +export const db = admin.firestore(); +export const connectedUsersCollection = db.collection('ConnectedUsers'); +export const messagesCollection = db.collection('Messages'); -const createCollection = (collectionName: string) => { - return collection(firestore, collectionName) as CollectionReference; -} - -import { Message } from '../types/Message' -import { ConnectedUser, UserConfig } from '../types/User' - -export const messages = createCollection('Messages') -export const connectedUsers = createCollection('ConnectedUsers') -export const userConfigs = createCollection('UserConfigs') - -console.log("[FIRESTORE] Database synced.") +console.log("[FIREBASE] Firestore synced.") +// TODO: refactor file name to 'firebase' for accuracy. +// TODO: move key info to .env From c747b8b7f63a4395256b0bd963e44a71361eb2f8 Mon Sep 17 00:00:00 2001 From: Dylan Coben <59846502+dyland88@users.noreply.github.com> Date: Thu, 29 Feb 2024 17:29:56 -0500 Subject: [PATCH 3/4] Redesigned chat input (#153) * Created text container with send button inside * More small tweaks to the layout * Moved chat sending area to its own file * Added icons for image and smiley face * Made chatbox icons allign to the bottom. * Added click opacity for icons * Redefined dimensions in terms of width * Streamlined View hierarchy, still need to set margins properly * Resized Chatbox and fixed margins * Changed margins for android devices and centered text input * Renamed component and filename to ChatScreenFooter --- client/assets/transparentSend.png | Bin 0 -> 15493 bytes client/package.json | 4 +- client/src/components/Chat/ChatScreen.tsx | 16 ++-- .../components/Common/ChatScreenFooter.tsx | 88 ++++++++++++++++++ .../src/components/Common/CustomButtons.tsx | 17 ++-- client/src/components/Common/CustomInputs.tsx | 41 ++++++-- 6 files changed, 142 insertions(+), 24 deletions(-) create mode 100644 client/assets/transparentSend.png create mode 100644 client/src/components/Common/ChatScreenFooter.tsx diff --git a/client/assets/transparentSend.png b/client/assets/transparentSend.png new file mode 100644 index 0000000000000000000000000000000000000000..e3a3380cc039c0e76726cefef79aea438342a751 GIT binary patch literal 15493 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 He(8SzIb%0> literal 0 HcmV?d00001 diff --git a/client/package.json b/client/package.json index 46a975ac9..995d4e31d 100644 --- a/client/package.json +++ b/client/package.json @@ -22,6 +22,7 @@ "expo-linear-gradient": "~12.3.0", "expo-linking": "~5.0.2", "expo-location": "~16.1.0", + "expo-network": "~5.4.0", "expo-router": "^2.0.0", "expo-secure-store": "~12.3.1", "expo-status-bar": "~1.6.0", @@ -30,13 +31,14 @@ "react": "18.2.0", "react-native": "0.72.6", "react-native-dotenv": "^3.4.9", + "react-native-feather": "^1.1.2", "react-native-fs": "^2.20.0", "react-native-safe-area-context": "4.6.3", "react-native-screens": "~3.22.0", "react-native-uuid": "^2.0.1", "react-native-web": "~0.19.6", "socket.io-client": "^4.7.4", - "expo-network": "~5.4.0" + "react-native-svg": "13.9.0" }, "devDependencies": { "@babel/core": "^7.20.0", diff --git a/client/src/components/Chat/ChatScreen.tsx b/client/src/components/Chat/ChatScreen.tsx index 2939a47cb..12c9548e2 100644 --- a/client/src/components/Chat/ChatScreen.tsx +++ b/client/src/components/Chat/ChatScreen.tsx @@ -24,6 +24,7 @@ import { useSettings } from "../../contexts/SettingsContext"; import { useLocation } from "../../contexts/LocationContext"; import { useUser } from "../../contexts/UserContext"; // imported for when it needs to be used import { AuthStore } from "../../services/store"; +import { ChatScreenFooter } from "../Common/ChatScreenFooter" const ChatScreen = () => { const settings = useSettings(); @@ -108,13 +109,13 @@ const ChatScreen = () => { - { setMessageContent(text); }} + onSend={onHandleSubmit} /> - @@ -147,16 +148,17 @@ const styles = StyleSheet.create({ footerContainer: { width: "95%", - minHeight: Dimensions.get("window").height * 0.1, + maxHeight: Dimensions.get("window").height * 0.15, display: "flex", flexDirection: "row", alignItems: "flex-end", justifyContent: "space-evenly", - paddingBottom: Dimensions.get("window").height * 0.02, - paddingTop: Dimensions.get("window").height * 0.02, - marginTop: 10, - borderTopWidth: 1, + paddingBottom: Dimensions.get("window").height * 0.003, + paddingTop: Dimensions.get("window").height * 0.004, + marginTop: 0, + borderTopWidth: 0, + borderColor: "#8E8E8E", }, }); diff --git a/client/src/components/Common/ChatScreenFooter.tsx b/client/src/components/Common/ChatScreenFooter.tsx new file mode 100644 index 000000000..af9998ed5 --- /dev/null +++ b/client/src/components/Common/ChatScreenFooter.tsx @@ -0,0 +1,88 @@ +import React from 'react' +import { TextInput, View, StyleSheet, Dimensions, Platform, TouchableOpacity } from 'react-native' +import { ChatSendButton } from './CustomButtons' +import { Smile, Image } from "react-native-feather"; + +interface ChatInputProps { + value?: string, + onChangeText?: (text: string) => void + invalid?: boolean, + onSend?: () => void, +} + +export const ChatScreenFooter: React.FC = ({ value, onChangeText, onSend }) => { + + + + return ( + + + + + + + + + + + + + + + ) +}; + +const styles = StyleSheet.create({ + + container: { + flexDirection: 'row', + flex: 1, + alignItems: 'center', + borderColor: "#8E8E8E", + borderWidth: 1, + borderRadius: Dimensions.get('window').width * 0.058, + marginHorizontal: Dimensions.get('window').width * 0.005, + marginBottom: Platform.OS === 'ios' ? 0 : 5, + minHeight: Dimensions.get('window').width * 0.113, + maxHeight: Dimensions.get('window').width * 0.3, + }, + messageInput: { + fontSize: 16, + flex: 1, + marginBottom: Platform.OS === 'ios' ? 5 : 4, + marginTop: Platform.OS === 'ios' ? 2 : 4, + marginHorizontal: Dimensions.get('window').width * 0.018, + + + }, + icons: { + marginHorizontal: Dimensions.get('window').width * 0.008, + }, + iconContainer: { + marginLeft: Dimensions.get('window').width * 0.02, + marginBottom: Dimensions.get('window').width * 0.025, + marginTop: Dimensions.get('window').width * 0.025, + flexDirection: 'row', + alignItems: "flex-end", + justifyContent: "flex-end", + alignSelf: "stretch", + + + }, + sendButtonContainer: { + alignItems: "flex-end", + justifyContent: "flex-end", + flexDirection: "row", + alignSelf: "stretch", + marginRight: Dimensions.get('window').width * 0.01, + marginBottom: Dimensions.get('window').width * 0.01, + marginTop: Dimensions.get('window').width * 0.01, + } + +}); \ No newline at end of file diff --git a/client/src/components/Common/CustomButtons.tsx b/client/src/components/Common/CustomButtons.tsx index 6474e4c56..1b9cd5cb7 100644 --- a/client/src/components/Common/CustomButtons.tsx +++ b/client/src/components/Common/CustomButtons.tsx @@ -8,25 +8,26 @@ interface ChatSendButtonProps { export const ChatSendButton: React.FC = ({ onPress }) => { return ( - + ) } const styles = StyleSheet.create({ sendButton: { - height: Dimensions.get('window').height * 0.055, - width: Dimensions.get('window').height * 0.055, - borderRadius: 30, - backgroundColor: 'blue', + height: Dimensions.get('window').width * 0.09, + width: Dimensions.get('window').width * 0.09, + borderRadius: 100, + backgroundColor: '#34D1BF', justifyContent: 'center', alignItems: 'center', }, sendButtonImage:{ - height: Dimensions.get('window').height * 0.033, - width: Dimensions.get('window').height * 0.033, - marginLeft: Dimensions.get('window').width * 0.01, + height: "64%", + width: "64%", + marginLeft: "13%", + tintColor: 'white', }, }) diff --git a/client/src/components/Common/CustomInputs.tsx b/client/src/components/Common/CustomInputs.tsx index 525258263..71871be41 100644 --- a/client/src/components/Common/CustomInputs.tsx +++ b/client/src/components/Common/CustomInputs.tsx @@ -1,10 +1,12 @@ import React from 'react' import { TextInput, View, StyleSheet, Dimensions, Platform } from 'react-native' +import { ChatSendButton } from './CustomButtons' interface ChatInputProps { value?: string, onChangeText?: (text: string) => void invalid?: boolean, + onSend?: () => void, } export const WelcomeEmailInput: React.FC = ({ value, onChangeText }) => { @@ -80,17 +82,23 @@ export const SignUpConfirmPasswordInput: React.FC = ({ value, on ) } -export const ChatInput: React.FC = ({ value, onChangeText }) => { +export const ChatInput: React.FC = ({ value, onChangeText, onSend }) => { return ( - + + + + + + ) }; @@ -115,7 +123,24 @@ const styles = StyleSheet.create({ paddingLeft: 15, paddingRight: 15, }, - + messsageContainer: { + width: Dimensions.get('window').width * 0.75, + borderWidth: 1, + borderRadius: 30, + paddingTop: Dimensions.get('window').height * 0.006, + paddingBottom: Dimensions.get('window').height * 0.006, + paddingLeft: 15, + paddingRight: Dimensions.get('window').height * 0.006, + flexDirection: 'row', + flex: 1, + justifyContent: 'space-between', + alignItems: 'center', + borderColor: "#8E8E8E" + }, + messageInput: { + width: Dimensions.get('window').height * 0.35, + fontSize: 16, + }, invalidLoginInput: { borderColor: 'red', }, From 9a33b94f84b2a8b6802cb59944af54c9d3241fa0 Mon Sep 17 00:00:00 2001 From: Aadit Kamat <30969577+aaditkamat@users.noreply.github.com> Date: Thu, 29 Feb 2024 22:05:40 -0500 Subject: [PATCH 4/4] Update message type to reflect users it is visible to --- server/src/types/Message.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/types/Message.ts b/server/src/types/Message.ts index 64af59b4c..41b6e0966 100644 --- a/server/src/types/Message.ts +++ b/server/src/types/Message.ts @@ -8,4 +8,5 @@ export interface Message { lon: number geohash?: string } + visibleToUids?: Array }