diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3f07002e0c5b..90c56d41b4bb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -891,6 +891,7 @@ jobs: 'create-remix-app-express-legacy', 'create-remix-app-express-vite-dev', 'default-browser', + 'firebase', 'node-express-esm-loader', 'node-express-esm-preload', 'node-express-esm-without-loader', diff --git a/dev-packages/e2e-tests/test-applications/firebase/.gitignore b/dev-packages/e2e-tests/test-applications/firebase/.gitignore new file mode 100644 index 000000000000..48b1bd712db4 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/.gitignore @@ -0,0 +1,58 @@ +# compiled output +/dist +/node_modules +/build + +# Logs +logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# OS +.DS_Store + +# Tests +/coverage +/.nyc_output + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# temp directory +.temp +.tmp + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +test-results diff --git a/dev-packages/e2e-tests/test-applications/firebase/.npmrc b/dev-packages/e2e-tests/test-applications/firebase/.npmrc new file mode 100644 index 000000000000..070f80f05092 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/.npmrc @@ -0,0 +1,2 @@ +@sentry:registry=http://127.0.0.1:4873 +@sentry-internal:registry=http://127.0.0.1:4873 diff --git a/dev-packages/e2e-tests/test-applications/firebase/README.md b/dev-packages/e2e-tests/test-applications/firebase/README.md new file mode 100644 index 000000000000..e44ee12f5268 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/README.md @@ -0,0 +1,64 @@ +## Assuming you already have installed docker desktop or orbstack etc. or any other docker software + +### Enabling / authorising firebase emulator through docker + +1. Run the docker + +```bash +pnpm docker +``` + +2. In new tab, enter the docker container by simply running + +```bash +docker exec -it sentry-firebase bash +``` + +3. Now inside docker container run + +```bash +firebase login +``` + +4. You should now see a long link to authenticate with google account, copy the link and open it using your browser +5. Choose the account you want to authenticate with +6. Once you do this you should be able to see something like "Firebase CLI Login Successful" +7. And inside docker container you should see something like "Success! Logged in as " +8. Now you can exit docker container + +```bash +exit +``` + +9. Switch back to previous tab, stop the docker container (ctrl+c). +10. You should now be able to run the test, as you have correctly authenticated the firebase emulator + +### Preparing data for CLI + +1. Please authorize the docker first - see the previous section +2. Once you do that you can generate .env file locally, to do that just run + +```bash +npm run createEnvFromConfig +``` + +3. It will create a new file called ".env" inside folder "docker" +4. View the file. There will be 2 params CONFIG_FIREBASE_TOOLS and CONFIG_UPDATE_NOTIFIER_FIREBASE_TOOLS. +5. Now inside the CLI create a new variable under the name CONFIG_FIREBASE_TOOLS and + CONFIG_UPDATE_NOTIFIER_FIREBASE_TOOLS - take values from mentioned .env file +6. File .env is ignored to avoid situation when developer after authorizing firebase with private account will + accidently push the tokens to github. +7. But if we want the users to still have some default to be used for authorisation (on their local development) it will + be enough to commit this file, we just have to authorize it with some "special" account. + +**Some explanation towards environment settings, the environment variable defined directly in "environments" takes +precedence over .env file, that means it will be safe to define it in CLI and still keeps the .env file.** + +### Scripts - helpers + +- createEnvFromConfig - it will use the firebase docker authentication and create .env file which will be used then by + docker whenever you run emulator +- createConfigFromEnv - it will use '.env' file in docker folder to create .config for the firebase to be used to + authenticate whenever you run docker, Docker by default loads .env file itself + +Use these scripts when testing and updating the environment settings on CLI diff --git a/dev-packages/e2e-tests/test-applications/firebase/createConfigFromEnv.js b/dev-packages/e2e-tests/test-applications/firebase/createConfigFromEnv.js new file mode 100644 index 000000000000..3345a9d868fb --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/createConfigFromEnv.js @@ -0,0 +1,14 @@ +const path = require('path'); +const dotent = require('dotenv'); +dotent.config({ path: path.resolve(__dirname, './docker/.env') }); + +const createConfigFromEnv = require('./docker/firebase/utils').createConfigFromEnv; + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +(async () => { + try { + await createConfigFromEnv(); + } catch (e) { + console.error(e); + } +})(); diff --git a/dev-packages/e2e-tests/test-applications/firebase/createEnvFromConfig.js b/dev-packages/e2e-tests/test-applications/firebase/createEnvFromConfig.js new file mode 100644 index 000000000000..d19ea4cb1dc9 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/createEnvFromConfig.js @@ -0,0 +1,10 @@ +const createEnvFromConfig = require('./docker/firebase/utils').createEnvFromConfig; + +(async () => { + try { + await createEnvFromConfig(); + } catch (e) { + console.error(e); + } +})(); + diff --git a/dev-packages/e2e-tests/test-applications/firebase/docker/.gitignore b/dev-packages/e2e-tests/test-applications/firebase/docker/.gitignore new file mode 100644 index 000000000000..b8b9f2089493 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/docker/.gitignore @@ -0,0 +1,6 @@ +.config +cache +firebase/data +firebase/firebase-export-* +*-debug.log +.env diff --git a/dev-packages/e2e-tests/test-applications/firebase/docker/Dockerfile b/dev-packages/e2e-tests/test-applications/firebase/docker/Dockerfile new file mode 100644 index 000000000000..ce0fde56dbc7 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/docker/Dockerfile @@ -0,0 +1,15 @@ +FROM node:20-alpine + +ARG FIREBASE_VERSION + +RUN apk --no-cache add openjdk11-jre bash curl openssl gettext nano nginx sudo && \ + npm cache clean --force && \ + npm i -g firebase-tools@$FIREBASE_VERSION + +COPY nginx.conf /etc/nginx/ +COPY serve.sh /usr/bin/ +RUN chmod +x /usr/bin/serve.sh + +WORKDIR /srv/firebase + +ENTRYPOINT ["/usr/bin/serve.sh"] diff --git a/dev-packages/e2e-tests/test-applications/firebase/docker/docker-compose.yml b/dev-packages/e2e-tests/test-applications/firebase/docker/docker-compose.yml new file mode 100644 index 000000000000..3442db42d232 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/docker/docker-compose.yml @@ -0,0 +1,60 @@ +services: + emulator: + container_name: sentry-firebase + build: + context: . + dockerfile: Dockerfile + args: + - FIREBASE_VERSION=13.19.0 + stop_grace_period: 1m + environment: + FIREBASE_AUTH_EMULATOR_HOST: "localhost:5507" + FIRESTORE_EMULATOR_HOST: "localhost:5504" + PUBSUB_EMULATOR_HOST: "localhost:5505" + FUNCTIONS_EMULATOR_HOST: "localhost:5503" + FIREBASE_PROJECT: "sentry-15d85" + GCLOUD_PROJECT: "sentry-15d85" + FORCE_COLOR: "true" + DATA_DIRECTORY: "data" + CHOKIDAR_USEPOLLING: "true" + CONFIG_FIREBASE_TOOLS: ${CONFIG_FIREBASE_TOOLS} + CONFIG_UPDATE_NOTIFIER_FIREBASE_TOOLS: ${CONFIG_UPDATE_NOTIFIER_FIREBASE_TOOLS} + ports: + - "5500:4001" # ui + - "5501:4401" # hub + - "5502:4601" # logging + - "5503:5002" # functions + - "5504:8081" # firestore + - "5505:8086" # pubsub + - "5506:9001" # database + - "5507:9100" # auth + - "5508:9200" # Storage + - "5509:6001" # Hosting + - '5510:9081' # firestore (grpc) + - '5511:9230' # cloud_functions_debug + - '9005:9005' # to be able to authenticate using gmail and docker + volumes: + - type: bind + source: ./firebase + target: /srv/firebase + bind: + create_host_path: true + - type: bind + source: ./cache + target: /root/.cache + bind: + create_host_path: true + - type: bind + source: .config + target: /root/.config + bind: + create_host_path: true + - type: bind + source: ./firebase/data + target: /srv/firebase/data + bind: + create_host_path: true + +networks: + default: + driver: bridge diff --git a/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/.firebaserc b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/.firebaserc new file mode 100644 index 000000000000..392290d3c931 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "sentry-project-436908" + } +} diff --git a/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/.gitignore b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/.gitignore new file mode 100644 index 000000000000..b17f63107554 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/.gitignore @@ -0,0 +1,69 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +firebase-debug.log* +firebase-debug.*.log* + +# Firebase cache +.firebase/ + +# Firebase config + +# Uncomment this if you'd like others to create their own Firebase project. +# For a team working on the same Firebase project(s), it is recommended to leave +# it commented so all members can deploy to the same project(s) in .firebaserc. +# .firebaserc + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# dataconnect generated files +.dataconnect diff --git a/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/createOrUpdateConfigIfPossible.js b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/createOrUpdateConfigIfPossible.js new file mode 100644 index 000000000000..3ac51191deab --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/createOrUpdateConfigIfPossible.js @@ -0,0 +1,3 @@ +const createOrUpdateConfigIfPossible = require('./utils').createOrUpdateConfigIfPossible; + +createOrUpdateConfigIfPossible(); diff --git a/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/database.rules.json b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/database.rules.json new file mode 100644 index 000000000000..4335e236f6db --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/database.rules.json @@ -0,0 +1,7 @@ +{ + /* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */ + "rules": { + ".read": false, + ".write": false + } +} diff --git a/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/firebase.json b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/firebase.json new file mode 100644 index 000000000000..714e003f7324 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/firebase.json @@ -0,0 +1,25 @@ +{ + "database": { + "rules": "database.rules.json" + }, + "firestore": { + "rules": "firestore.rules", + "indexes": "firestore.indexes.json" + }, + "emulators": { + "auth": { + "port": 5507 + }, + "firestore": { + "port": 5504 + }, + "database": { + "port": 5506 + }, + "ui": { + "enabled": true, + "port": 5500 + }, + "singleProjectMode": true + } +} diff --git a/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/firestore.indexes.json b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/firestore.indexes.json new file mode 100644 index 000000000000..415027e5ddaf --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/firestore.indexes.json @@ -0,0 +1,4 @@ +{ + "indexes": [], + "fieldOverrides": [] +} diff --git a/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/firestore.rules b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/firestore.rules new file mode 100644 index 000000000000..c3c1733dcd8b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/firestore.rules @@ -0,0 +1,8 @@ +rules_version = '2'; +service cloud.firestore { + match /databases/{database}/documents { + match /{document=**} { + allow read, write: if true; + } + } +} diff --git a/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/storage.rules b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/storage.rules new file mode 100644 index 000000000000..4cc806e7d390 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/storage.rules @@ -0,0 +1,8 @@ +rules_version = '2'; +service firebase.storage { + match /b/{bucket}/o { + match /{file=**} { + allow read, write: if true; + } + } +} diff --git a/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/utils.js b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/utils.js new file mode 100644 index 000000000000..0fc6069c682e --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/docker/firebase/utils.js @@ -0,0 +1,145 @@ +const fs = require('fs'); +const path = require('path'); + +const firebaseToolsFileName = 'firebase-tools.json'; +const updateNotifierFirebaseToolsFileName = 'update-notifier-firebase-tools.json'; + +function createJsonFile(filePath, json) { + return new Promise((resolve, reject) => { + let content = JSON.stringify(json, null, 2); + + // replace spaces with tabs + content = content.replace(/[ ]{2}/g, '\t'); + + fs.mkdirSync(filePath.substring(0, filePath.lastIndexOf('/')), { recursive: true }); + fs.writeFile(filePath, content, function (err) { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); +} + +function createEnvironmentFile(filePath, content) { + return new Promise((resolve, reject) => { + fs.writeFile(filePath, content, function (err) { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); +} + +function readJsonFromFile(filePath) { + return new Promise((resolve, reject) => { + fs.readFile(filePath, 'utf8', (err, data) => { + if (err) { + reject(err); + return; + } + try { + resolve(JSON.parse(data)); + } catch (err) { + reject(err); + console.error(err); + } + }); + }); +} + +/** + * Creates firebase configuration based on .env file + */ +async function createConfigFromEnv() { + const dockerPath = path.resolve(__dirname, '..'); + const configPath = path.resolve(dockerPath, '.config/configstore'); + + let filePathFirebaseTools = process.env.CONFIG_FIREBASE_TOOLS; + let filePathUpdateNotifierFirebaseTools = process.env.CONFIG_UPDATE_NOTIFIER_FIREBASE_TOOLS; + + if (typeof filePathFirebaseTools !== 'string') { + throw new Error('no CONFIG_FIREBASE_TOOLS environment'); + } + if (typeof filePathUpdateNotifierFirebaseTools !== 'string') { + throw new Error('no CONFIG_UPDATE_NOTIFIER_FIREBASE_TOOLS environment'); + } + + try { + filePathFirebaseTools = JSON.parse(filePathFirebaseTools); + filePathUpdateNotifierFirebaseTools = JSON.parse(filePathUpdateNotifierFirebaseTools); + + await Promise.all([ + createJsonFile(path.resolve(configPath, firebaseToolsFileName), filePathFirebaseTools), + createJsonFile( + path.resolve(configPath, updateNotifierFirebaseToolsFileName), + filePathUpdateNotifierFirebaseTools, + ), + ]); + console.log('firebase config based on environment variables created successfully'); + } catch (e) { + console.error('firebase config creation error', e); + } +} + +/** + * Creates file .env based on firebase configuration + */ +async function createEnvFromConfig() { + const dockerPath = path.resolve(__dirname, '..'); + const configPath = path.resolve(dockerPath, '.config/configstore'); + const dockerFilePath = path.resolve(dockerPath, '.env'); + try { + const results = await Promise.all([ + readJsonFromFile(path.resolve(configPath, firebaseToolsFileName)), + readJsonFromFile(path.resolve(configPath, updateNotifierFirebaseToolsFileName)), + ]); + const filePathFirebaseTools = results[0]; + const filePathUpdateNotifierFirebaseTools = results[1]; + + if (!filePathFirebaseTools) { + throw new Error('Environment variable '); + } + + const content = []; + content.push('# This is autogenerated'); + content.push(`CONFIG_FIREBASE_TOOLS=${JSON.stringify(filePathFirebaseTools)}`); + content.push(`CONFIG_UPDATE_NOTIFIER_FIREBASE_TOOLS=${JSON.stringify(filePathUpdateNotifierFirebaseTools)}`); + content.push(''); + await createEnvironmentFile(dockerFilePath, content.join('\n')); + + console.log(`environments variables saved in "${dockerFilePath}" based on firebase config`); + } catch (e) { + console.error(e); + } +} + +/** + * Creates or update the existing config whenever environment is defined. This is used by docker and will recreate + * the config each time the docker is run as long as the environment settings exist. + */ +function createOrUpdateConfigIfPossible() { + const filePathFirebaseTools = process.env.CONFIG_FIREBASE_TOOLS; + const filePathUpdateNotifierFirebaseTools = process.env.CONFIG_UPDATE_NOTIFIER_FIREBASE_TOOLS; + if ( + typeof filePathFirebaseTools === 'string' && + typeof filePathUpdateNotifierFirebaseTools === 'string' && + filePathFirebaseTools !== '' && + filePathUpdateNotifierFirebaseTools !== '' + ) { + createConfigFromEnv(); + } else { + console.error('>>>>>>>>>>>>>>>> WARNING <<<<<<<<<<<<<<<<<<<<<'); + console.error('firebase config creation failed due to missing environment variables'); + console.error('>>>>>>>>>>>>>>>> WARNING <<<<<<<<<<<<<<<<<<<<<'); + } +} + +module.exports = { + createEnvFromConfig: createEnvFromConfig, + createConfigFromEnv: createConfigFromEnv, + createOrUpdateConfigIfPossible: createOrUpdateConfigIfPossible, +}; diff --git a/dev-packages/e2e-tests/test-applications/firebase/docker/nginx.conf b/dev-packages/e2e-tests/test-applications/firebase/docker/nginx.conf new file mode 100644 index 000000000000..d8189878c99a --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/docker/nginx.conf @@ -0,0 +1,150 @@ +daemon off; +worker_processes 1; + +# error_log /dev/stderr; + +events { + worker_connections 1024; +} + +http { + client_max_body_size 100M; + + map $http_upgrade $connection_upgrade { + default upgrade; '' close; + } + + server { + listen 0.0.0.0:4001; + server_name ui; + location / { + proxy_pass http://127.0.0.1:5500; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + } + } + + server { + listen 0.0.0.0:4401; + server_name hub; + location / { + proxy_pass http://127.0.0.1:5501; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + } + } + + server { + listen 0.0.0.0:4601; + server_name logging; + location / { + proxy_pass http://127.0.0.1:5502; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + } + } + + server { + listen 0.0.0.0:5002; + server_name functions; + location / { + proxy_pass http://127.0.0.1:5503; + } + } + + server { + listen 0.0.0.0:8081; + server_name firestore; + location / { + proxy_pass http://127.0.0.1:5504; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + } + } + + server { + listen 0.0.0.0:8086; + http2 on; + server_name pubsub; + location / { + grpc_pass grpc://127.0.0.1:5505; + } + } + + server { + listen 0.0.0.0:9001; + server_name database; + location / { + proxy_pass http://127.0.0.1:5506; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + } + } + + server { + listen 0.0.0.0:9100; + server_name auth; + location / { + proxy_pass http://127.0.0.1:5507; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + } + } + + server { + listen 0.0.0.0:9200; + server_name cloud_storage; + location / { + proxy_pass http://127.0.0.1:5508; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + } + } + + server { + listen 0.0.0.0:6001; + server_name hosting; + location / { + proxy_pass http://127.0.0.1:5509; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + } + } + + server { + listen 0.0.0.0:9081; + http2 on; + server_name firestore; + location / { + grpc_pass grpc://127.0.0.1:5510; + } + } + + server { + listen 0.0.0.0:9230; + server_name cloud_functions_debug; + location / { + proxy_pass http://127.0.0.1:5511; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + } + } +} diff --git a/dev-packages/e2e-tests/test-applications/firebase/docker/serve.sh b/dev-packages/e2e-tests/test-applications/firebase/docker/serve.sh new file mode 100644 index 000000000000..23503e69109c --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/docker/serve.sh @@ -0,0 +1,64 @@ +#!/bin/bash +set -eo pipefail + +# Function to print error messages and exit +error_exit() { + echo "$1" 1>&2 + exit 1 +} + +# Sanity checks +[[ -z "${DATA_DIRECTORY}" ]] && echo "DATA_DIRECTORY environment variable missing, will not export or import data to firebase" +[[ -z "${FIREBASE_PROJECT}" ]] && error_exit "FIREBASE_PROJECT environment variable missing" + +dirs=("/srv/firebase/functions" "/srv/firebase/firestore" "/srv/firebase/storage") + +for dir in "${dirs[@]}"; do + if [[ -d "$dir" ]]; then + echo "Installing npm packages in $dir" + npm install --prefix "$dir" || error_exit "npm install failed in $dir" + fi +done + +if [[ -z "${CONFIG_FIREBASE_TOOLS}" ]];then + echo "CONFIG_FIREBASE_TOOLS environment variable missing" +fi +if [[ -z "${CONFIG_UPDATE_NOTIFIER_FIREBASE_TOOLS}" ]];then + echo "CONFIG_UPDATE_NOTIFIER_FIREBASE_TOOLS environment variable missing" +fi + +node createOrUpdateConfigIfPossible.js +sleep 1 + +# Start Firebase emulators +emulator_cmd="firebase emulators:start --project=${FIREBASE_PROJECT}" +[[ -n "${DATA_DIRECTORY}" ]] && emulator_cmd+=" --import=./${DATA_DIRECTORY}/export --export-on-exit" +$emulator_cmd & +firebase_pid=$! + +# Start nginx and npm +echo "Starting nginx..." +nginx & +nginx_pid=$! + +cleanup() { + echo "Stopping services..." + # Gracefully stop background processes + echo "Terminating background services..." + if [[ -n "$firebase_pid" ]]; then + kill -SIGTERM "$firebase_pid" || echo "Failed to terminate Firebase process" + wait "$firebase_pid" 2>/dev/null + fi + if [[ -n "$nginx_pid" ]]; then + kill -SIGTERM "$nginx_pid" || echo "Failed to terminate Nginx process" + wait "$nginx_pid" 2>/dev/null + fi + if [[ -n "$npm_pid" ]]; then + kill -SIGTERM "$npm_pid" || echo "Failed to terminate NPM process" + wait "$npm_pid" 2>/dev/null + fi +} + +trap cleanup INT TERM SIGTERM SIGINT + +wait diff --git a/dev-packages/e2e-tests/test-applications/firebase/package.json b/dev-packages/e2e-tests/test-applications/firebase/package.json new file mode 100644 index 000000000000..5cad8326c359 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/package.json @@ -0,0 +1,29 @@ +{ + "name": "firebase", + "version": "0.0.1", + "private": true, + "scripts": { + "build": "tsc", + "createEnvFromConfig": "node createEnvFromConfig.js", + "createConfigFromEnv": "node createConfigFromEnv.js", + "dev": "tsc --build --watch", + "docker": "cd docker && docker compose up --build", + "proxy": "node start-event-proxy.mjs", + "start": "node ./dist/app.js", + "test": "playwright test", + "clean": "npx rimraf node_modules pnpm-lock.yaml", + "test:build": "pnpm install && pnpm build", + "test:assert": "pnpm test" + }, + "devDependencies": { + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", + "dotenv": "^16.4.5", + "firebase": "^11.0.1", + "tsconfig-paths": "^4.2.0", + "typescript": "4.9.5" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/dev-packages/e2e-tests/test-applications/firebase/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/firebase/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/firebase/src/app.ts b/dev-packages/e2e-tests/test-applications/firebase/src/app.ts new file mode 100644 index 000000000000..01567bc683ec --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/src/app.ts @@ -0,0 +1,71 @@ +import * as Sentry from '@sentry/node'; +import './init'; +import express from 'express'; +import type { FirebaseOptions } from '@firebase/app'; +import { initializeApp } from 'firebase/app'; +import { + addDoc, + collection, + connectFirestoreEmulator, + deleteDoc, + doc, + getDocs, + getFirestore, + setDoc, +} from 'firebase/firestore/lite'; // seems like "firebase/firestore" is trying to use grpc for connection and it + +const options: FirebaseOptions = { + projectId: 'sentry-15d85', + apiKey: 'sentry-fake-api-key', +}; + +const app = initializeApp(options); + +const db = getFirestore(app); +connectFirestoreEmulator(db, '127.0.0.1', 5504); +const citiesRef = collection(db, 'cities'); + +async function addCity(): Promise { + await addDoc(citiesRef, { + name: 'San Francisco', + }); +} + +async function getCities(): Promise { + const citySnapshot = await getDocs(citiesRef); + const cityList = citySnapshot.docs.map(doc => doc.data()); + return cityList; +} + +async function deleteCity(): Promise { + await deleteDoc(doc(citiesRef, 'SF')); +} + +async function setCity(): Promise { + await setDoc(doc(citiesRef, 'SF'), { + name: 'San Francisco', + state: 'CA', + country: 'USA', + capital: false, + population: 860000, + regions: ['west_coast', 'norcal'], + }); +} + +const expressApp = express(); +const port = 3030; + +expressApp.get('/test', async function (req, res) { + await Sentry.startSpan({ name: 'root span' }, async () => { + await addCity(); + await setCity(); + await getCities(); + await deleteCity(); + }); + await Sentry.flush(); + res.send({ version: 'v1' }); +}); + +expressApp.listen(port, () => { + console.log(`Example app listening on port ${port}`); +}); diff --git a/dev-packages/e2e-tests/test-applications/firebase/src/init.ts b/dev-packages/e2e-tests/test-applications/firebase/src/init.ts new file mode 100644 index 000000000000..23c3d2fa5974 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/src/init.ts @@ -0,0 +1,11 @@ +import * as Sentry from '@sentry/node'; + + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + tracesSampleRate: 1.0, + integrations: [Sentry.firebaseIntegration()], + defaultIntegrations: false, + tunnel: `http://localhost:3031/`, // proxy server +}); diff --git a/dev-packages/e2e-tests/test-applications/firebase/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/firebase/start-event-proxy.mjs new file mode 100644 index 000000000000..6d7cc1cb3b95 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/start-event-proxy.mjs @@ -0,0 +1,6 @@ +import { startEventProxyServer } from '@sentry-internal/test-utils'; + +startEventProxyServer({ + port: 3031, + proxyServerName: 'firebase', +}); diff --git a/dev-packages/e2e-tests/test-applications/firebase/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/firebase/tests/transactions.test.ts new file mode 100644 index 000000000000..ac8256424861 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/tests/transactions.test.ts @@ -0,0 +1,110 @@ +import { expect, test } from '@playwright/test'; +import { waitForTransaction } from '@sentry-internal/test-utils'; +import { runDockerCompose } from '../../../../node-integration-tests/utils/runner'; + +const spanAddDoc = expect.objectContaining({ + description: 'addDoc cities', + data: expect.objectContaining({ + 'db.collection.name': 'cities', + 'db.namespace': '[DEFAULT]', + 'db.operation.name': 'addDoc', + 'db.system': 'firebase.firestore', + 'firebase.firestore.options.projectId': 'sentry-15d85', + 'firebase.firestore.type': 'collection', + 'otel.kind': 'CLIENT', + 'server.address': '127.0.0.1', + 'server.port': '5504', + 'sentry.origin': 'auto.firebase.otel.firestore', + 'sentry.op': 'addDoc', + }), + status: 'ok', +}); + +const spanSetDocs = expect.objectContaining({ + description: 'setDocs cities', + data: expect.objectContaining({ + 'db.collection.name': 'cities', + 'db.namespace': '[DEFAULT]', + 'db.operation.name': 'setDocs', + 'db.system': 'firebase.firestore', + 'firebase.firestore.options.projectId': 'sentry-15d85', + 'firebase.firestore.type': 'collection', + 'otel.kind': 'CLIENT', + 'server.address': '127.0.0.1', + 'server.port': '5504', + 'sentry.origin': 'auto.firebase.otel.firestore', + 'sentry.op': 'setDocs', + }), + status: 'ok', +}); + +const spanGetDocs = expect.objectContaining({ + description: 'getDocs cities', + data: expect.objectContaining({ + 'db.collection.name': 'cities', + 'db.namespace': '[DEFAULT]', + 'db.operation.name': 'getDocs', + 'db.system': 'firebase.firestore', + 'firebase.firestore.options.projectId': 'sentry-15d85', + 'firebase.firestore.type': 'collection', + 'otel.kind': 'CLIENT', + 'server.address': '127.0.0.1', + 'server.port': '5504', + 'sentry.origin': 'auto.firebase.otel.firestore', + 'sentry.op': 'getDocs', + }), + status: 'ok', +}); + +const spanDeleteDoc = expect.objectContaining({ + description: 'deleteDoc cities', + data: expect.objectContaining({ + 'db.collection.name': 'cities', + 'db.namespace': '[DEFAULT]', + 'db.operation.name': 'deleteDoc', + 'db.system': 'firebase.firestore', + 'firebase.firestore.options.projectId': 'sentry-15d85', + 'firebase.firestore.type': 'collection', + 'otel.kind': 'CLIENT', + 'server.address': '127.0.0.1', + 'server.port': '5504', + 'sentry.origin': 'auto.firebase.otel.firestore', + 'sentry.op': 'deleteDoc', + }), + status: 'ok', +}); + +let dockerChild; + +test.beforeAll(async () => { + console.log('creating firebase docker'); + dockerChild = await runDockerCompose({ + workingDirectory: [__dirname, '../docker'], + readyMatches: ['Emulator Hub running at'], + }); + console.log('firebase docker created'); +}); + +test.afterAll(() => { + dockerChild(); + console.log('firebase docker closed'); +}); + +test('should add, set, get and delete document', async ({ baseURL, page }) => { + const serverTransactionPromise = waitForTransaction('firebase', () => { + return true; + }); + + await fetch(`${baseURL}/test`); + + const transactionEvent = await serverTransactionPromise; + + expect(transactionEvent.transaction).toEqual('root span'); + + expect(transactionEvent.spans?.length).toEqual(4); + + expect(transactionEvent.spans![0]).toMatchObject(spanAddDoc); + expect(transactionEvent.spans![1]).toMatchObject(spanSetDocs); + expect(transactionEvent.spans![2]).toMatchObject(spanGetDocs); + expect(transactionEvent.spans![3]).toMatchObject(spanDeleteDoc); +}); diff --git a/dev-packages/e2e-tests/test-applications/firebase/tsconfig.build.json b/dev-packages/e2e-tests/test-applications/firebase/tsconfig.build.json new file mode 100644 index 000000000000..26c30d4eddf2 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist"] +} diff --git a/dev-packages/e2e-tests/test-applications/firebase/tsconfig.json b/dev-packages/e2e-tests/test-applications/firebase/tsconfig.json new file mode 100644 index 000000000000..8cb64e989ed9 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "types": ["node"], + "esModuleInterop": true, + "lib": ["es2018"], + "strict": true, + "outDir": "dist" + }, + "include": ["src/**/*.ts"] +} diff --git a/dev-packages/e2e-tests/test-applications/firebase/yarn.lock b/dev-packages/e2e-tests/test-applications/firebase/yarn.lock new file mode 100644 index 000000000000..ee5e2c8f88df --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/firebase/yarn.lock @@ -0,0 +1,749 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@firebase/analytics-compat@0.2.15": + version "0.2.15" + resolved "https://registry.yarnpkg.com/@firebase/analytics-compat/-/analytics-compat-0.2.15.tgz#91ce1983b980f66e53c28a7cc4b596e551be5f97" + integrity sha512-C5to422Sr8FkL0MPwXcIecbMnF4o2Ll7MtoWvIm4Q/LPJvvM+tWa1DiU+LzsCdsd1/CYE9EIW9Ma3ko9XnAAYw== + dependencies: + "@firebase/analytics" "0.10.9" + "@firebase/analytics-types" "0.8.2" + "@firebase/component" "0.6.10" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/analytics-types@0.8.2": + version "0.8.2" + resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.8.2.tgz#947f85346e404332aac6c996d71fd4a89cd7f87a" + integrity sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw== + +"@firebase/analytics@0.10.9": + version "0.10.9" + resolved "https://registry.yarnpkg.com/@firebase/analytics/-/analytics-0.10.9.tgz#b1ba347405346b2daaee61dc6daa0dfaf0c8a209" + integrity sha512-FrvW6u6xDBKXUGYUy1WIUh0J9tvbppMsk90mig0JhHST8iLveKu/dIBVeVE/ZYZhmXy4fkI7SPSWvD1V0O4tXw== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/installations" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/app-check-compat@0.3.16": + version "0.3.16" + resolved "https://registry.yarnpkg.com/@firebase/app-check-compat/-/app-check-compat-0.3.16.tgz#cd1c5e9d0144e04f88afbfb3b82ce69730fac047" + integrity sha512-AxIGzLRXrTFNL+H6V+4BO0w/gERloROfRbWI/FoJUnQd0qPZIzyfdHZBbThFzFGLfDt/mVs2kdjYFx/l9I8NhQ== + dependencies: + "@firebase/app-check" "0.8.9" + "@firebase/app-check-types" "0.5.2" + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/app-check-interop-types@0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.2.tgz#455b6562c7a3de3ef75ea51f72dfec5829ad6997" + integrity sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ== + +"@firebase/app-check-types@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@firebase/app-check-types/-/app-check-types-0.5.2.tgz#1221bd09b471e11bb149252f16640a0a51043cbc" + integrity sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA== + +"@firebase/app-check@0.8.9": + version "0.8.9" + resolved "https://registry.yarnpkg.com/@firebase/app-check/-/app-check-0.8.9.tgz#da12501dd42686cb283169cfcb1413ddede7e99e" + integrity sha512-YzVn1mMLzD2JboMPVVO0Pe20YOgWzrF+aXoAmmd0v3xec051n83YpxSUZbacL69uYvk0dHrEsbea44QtQ5WPDA== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/app-compat@0.2.45": + version "0.2.45" + resolved "https://registry.yarnpkg.com/@firebase/app-compat/-/app-compat-0.2.45.tgz#2541fa77eba61de9d3d437df76c28e21d7e66839" + integrity sha512-5rYbXq1ndtMTg+07oH4WrkYuP+NZq61uzVwW1hlmybp/gr4cXq2SfaP9fc6/9IzTKmu3dh3H0fjj++HG7Z7o/w== + dependencies: + "@firebase/app" "0.10.15" + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/app-types@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.9.2.tgz#8cbcceba784753a7c0066a4809bc22f93adee080" + integrity sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ== + +"@firebase/app@0.10.15": + version "0.10.15" + resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.10.15.tgz#5328c05ace83902aa19ea673322147b0179970cb" + integrity sha512-he6qlG3pmwL+LHdG/BrSMBQeJzzutciq4fpXN3lGa1uSwYSijJ24VtakS/bP2X9SiDf8jGywJ4u+OgXAenJsNg== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/auth-compat@0.5.15": + version "0.5.15" + resolved "https://registry.yarnpkg.com/@firebase/auth-compat/-/auth-compat-0.5.15.tgz#7f3f9a90aae3721031fc98103a15600d24d8d2c0" + integrity sha512-jz6k1ridPiecKI8CBRiqCM6IMOhwYp2MD+YvoxnMiK8nQLSTm57GvHETlPNX3WlbyQnCjMCOvrAhe27whyxAEg== + dependencies: + "@firebase/auth" "1.8.0" + "@firebase/auth-types" "0.12.2" + "@firebase/component" "0.6.10" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/auth-interop-types@0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz#927f1f2139a680b55fef0bddbff2c982b08587e8" + integrity sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ== + +"@firebase/auth-types@0.12.2": + version "0.12.2" + resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.12.2.tgz#f12d890585866e53b6ab18b16fa4d425c52eee6e" + integrity sha512-qsEBaRMoGvHO10unlDJhaKSuPn4pyoTtlQuP1ghZfzB6rNQPuhp/N/DcFZxm9i4v0SogjCbf9reWupwIvfmH6w== + +"@firebase/auth@1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-1.8.0.tgz#51fc42016b747bf82b43b8ae6731761386377915" + integrity sha512-/O7UDWE5S5ux456fzNHSLx/0YN/Kykw/WyAzgDQ6wvkddZhSEmPX19EzxgsFldzhuFjsl5uOZTz8kzlosCiJjg== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/component@0.6.10": + version "0.6.10" + resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.6.10.tgz#5d2abe7c5c18d60ae806be8bcc698ca1bee7acbf" + integrity sha512-OsNbEKyz9iLZSmMUhsl6+kCADzte00iisJIRUspnUqvDCX+RSGZOBIqekukv/jN177ovjApBQNFaxSYIDc/SyQ== + dependencies: + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/data-connect@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@firebase/data-connect/-/data-connect-0.1.1.tgz#99738c28319c4debc47a921933a1bc7b6bb8f945" + integrity sha512-RBJ7XE/a3oXFv31Jlw8cbMRdsxQoI8F3L7xm4n93ab+bIr1NQUiYGgW9L7TTw7obdNev91ZnW0xfqJtXcPA5yA== + dependencies: + "@firebase/auth-interop-types" "0.2.3" + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/database-compat@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@firebase/database-compat/-/database-compat-2.0.0.tgz#fc702576c2bcf4ee0a8b80351b86885d251a03bd" + integrity sha512-2xlODKWwf/vNAxCmou0GFhymx2pqZKkhXMN9B5aiTjZ6+81sOxGim53ELY2lj+qKG2IvgiCYFc4X+ZJA2Ad5vg== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/database" "1.0.9" + "@firebase/database-types" "1.0.6" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/database-types@1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-1.0.6.tgz#97e3026e726ebfd489dbce095371b47c69387bc9" + integrity sha512-sMI7IynSZBsyGbUugc8PKE1jwKbnvaieAz/RxuM57PZQNCi6Rteiviwcw/jqZOX6igqYJwXWZ3UzKOZo2nUDRA== + dependencies: + "@firebase/app-types" "0.9.2" + "@firebase/util" "1.10.1" + +"@firebase/database@1.0.9": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@firebase/database/-/database-1.0.9.tgz#1e4862542b3a93e8039cb3a5a25c79fe5ff1f212" + integrity sha512-EkiPSKSu2TJJGtOjyISASf3UFpFJDil1lMbfqnxilfbmIsilvC8DzgjuLoYD+eOitcug4wtU9Fh1tt2vgBhskA== + dependencies: + "@firebase/app-check-interop-types" "0.3.2" + "@firebase/auth-interop-types" "0.2.3" + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + faye-websocket "0.11.4" + tslib "^2.1.0" + +"@firebase/firestore-compat@0.3.39": + version "0.3.39" + resolved "https://registry.yarnpkg.com/@firebase/firestore-compat/-/firestore-compat-0.3.39.tgz#b34d3cef25d5956a4332f464ab41681d6087d5b4" + integrity sha512-CsK8g34jNeHx95LISDRTcArJLonW+zJCqHI1Ez9WNiLAK2X8FeQ4UiD+RwOwxAIR+t2a6xED/5Fe6ZIqx7MuoQ== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/firestore" "4.7.4" + "@firebase/firestore-types" "3.0.2" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/firestore-types@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-3.0.2.tgz#75c301acc5fa33943eaaa9570b963c55398cad2a" + integrity sha512-wp1A+t5rI2Qc/2q7r2ZpjUXkRVPtGMd6zCLsiWurjsQpqPgFin3AhNibKcIzoF2rnToNa/XYtyWXuifjOOwDgg== + +"@firebase/firestore@4.7.4": + version "4.7.4" + resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-4.7.4.tgz#f24e5ceffd607fb93d652512261a8c3526b938a6" + integrity sha512-K2nq4w+NF8J1waGawY5OHLawP/Aw5CYxyDstVv1NZemGPcM3U+LZ9EPaXr1PatYIrPA7fS4DxZoWcbB0aGJ8Zg== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + "@firebase/webchannel-wrapper" "1.0.2" + "@grpc/grpc-js" "~1.9.0" + "@grpc/proto-loader" "^0.7.8" + tslib "^2.1.0" + +"@firebase/functions-compat@0.3.15": + version "0.3.15" + resolved "https://registry.yarnpkg.com/@firebase/functions-compat/-/functions-compat-0.3.15.tgz#d32277390296d65f4266d208e7243573ed3cc85d" + integrity sha512-eiHpc6Sd9Y/SNhBsGi944SapiFbfTPKsiSUQ74QxNSs0yoxvABeIRolVMFk4TokP57NGmstGYpYte02XGNPcYw== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/functions" "0.11.9" + "@firebase/functions-types" "0.6.2" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/functions-types@0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@firebase/functions-types/-/functions-types-0.6.2.tgz#03b4ec9259d2f57548a3909d6a35ae35ad243552" + integrity sha512-0KiJ9lZ28nS2iJJvimpY4nNccV21rkQyor5Iheu/nq8aKXJqtJdeSlZDspjPSBBiHRzo7/GMUttegnsEITqR+w== + +"@firebase/functions@0.11.9": + version "0.11.9" + resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.11.9.tgz#6ddc28353a366ab4e6d4133753c5578b7b27ab62" + integrity sha512-dhO5IUfQRCsrc20YD20nSOX+QCT+cH6N86HlZOLz2XgyEFgzOdBQnUot4EabBJQRkMBI7fZWUrbYfRcnov53ug== + dependencies: + "@firebase/app-check-interop-types" "0.3.2" + "@firebase/auth-interop-types" "0.2.3" + "@firebase/component" "0.6.10" + "@firebase/messaging-interop-types" "0.2.2" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/installations-compat@0.2.10": + version "0.2.10" + resolved "https://registry.yarnpkg.com/@firebase/installations-compat/-/installations-compat-0.2.10.tgz#5bcb60f36db2028843f350199566d1065dc9a62a" + integrity sha512-YTonkcVz3AK7RF8xFhvs5CwDuJ0xbzzCJIwXoV14gnzdYbMgy6vWlUUbzkvbtEDXzPRHB0n7aGZl56oy9dLOFw== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/installations" "0.6.10" + "@firebase/installations-types" "0.5.2" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/installations-types@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@firebase/installations-types/-/installations-types-0.5.2.tgz#4d4949e0e83ced7f36cbee009355cd305a36e158" + integrity sha512-que84TqGRZJpJKHBlF2pkvc1YcXrtEDOVGiDjovP/a3s6W4nlbohGXEsBJo0JCeeg/UG9A+DEZVDUV9GpklUzA== + +"@firebase/installations@0.6.10": + version "0.6.10" + resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.6.10.tgz#cff44e441ff2fe8cb8f0111acf612ba64d32870b" + integrity sha512-TuGSOMqkFrllxa0X/8VZIqBCRH4POndU/iWKWkRmkh12+/xKSpdp+y/kWaVbsySrelltan6LeYlcYPmLibWbwg== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/util" "1.10.1" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/logger@0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.4.3.tgz#e7e55c022b62083307a428b6d03f86db012eca88" + integrity sha512-Th42bWJg18EF5bJwhRosn2M/eYxmbWCwXZr4hHX7ltO0SE3QLrpgiMKeRBR/NW7vJke7i0n3i8esbCW2s93qBw== + dependencies: + tslib "^2.1.0" + +"@firebase/messaging-compat@0.2.13": + version "0.2.13" + resolved "https://registry.yarnpkg.com/@firebase/messaging-compat/-/messaging-compat-0.2.13.tgz#6189e43a765edd9d9d88dc2bbf9e794ce4e33cb0" + integrity sha512-9ootPClS6m2c2KIzo7AqSHaWzAw28zWcjQPjVv7WeQDu6wjufpbOg+7tuVzb+gqpF9Issa3lDoYOwlO0ZudO3g== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/messaging" "0.12.13" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/messaging-interop-types@0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.2.tgz#81042f7e9739733fa4571d17f6eb6869522754d0" + integrity sha512-l68HXbuD2PPzDUOFb3aG+nZj5KA3INcPwlocwLZOzPp9rFM9yeuI9YLl6DQfguTX5eAGxO0doTR+rDLDvQb5tA== + +"@firebase/messaging@0.12.13": + version "0.12.13" + resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.12.13.tgz#7008a6d31b8dd1cdac067b9885f3fec927f565df" + integrity sha512-YLa8PWl+BgiOVR5WOyzl21fVJFJeBRfniNuN25d9DBrQzppSAahuN6yS+vt1OIjvZNPN4pZ/lcRLYupbGu4W0w== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/installations" "0.6.10" + "@firebase/messaging-interop-types" "0.2.2" + "@firebase/util" "1.10.1" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/performance-compat@0.2.10": + version "0.2.10" + resolved "https://registry.yarnpkg.com/@firebase/performance-compat/-/performance-compat-0.2.10.tgz#e42d3a7afc7650903e55c357fecf3a3227883a43" + integrity sha512-0h1qYkF6I79DSSpHfTQFvb91fo8shmmwiPzWFYAPdPK02bSWpKwVssNYlZX2iUnumxerDMbl7dWN+Im/W3bnXA== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/performance" "0.6.10" + "@firebase/performance-types" "0.2.2" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/performance-types@0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@firebase/performance-types/-/performance-types-0.2.2.tgz#7b78cd2ab2310bac89a63348d93e67e01eb06dd7" + integrity sha512-gVq0/lAClVH5STrIdKnHnCo2UcPLjJlDUoEB/tB4KM+hAeHUxWKnpT0nemUPvxZ5nbdY/pybeyMe8Cs29gEcHA== + +"@firebase/performance@0.6.10": + version "0.6.10" + resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.6.10.tgz#ae734d7f56105ef181f2bcbfb44eb0696c16f986" + integrity sha512-x/mNYKGxq7A+QV0EiEZeD2S+E+kw+UcZ8FXuE7qDJyGGt/0Wd+bIIL7RakG/VrFt7/UYc//nKygDc7/Ig7sOmQ== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/installations" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/remote-config-compat@0.2.10": + version "0.2.10" + resolved "https://registry.yarnpkg.com/@firebase/remote-config-compat/-/remote-config-compat-0.2.10.tgz#416238bc86b604682d866c54f659da0588ddb182" + integrity sha512-fIi5OB2zk0zpChMV/tTd0oEZcZI8TlwQDlLlcrDpMOV5l5dqd0JNlWKh6Fwmh4izmytk+rZIAIpnak/NjGVesQ== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/remote-config" "0.4.10" + "@firebase/remote-config-types" "0.3.2" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/remote-config-types@0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@firebase/remote-config-types/-/remote-config-types-0.3.2.tgz#a5d1009c6fd08036c5cd4f28764e3cd694f966d5" + integrity sha512-0BC4+Ud7y2aPTyhXJTMTFfrGGLqdYXrUB9sJVAB8NiqJswDTc4/2qrE/yfUbnQJhbSi6ZaTTBKyG3n1nplssaA== + +"@firebase/remote-config@0.4.10": + version "0.4.10" + resolved "https://registry.yarnpkg.com/@firebase/remote-config/-/remote-config-0.4.10.tgz#ad2ebab95d5cde6f096bdec288c8149376dba55b" + integrity sha512-jTRjy3TdqzVna19m5a1HEHE5BG4Z3BQTxBgvQRTmMKlHacx4QS0CToAas7R9M9UkxpgFcVuAE7FpWIOWQGCEWw== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/installations" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/storage-compat@0.3.13": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@firebase/storage-compat/-/storage-compat-0.3.13.tgz#da35d68fd2eeecbe84ab730229b855896299612f" + integrity sha512-15kje7JALswRCBKsCSvKg5FbqUYykaIMqMbZRD7I6uVRWwdyTvez5MBQfMhBia2JcEmPiDpXhJTXH4PAWFiA8g== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/storage" "0.13.3" + "@firebase/storage-types" "0.8.2" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/storage-types@0.8.2": + version "0.8.2" + resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.8.2.tgz#edb321b8a3872a9f74e1f27de046f160021c8e1f" + integrity sha512-0vWu99rdey0g53lA7IShoA2Lol1jfnPovzLDUBuon65K7uKG9G+L5uO05brD9pMw+l4HRFw23ah3GwTGpEav6g== + +"@firebase/storage@0.13.3": + version "0.13.3" + resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.13.3.tgz#b48e494bcbb9b662fd4cf78d18f48ae3059249a1" + integrity sha512-B5HiJ7isYKaT4dOEV43f2ySdhQxzq+SQEm7lqXebJ8AYCsebdHrgGzrPR0LR962xGjPzJHFKx63gA8Be/P2MCw== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/util@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@firebase/util/-/util-1.10.1.tgz#1af07dff98320b45c6eb46d7992e88800b97cba2" + integrity sha512-AIhFnCCjM8FmCqSNlNPTuOk3+gpHC1RkeNUBLtPbcqGYpN5MxI5q7Yby+rxycweOZOCboDzfIj8WyaY4tpQG/g== + dependencies: + tslib "^2.1.0" + +"@firebase/vertexai@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@firebase/vertexai/-/vertexai-1.0.0.tgz#da4310d0cae590b372939aacc2b1e16b86e30732" + integrity sha512-48N3Lp/9GgiCCRfrSdHS+Y1IiMdYXvnHFO/f+HL1PgUtBq7WQ/fWmYOX3mzAN36zvytq13nb68ImF+GALopp+Q== + dependencies: + "@firebase/app-check-interop-types" "0.3.2" + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/webchannel-wrapper@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.2.tgz#7f583968e0f9d18420ec9ce78520aaf90d7c8ba5" + integrity sha512-3F4iA2E+NtdMbOU0XC1cHE8q6MqpGIKRj62oGOF38S6AAx5VHR9cXmoDUSj7ejvTAT7m6jxuEeQkHeq0F+mU2w== + +"@grpc/grpc-js@~1.9.0": + version "1.9.15" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.15.tgz#433d7ac19b1754af690ea650ab72190bd700739b" + integrity sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ== + dependencies: + "@grpc/proto-loader" "^0.7.8" + "@types/node" ">=12.12.47" + +"@grpc/proto-loader@^0.7.8": + version "0.7.13" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.13.tgz#f6a44b2b7c9f7b609f5748c6eac2d420e37670cf" + integrity sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw== + dependencies: + lodash.camelcase "^4.3.0" + long "^5.0.0" + protobufjs "^7.2.5" + yargs "^17.7.2" + +"@playwright/test@^1.44.1": + version "1.48.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.48.1.tgz#343e710fcf2e559529e3ec8d7782e09f325b9396" + integrity sha512-s9RtWoxkOLmRJdw3oFvhFbs9OJS0BzrLUc8Hf6l2UdCNd1rqeEyD4BhCJkvzeEoD1FsK4mirsWwGerhVmYKtZg== + dependencies: + playwright "1.48.1" + +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== + +"@sentry-internal/test-utils@link:../../../test-utils": + version "0.0.0" + uid "" + +"@types/node@>=12.12.47", "@types/node@>=13.7.0": + version "22.8.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.8.4.tgz#ab754f7ac52e1fe74174f761c5b03acaf06da0dc" + integrity sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw== + dependencies: + undici-types "~6.19.8" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +dotenv@^16.4.5: + version "16.4.5" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" + integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +escalade@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +faye-websocket@0.11.4: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + +firebase@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/firebase/-/firebase-11.0.1.tgz#e1c879f3473892adb88a467cf98c3b8cb9eeaea0" + integrity sha512-qsFb8dMcQINEDhJteG7RP+GqwgSRvfyiexQqHd5JToDdm87i9I2rGC4XQsGawKGxzKwZ/ISdgwNWxXAFYdCC6A== + dependencies: + "@firebase/analytics" "0.10.9" + "@firebase/analytics-compat" "0.2.15" + "@firebase/app" "0.10.15" + "@firebase/app-check" "0.8.9" + "@firebase/app-check-compat" "0.3.16" + "@firebase/app-compat" "0.2.45" + "@firebase/app-types" "0.9.2" + "@firebase/auth" "1.8.0" + "@firebase/auth-compat" "0.5.15" + "@firebase/data-connect" "0.1.1" + "@firebase/database" "1.0.9" + "@firebase/database-compat" "2.0.0" + "@firebase/firestore" "4.7.4" + "@firebase/firestore-compat" "0.3.39" + "@firebase/functions" "0.11.9" + "@firebase/functions-compat" "0.3.15" + "@firebase/installations" "0.6.10" + "@firebase/installations-compat" "0.2.10" + "@firebase/messaging" "0.12.13" + "@firebase/messaging-compat" "0.2.13" + "@firebase/performance" "0.6.10" + "@firebase/performance-compat" "0.2.10" + "@firebase/remote-config" "0.4.10" + "@firebase/remote-config-compat" "0.2.10" + "@firebase/storage" "0.13.3" + "@firebase/storage-compat" "0.3.13" + "@firebase/util" "1.10.1" + "@firebase/vertexai" "1.0.0" + +fsevents@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + +idb@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b" + integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +json5@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +long@^5.0.0: + version "5.2.3" + resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" + integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== + +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +playwright-core@1.48.1: + version "1.48.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.48.1.tgz#5fe28fb9a9326dae88d4608c35e819163cceeb23" + integrity sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA== + +playwright@1.48.1: + version "1.48.1" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.48.1.tgz#2a920cfbec4572c84789e757d8b044baaed49435" + integrity sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w== + dependencies: + playwright-core "1.48.1" + optionalDependencies: + fsevents "2.3.2" + +protobufjs@^7.2.5: + version "7.4.0" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.4.0.tgz#7efe324ce9b3b61c82aae5de810d287bc08a248a" + integrity sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/node" ">=13.7.0" + long "^5.0.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +safe-buffer@>=5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +tsconfig-paths@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" + integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== + dependencies: + json5 "^2.2.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@^2.1.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.0.tgz#d124c86c3c05a40a91e6fdea4021bd31d377971b" + integrity sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA== + +typescript@4.9.5: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + +undici-types@~6.19.8: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +websocket-driver@>=0.5.1: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" diff --git a/dev-packages/node-integration-tests/.eslintignore b/dev-packages/node-integration-tests/.eslintignore new file mode 100644 index 000000000000..2a4eaea7016b --- /dev/null +++ b/dev-packages/node-integration-tests/.eslintignore @@ -0,0 +1,3 @@ +.config +suites/tracing/firebase/docker/cache +suites/tracing/firebase/docker/firebase/data/** diff --git a/dev-packages/node-integration-tests/utils/runner.ts b/dev-packages/node-integration-tests/utils/runner.ts index bde5bd06cd21..31ec9e9aa3ff 100644 --- a/dev-packages/node-integration-tests/utils/runner.ts +++ b/dev-packages/node-integration-tests/utils/runner.ts @@ -107,7 +107,7 @@ interface DockerOptions { * * Returns a function that can be called to docker compose down */ -async function runDockerCompose(options: DockerOptions): Promise { +export async function runDockerCompose(options: DockerOptions): Promise { return new Promise((resolve, reject) => { const cwd = join(...options.workingDirectory); const close = (): void => { diff --git a/packages/astro/src/index.server.ts b/packages/astro/src/index.server.ts index b544b71087fc..93a67861ffbd 100644 --- a/packages/astro/src/index.server.ts +++ b/packages/astro/src/index.server.ts @@ -14,6 +14,7 @@ export { addOpenTelemetryInstrumentation, addRequestDataToEvent, amqplibIntegration, + firebaseIntegration, anrIntegration, captureCheckIn, captureConsoleIntegration, diff --git a/packages/node/package.json b/packages/node/package.json index a4d3bdd3e457..323c96c6078c 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -102,7 +102,8 @@ "import-in-the-middle": "^1.11.2" }, "devDependencies": { - "@types/node": "^14.18.0" + "@types/node": "^14.18.0", + "firebase": "11.0.1" }, "scripts": { "build": "run-p build:transpile build:types", diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index 2e658f7abc36..0136bc67eb11 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -32,6 +32,7 @@ export { genericPoolIntegration } from './integrations/tracing/genericPool'; export { dataloaderIntegration } from './integrations/tracing/dataloader'; export { amqplibIntegration } from './integrations/tracing/amqplib'; export { processThreadBreadcrumbIntegration } from './integrations/processThread'; +export { firebaseIntegration } from './integrations/tracing/firebase'; export { SentryContextManager } from './otel/contextManager'; export { generateInstrumentOnce } from './otel/instrument'; diff --git a/packages/node/src/integrations/tracing/firebase/README.md b/packages/node/src/integrations/tracing/firebase/README.md new file mode 100644 index 000000000000..6d839a4476f5 --- /dev/null +++ b/packages/node/src/integrations/tracing/firebase/README.md @@ -0,0 +1 @@ +The structure inside OTEL is to be kept as close as possible to opentelemetry plugin. diff --git a/packages/node/src/integrations/tracing/firebase/firebase.ts b/packages/node/src/integrations/tracing/firebase/firebase.ts new file mode 100644 index 000000000000..483d03bc1dc8 --- /dev/null +++ b/packages/node/src/integrations/tracing/firebase/firebase.ts @@ -0,0 +1,38 @@ +import type { Span } from '@opentelemetry/api'; +import type { ReadableSpan } from '@opentelemetry/sdk-trace-base'; +import { defineIntegration, SEMANTIC_ATTRIBUTE_SENTRY_OP } from '@sentry/core'; +import type { IntegrationFn } from '@sentry/types'; +import { generateInstrumentOnce } from '../../../otel/instrument'; +import { addOriginToSpan } from '../../../utils/addOriginToSpan'; +import { FirebaseInstrumentation, type FirebaseInstrumentationConfig } from './otel'; +import { ATTR_DB_OPERATION_NAME } from './otel/otelMissingSemanticConventions'; + +const INTEGRATION_NAME = 'Firebase'; + +const config: FirebaseInstrumentationConfig = { + firestoreSpanCreationHook: (span) => { + addOriginToSpan(span as Span, 'auto.firebase.otel.firestore'); + let operation = 'db.query'; + + const readableSpan = span as unknown as ReadableSpan; + + if (readableSpan.attributes && typeof readableSpan.attributes[ATTR_DB_OPERATION_NAME] === 'string') { + operation = readableSpan.attributes[ATTR_DB_OPERATION_NAME]; + } + + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, operation); + }, +}; + +export const instrumentFirebase = generateInstrumentOnce(INTEGRATION_NAME, () => new FirebaseInstrumentation(config)); + +const _firebaseIntegration = (() => { + return { + name: INTEGRATION_NAME, + setupOnce() { + instrumentFirebase(); + }, + }; +}) satisfies IntegrationFn; + +export const firebaseIntegration = defineIntegration(_firebaseIntegration); diff --git a/packages/node/src/integrations/tracing/firebase/index.ts b/packages/node/src/integrations/tracing/firebase/index.ts new file mode 100644 index 000000000000..5588511bf303 --- /dev/null +++ b/packages/node/src/integrations/tracing/firebase/index.ts @@ -0,0 +1 @@ +export * from './firebase'; diff --git a/packages/node/src/integrations/tracing/firebase/otel/firebaseInstrumentation.ts b/packages/node/src/integrations/tracing/firebase/otel/firebaseInstrumentation.ts new file mode 100644 index 000000000000..66e4cc202dd8 --- /dev/null +++ b/packages/node/src/integrations/tracing/firebase/otel/firebaseInstrumentation.ts @@ -0,0 +1,38 @@ +import { InstrumentationBase, type InstrumentationNodeModuleDefinition } from '@opentelemetry/instrumentation'; + +import { patchFirestore } from './patches/firestore'; +import type { FirebaseInstrumentationConfig } from './types'; +import { VERSION } from './version'; + +const DefaultFirebaseInstrumentationConfig: FirebaseInstrumentationConfig = {}; +const firestoreSupportedVersions = ['>=3.0.0 <5']; // firebase 9+ + +/** + * + */ +export class FirebaseInstrumentation extends InstrumentationBase { + public constructor(config: FirebaseInstrumentationConfig = DefaultFirebaseInstrumentationConfig) { + super('@sentry/instrumentation-firebase', VERSION, config); + } + + /** + * sets config + * @param config + */ + public override setConfig(config: FirebaseInstrumentationConfig = {}): void { + super.setConfig({ ...DefaultFirebaseInstrumentationConfig, ...config }); + } + + /** + * + * @protected + */ + // eslint-disable-next-line @typescript-eslint/naming-convention + protected init(): InstrumentationNodeModuleDefinition | InstrumentationNodeModuleDefinition[] | void { + const modules: InstrumentationNodeModuleDefinition[] = []; + + modules.push(patchFirestore(this.tracer, firestoreSupportedVersions, this._wrap, this._unwrap, this.getConfig())); + + return modules; + } +} diff --git a/packages/node/src/integrations/tracing/firebase/otel/index.ts b/packages/node/src/integrations/tracing/firebase/otel/index.ts new file mode 100644 index 000000000000..3b914e641ec0 --- /dev/null +++ b/packages/node/src/integrations/tracing/firebase/otel/index.ts @@ -0,0 +1,2 @@ +export * from './firebaseInstrumentation'; +export * from './types'; diff --git a/packages/node/src/integrations/tracing/firebase/otel/otelMissingSemanticConventions.ts b/packages/node/src/integrations/tracing/firebase/otel/otelMissingSemanticConventions.ts new file mode 100644 index 000000000000..72f17b0cdde7 --- /dev/null +++ b/packages/node/src/integrations/tracing/firebase/otel/otelMissingSemanticConventions.ts @@ -0,0 +1,4 @@ +export const ATTR_DB_COLLECTION_NAME = 'db.collection.name'; +export const ATTR_DB_NAMESPACE = 'db.namespace'; +export const ATTR_DB_SYSTEM = 'db.system'; +export const ATTR_DB_OPERATION_NAME = 'db.operation.name'; diff --git a/packages/node/src/integrations/tracing/firebase/otel/patches/firestore.ts b/packages/node/src/integrations/tracing/firebase/otel/patches/firestore.ts new file mode 100644 index 000000000000..c5760519a871 --- /dev/null +++ b/packages/node/src/integrations/tracing/firebase/otel/patches/firestore.ts @@ -0,0 +1,299 @@ +import type { FirebaseApp, FirebaseOptions } from 'firebase/app'; +import type { + CollectionReference, + DocumentData, + DocumentReference, + FirestoreSettings, + PartialWithFieldValue, + QuerySnapshot, + SetOptions, + WithFieldValue, + addDoc, + deleteDoc, + getDocs, + setDoc, +} from 'firebase/firestore'; +import type { Span, Tracer } from '@opentelemetry/api'; +import { SpanKind, context, diag, trace } from '@opentelemetry/api'; +import { + ATTR_SERVER_ADDRESS, + ATTR_SERVER_PORT +} from '@opentelemetry/semantic-conventions'; +import type { SpanAttributes } from '@sentry/types'; +import type { unwrap as shimmerUnwrap, wrap as shimmerWrap } from 'shimmer'; +import { + ATTR_DB_COLLECTION_NAME, + ATTR_DB_NAMESPACE, + ATTR_DB_OPERATION_NAME, + ATTR_DB_SYSTEM, +} from '../otelMissingSemanticConventions'; +import type { + AddDocType, + DeleteDocType, + FirebaseInstrumentationConfig, + FirestoreSpanCreationHook, + GetDocsType, + SetDocType, +} from '../types'; + +import { + InstrumentationNodeModuleDefinition, + InstrumentationNodeModuleFile, + isWrapped, + safeExecuteInTheMiddle, +} from '@opentelemetry/instrumentation'; +import type { FirebaseInstrumentation } from '../firebaseInstrumentation'; + +/** + * + * @param tracer - Opentelemetry Tracer + * @param firestoreSupportedVersions - supported version of firebase/firestore + * @param wrap - reference to native instrumentation wrap function + * @param unwrap - reference to native instrumentation wrap function + */ +export function patchFirestore( + tracer: Tracer, + firestoreSupportedVersions: string[], + wrap: typeof shimmerWrap, + unwrap: typeof shimmerUnwrap, + config: FirebaseInstrumentationConfig, +): InstrumentationNodeModuleDefinition { + // eslint-disable-next-line @typescript-eslint/no-empty-function + const defaultFirestoreSpanCreationHook: FirestoreSpanCreationHook = () => {}; + + let firestoreSpanCreationHook: FirestoreSpanCreationHook = defaultFirestoreSpanCreationHook; + const configFirestoreSpanCreationHook = config.firestoreSpanCreationHook; + + if (typeof configFirestoreSpanCreationHook === 'function') { + firestoreSpanCreationHook = (span: Span) => { + safeExecuteInTheMiddle( + () => configFirestoreSpanCreationHook(span), + error => { + if (!error) { + return; + } + diag.error(error?.message); + }, + true, + ); + }; + } + + const moduleFirestoreCJS = new InstrumentationNodeModuleDefinition( + '@firebase/firestore', + firestoreSupportedVersions, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (moduleExports: any) => wrapMethods(moduleExports, wrap, unwrap, tracer, firestoreSpanCreationHook), + ); + const files: string[] = [ + '@firebase/firestore/dist/lite/index.node.cjs.js', + '@firebase/firestore/dist/lite/index.node.mjs.js', + '@firebase/firestore/dist/lite/index.rn.esm2017.js', + '@firebase/firestore/dist/lite/index.cjs.js', + ]; + + for (const file of files) { + moduleFirestoreCJS.files.push( + new InstrumentationNodeModuleFile( + file, + firestoreSupportedVersions, + moduleExports => wrapMethods(moduleExports, wrap, unwrap, tracer, firestoreSpanCreationHook), + moduleExports => unwrapMethods(moduleExports, unwrap), + ), + ); + } + + return moduleFirestoreCJS; +} + +function wrapMethods( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + moduleExports: any, + wrap: typeof shimmerWrap, + unwrap: typeof shimmerUnwrap, + tracer: Tracer, + firestoreSpanCreationHook: FirestoreSpanCreationHook, +// eslint-disable-next-line @typescript-eslint/no-explicit-any +): any { + unwrapMethods(moduleExports, unwrap); + + wrap(moduleExports, 'addDoc', patchAddDoc(tracer, firestoreSpanCreationHook)); + wrap(moduleExports, 'getDocs', patchGetDocs(tracer, firestoreSpanCreationHook)); + wrap(moduleExports, 'setDoc', patchSetDoc(tracer, firestoreSpanCreationHook)); + wrap(moduleExports, 'deleteDoc', patchDeleteDoc(tracer, firestoreSpanCreationHook)); + + return moduleExports; +} + +function unwrapMethods( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + moduleExports: any, + unwrap: typeof shimmerUnwrap, +// eslint-disable-next-line @typescript-eslint/no-explicit-any +): any { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (isWrapped(moduleExports.addDoc)) { + unwrap(moduleExports, 'addDoc'); + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (isWrapped(moduleExports.getDocs)) { + unwrap(moduleExports, 'getDocs'); + } + + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (isWrapped(moduleExports.setDoc)) { + unwrap(moduleExports, 'setDoc'); + } + + return moduleExports; +} + +function patchAddDoc( + tracer: Tracer, + firestoreSpanCreationHook: FirestoreSpanCreationHook, +): ( + original: typeof addDoc, +) => ( + this: FirebaseInstrumentation, + reference: CollectionReference, + data: WithFieldValue, +) => Promise> { + return function addDoc(original: AddDocType) { + return function patchAddDoc( + reference: CollectionReference, + data: WithFieldValue, + ): Promise> { + const span = startSpan(tracer, 'addDoc', reference); + firestoreSpanCreationHook(span); + return executeContextWithSpan>>(span, () => { + return original(reference, data); + }); + }; + }; +} + +function patchDeleteDoc( + tracer: Tracer, + firestoreSpanCreationHook: FirestoreSpanCreationHook, +): ( + original: typeof deleteDoc, +) => (this: FirebaseInstrumentation, reference: DocumentReference) => Promise { + return function deleteDoc(original: DeleteDocType) { + return function patchDeleteDoc(reference: DocumentReference): Promise { + const span = startSpan(tracer, 'deleteDoc', reference.parent || reference); + firestoreSpanCreationHook(span); + return executeContextWithSpan>(span, () => { + return original(reference); + }); + }; + }; +} + +function patchGetDocs( + tracer: Tracer, + firestoreSpanCreationHook: FirestoreSpanCreationHook, +): ( + original: typeof getDocs, +) => ( + this: FirebaseInstrumentation, + reference: CollectionReference, +) => Promise> { + return function getDocs(original: GetDocsType) { + return function patchGetDocs( + reference: CollectionReference, + ): Promise> { + const span = startSpan(tracer, 'getDocs', reference); + firestoreSpanCreationHook(span); + return executeContextWithSpan>>(span, () => { + return original(reference); + }); + }; + }; +} + +function patchSetDoc( + tracer: Tracer, + firestoreSpanCreationHook: FirestoreSpanCreationHook, +): ( + original: typeof setDoc, +) => ( + this: FirebaseInstrumentation, + reference: DocumentReference, + data: WithFieldValue & PartialWithFieldValue, + options?: SetOptions, +) => Promise { + return function setDoc(original: SetDocType) { + return function patchSetDoc( + reference: DocumentReference, + data: WithFieldValue & PartialWithFieldValue, + options?: SetOptions, + ): Promise { + const span = startSpan(tracer, 'setDocs', reference.parent || reference); + firestoreSpanCreationHook(span); + + return executeContextWithSpan>(span, () => { + return typeof options !== 'undefined' ? original(reference, data, options) : original(reference, data); + }); + }; + }; +} + +function executeContextWithSpan(span: Span, callback: () => T): T { + return context.with(trace.setSpan(context.active(), span), () => { + return safeExecuteInTheMiddle( + (): T => { + return callback(); + }, + err => { + if (err) { + span.recordException(err); + } + span.end(); + }, + true, + ); + }); +} + +function startSpan( + tracer: Tracer, + spanName: string, + reference: CollectionReference | DocumentReference, +): Span { + const span = tracer.startSpan(`${spanName} ${reference.path}`, { kind: SpanKind.CLIENT }); + addAttributes(span, reference); + span.setAttribute(ATTR_DB_OPERATION_NAME, spanName); + return span; +} + +function addAttributes( + span: Span, + reference: CollectionReference | DocumentReference, +): void { + const firestoreApp: FirebaseApp = reference.firestore.app; + const firestoreOptions: FirebaseOptions = firestoreApp.options; + const json: { settings?: FirestoreSettings } = reference.firestore.toJSON() || {}; + const settings: FirestoreSettings = json.settings || {}; + + const attributes: SpanAttributes = { + [ATTR_DB_COLLECTION_NAME]: reference.path, + [ATTR_DB_NAMESPACE]: firestoreApp.name, + [ATTR_DB_SYSTEM]: 'firebase.firestore', + 'firebase.firestore.type': reference.type, + 'firebase.firestore.options.projectId': firestoreOptions.projectId, + 'firebase.firestore.options.appId': firestoreOptions.appId, + 'firebase.firestore.options.messagingSenderId': firestoreOptions.messagingSenderId, + 'firebase.firestore.options.storageBucket': firestoreOptions.storageBucket, + }; + + if (typeof settings.host === 'string') { + const arr = settings.host.split(':'); + if (arr.length === 2) { + attributes[ATTR_SERVER_ADDRESS] = arr[0]; + attributes[ATTR_SERVER_PORT] = arr[1]; + } + } + + span.setAttributes(attributes); +} diff --git a/packages/node/src/integrations/tracing/firebase/otel/types.ts b/packages/node/src/integrations/tracing/firebase/otel/types.ts new file mode 100644 index 000000000000..f2e8b6910345 --- /dev/null +++ b/packages/node/src/integrations/tracing/firebase/otel/types.ts @@ -0,0 +1,45 @@ +import type { + CollectionReference, + DocumentData, + DocumentReference, + PartialWithFieldValue, + QuerySnapshot, + SetOptions, + WithFieldValue, +} from '@firebase/firestore'; +import type { Span } from '@opentelemetry/api'; +import type { InstrumentationConfig } from '@opentelemetry/instrumentation'; + +/** + * Firebase Auto Instrumentation + */ +export interface FirebaseInstrumentationConfig extends InstrumentationConfig { + firestoreSpanCreationHook?: FirestoreSpanCreationHook; +} + +export type GetDocsType = ( + query: CollectionReference, +) => Promise>; + +export type SetDocType = (( + reference: DocumentReference, + data: WithFieldValue, +) => Promise) & + (( + reference: DocumentReference, + data: PartialWithFieldValue, + options: SetOptions, + ) => Promise); + +export type AddDocType = ( + reference: CollectionReference, + data: WithFieldValue, +) => Promise>; + +export type DeleteDocType = ( + reference: DocumentReference, +) => Promise; + +export interface FirestoreSpanCreationHook { + (span: Span): void; +} diff --git a/packages/node/src/integrations/tracing/firebase/otel/version.ts b/packages/node/src/integrations/tracing/firebase/otel/version.ts new file mode 100644 index 000000000000..37025ab12f97 --- /dev/null +++ b/packages/node/src/integrations/tracing/firebase/otel/version.ts @@ -0,0 +1 @@ +export const VERSION = '0.1.0'; diff --git a/packages/node/src/integrations/tracing/index.ts b/packages/node/src/integrations/tracing/index.ts index 328767c403be..b75237c73115 100644 --- a/packages/node/src/integrations/tracing/index.ts +++ b/packages/node/src/integrations/tracing/index.ts @@ -5,6 +5,7 @@ import { amqplibIntegration, instrumentAmqplib } from './amqplib'; import { connectIntegration, instrumentConnect } from './connect'; import { expressIntegration, instrumentExpress } from './express'; import { fastifyIntegration, instrumentFastify } from './fastify'; +import { firebaseIntegration, instrumentFirebase } from './firebase'; import { genericPoolIntegration, instrumentGenericPool } from './genericPool'; import { graphqlIntegration, instrumentGraphql } from './graphql'; import { hapiIntegration, instrumentHapi } from './hapi'; @@ -45,6 +46,7 @@ export function getAutoPerformanceIntegrations(): Integration[] { kafkaIntegration(), amqplibIntegration(), lruMemoizerIntegration(), + firebaseIntegration(), ]; } @@ -73,5 +75,6 @@ export function getOpenTelemetryInstrumentationToPreload(): (((options?: any) => instrumentRedis, instrumentGenericPool, instrumentAmqplib, + instrumentFirebase, ]; } diff --git a/packages/remix/src/index.server.ts b/packages/remix/src/index.server.ts index 098bd1293080..b61dc366a3b0 100644 --- a/packages/remix/src/index.server.ts +++ b/packages/remix/src/index.server.ts @@ -45,6 +45,7 @@ export { extractRequestData, extraErrorDataIntegration, fastifyIntegration, + firebaseIntegration, flush, functionToStringIntegration, generateInstrumentOnce, diff --git a/packages/solidstart/src/server/index.ts b/packages/solidstart/src/server/index.ts index d537ddd51e88..1b0d15d557c2 100644 --- a/packages/solidstart/src/server/index.ts +++ b/packages/solidstart/src/server/index.ts @@ -36,6 +36,7 @@ export { extractRequestData, extraErrorDataIntegration, fastifyIntegration, + firebaseIntegration, flush, functionToStringIntegration, generateInstrumentOnce, diff --git a/packages/sveltekit/src/server/index.ts b/packages/sveltekit/src/server/index.ts index 72b459e2fde3..1d2822c689b2 100644 --- a/packages/sveltekit/src/server/index.ts +++ b/packages/sveltekit/src/server/index.ts @@ -36,6 +36,7 @@ export { extractRequestData, extraErrorDataIntegration, fastifyIntegration, + firebaseIntegration, flush, functionToStringIntegration, genericPoolIntegration, diff --git a/yarn.lock b/yarn.lock index 9d3139160e51..859c43481b3e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5367,6 +5367,396 @@ resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.0.0.tgz#f22824caff3ae506b18207bad4126dbc6ccdb6b8" integrity sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ== +"@firebase/analytics-compat@0.2.15": + version "0.2.15" + resolved "https://registry.yarnpkg.com/@firebase/analytics-compat/-/analytics-compat-0.2.15.tgz#91ce1983b980f66e53c28a7cc4b596e551be5f97" + integrity sha512-C5to422Sr8FkL0MPwXcIecbMnF4o2Ll7MtoWvIm4Q/LPJvvM+tWa1DiU+LzsCdsd1/CYE9EIW9Ma3ko9XnAAYw== + dependencies: + "@firebase/analytics" "0.10.9" + "@firebase/analytics-types" "0.8.2" + "@firebase/component" "0.6.10" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/analytics-types@0.8.2": + version "0.8.2" + resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.8.2.tgz#947f85346e404332aac6c996d71fd4a89cd7f87a" + integrity sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw== + +"@firebase/analytics@0.10.9": + version "0.10.9" + resolved "https://registry.yarnpkg.com/@firebase/analytics/-/analytics-0.10.9.tgz#b1ba347405346b2daaee61dc6daa0dfaf0c8a209" + integrity sha512-FrvW6u6xDBKXUGYUy1WIUh0J9tvbppMsk90mig0JhHST8iLveKu/dIBVeVE/ZYZhmXy4fkI7SPSWvD1V0O4tXw== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/installations" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/app-check-compat@0.3.16": + version "0.3.16" + resolved "https://registry.yarnpkg.com/@firebase/app-check-compat/-/app-check-compat-0.3.16.tgz#cd1c5e9d0144e04f88afbfb3b82ce69730fac047" + integrity sha512-AxIGzLRXrTFNL+H6V+4BO0w/gERloROfRbWI/FoJUnQd0qPZIzyfdHZBbThFzFGLfDt/mVs2kdjYFx/l9I8NhQ== + dependencies: + "@firebase/app-check" "0.8.9" + "@firebase/app-check-types" "0.5.2" + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/app-check-interop-types@0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.2.tgz#455b6562c7a3de3ef75ea51f72dfec5829ad6997" + integrity sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ== + +"@firebase/app-check-types@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@firebase/app-check-types/-/app-check-types-0.5.2.tgz#1221bd09b471e11bb149252f16640a0a51043cbc" + integrity sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA== + +"@firebase/app-check@0.8.9": + version "0.8.9" + resolved "https://registry.yarnpkg.com/@firebase/app-check/-/app-check-0.8.9.tgz#da12501dd42686cb283169cfcb1413ddede7e99e" + integrity sha512-YzVn1mMLzD2JboMPVVO0Pe20YOgWzrF+aXoAmmd0v3xec051n83YpxSUZbacL69uYvk0dHrEsbea44QtQ5WPDA== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/app-compat@0.2.45": + version "0.2.45" + resolved "https://registry.yarnpkg.com/@firebase/app-compat/-/app-compat-0.2.45.tgz#2541fa77eba61de9d3d437df76c28e21d7e66839" + integrity sha512-5rYbXq1ndtMTg+07oH4WrkYuP+NZq61uzVwW1hlmybp/gr4cXq2SfaP9fc6/9IzTKmu3dh3H0fjj++HG7Z7o/w== + dependencies: + "@firebase/app" "0.10.15" + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/app-types@0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.9.2.tgz#8cbcceba784753a7c0066a4809bc22f93adee080" + integrity sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ== + +"@firebase/app@0.10.15": + version "0.10.15" + resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.10.15.tgz#5328c05ace83902aa19ea673322147b0179970cb" + integrity sha512-he6qlG3pmwL+LHdG/BrSMBQeJzzutciq4fpXN3lGa1uSwYSijJ24VtakS/bP2X9SiDf8jGywJ4u+OgXAenJsNg== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/auth-compat@0.5.15": + version "0.5.15" + resolved "https://registry.yarnpkg.com/@firebase/auth-compat/-/auth-compat-0.5.15.tgz#7f3f9a90aae3721031fc98103a15600d24d8d2c0" + integrity sha512-jz6k1ridPiecKI8CBRiqCM6IMOhwYp2MD+YvoxnMiK8nQLSTm57GvHETlPNX3WlbyQnCjMCOvrAhe27whyxAEg== + dependencies: + "@firebase/auth" "1.8.0" + "@firebase/auth-types" "0.12.2" + "@firebase/component" "0.6.10" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/auth-interop-types@0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz#927f1f2139a680b55fef0bddbff2c982b08587e8" + integrity sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ== + +"@firebase/auth-types@0.12.2": + version "0.12.2" + resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.12.2.tgz#f12d890585866e53b6ab18b16fa4d425c52eee6e" + integrity sha512-qsEBaRMoGvHO10unlDJhaKSuPn4pyoTtlQuP1ghZfzB6rNQPuhp/N/DcFZxm9i4v0SogjCbf9reWupwIvfmH6w== + +"@firebase/auth@1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-1.8.0.tgz#51fc42016b747bf82b43b8ae6731761386377915" + integrity sha512-/O7UDWE5S5ux456fzNHSLx/0YN/Kykw/WyAzgDQ6wvkddZhSEmPX19EzxgsFldzhuFjsl5uOZTz8kzlosCiJjg== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/component@0.6.10": + version "0.6.10" + resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.6.10.tgz#5d2abe7c5c18d60ae806be8bcc698ca1bee7acbf" + integrity sha512-OsNbEKyz9iLZSmMUhsl6+kCADzte00iisJIRUspnUqvDCX+RSGZOBIqekukv/jN177ovjApBQNFaxSYIDc/SyQ== + dependencies: + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/data-connect@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@firebase/data-connect/-/data-connect-0.1.1.tgz#99738c28319c4debc47a921933a1bc7b6bb8f945" + integrity sha512-RBJ7XE/a3oXFv31Jlw8cbMRdsxQoI8F3L7xm4n93ab+bIr1NQUiYGgW9L7TTw7obdNev91ZnW0xfqJtXcPA5yA== + dependencies: + "@firebase/auth-interop-types" "0.2.3" + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/database-compat@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@firebase/database-compat/-/database-compat-2.0.0.tgz#fc702576c2bcf4ee0a8b80351b86885d251a03bd" + integrity sha512-2xlODKWwf/vNAxCmou0GFhymx2pqZKkhXMN9B5aiTjZ6+81sOxGim53ELY2lj+qKG2IvgiCYFc4X+ZJA2Ad5vg== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/database" "1.0.9" + "@firebase/database-types" "1.0.6" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/database-types@1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-1.0.6.tgz#97e3026e726ebfd489dbce095371b47c69387bc9" + integrity sha512-sMI7IynSZBsyGbUugc8PKE1jwKbnvaieAz/RxuM57PZQNCi6Rteiviwcw/jqZOX6igqYJwXWZ3UzKOZo2nUDRA== + dependencies: + "@firebase/app-types" "0.9.2" + "@firebase/util" "1.10.1" + +"@firebase/database@1.0.9": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@firebase/database/-/database-1.0.9.tgz#1e4862542b3a93e8039cb3a5a25c79fe5ff1f212" + integrity sha512-EkiPSKSu2TJJGtOjyISASf3UFpFJDil1lMbfqnxilfbmIsilvC8DzgjuLoYD+eOitcug4wtU9Fh1tt2vgBhskA== + dependencies: + "@firebase/app-check-interop-types" "0.3.2" + "@firebase/auth-interop-types" "0.2.3" + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + faye-websocket "0.11.4" + tslib "^2.1.0" + +"@firebase/firestore-compat@0.3.39": + version "0.3.39" + resolved "https://registry.yarnpkg.com/@firebase/firestore-compat/-/firestore-compat-0.3.39.tgz#b34d3cef25d5956a4332f464ab41681d6087d5b4" + integrity sha512-CsK8g34jNeHx95LISDRTcArJLonW+zJCqHI1Ez9WNiLAK2X8FeQ4UiD+RwOwxAIR+t2a6xED/5Fe6ZIqx7MuoQ== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/firestore" "4.7.4" + "@firebase/firestore-types" "3.0.2" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/firestore-types@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-3.0.2.tgz#75c301acc5fa33943eaaa9570b963c55398cad2a" + integrity sha512-wp1A+t5rI2Qc/2q7r2ZpjUXkRVPtGMd6zCLsiWurjsQpqPgFin3AhNibKcIzoF2rnToNa/XYtyWXuifjOOwDgg== + +"@firebase/firestore@4.7.4": + version "4.7.4" + resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-4.7.4.tgz#f24e5ceffd607fb93d652512261a8c3526b938a6" + integrity sha512-K2nq4w+NF8J1waGawY5OHLawP/Aw5CYxyDstVv1NZemGPcM3U+LZ9EPaXr1PatYIrPA7fS4DxZoWcbB0aGJ8Zg== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + "@firebase/webchannel-wrapper" "1.0.2" + "@grpc/grpc-js" "~1.9.0" + "@grpc/proto-loader" "^0.7.8" + tslib "^2.1.0" + +"@firebase/functions-compat@0.3.15": + version "0.3.15" + resolved "https://registry.yarnpkg.com/@firebase/functions-compat/-/functions-compat-0.3.15.tgz#d32277390296d65f4266d208e7243573ed3cc85d" + integrity sha512-eiHpc6Sd9Y/SNhBsGi944SapiFbfTPKsiSUQ74QxNSs0yoxvABeIRolVMFk4TokP57NGmstGYpYte02XGNPcYw== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/functions" "0.11.9" + "@firebase/functions-types" "0.6.2" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/functions-types@0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@firebase/functions-types/-/functions-types-0.6.2.tgz#03b4ec9259d2f57548a3909d6a35ae35ad243552" + integrity sha512-0KiJ9lZ28nS2iJJvimpY4nNccV21rkQyor5Iheu/nq8aKXJqtJdeSlZDspjPSBBiHRzo7/GMUttegnsEITqR+w== + +"@firebase/functions@0.11.9": + version "0.11.9" + resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.11.9.tgz#6ddc28353a366ab4e6d4133753c5578b7b27ab62" + integrity sha512-dhO5IUfQRCsrc20YD20nSOX+QCT+cH6N86HlZOLz2XgyEFgzOdBQnUot4EabBJQRkMBI7fZWUrbYfRcnov53ug== + dependencies: + "@firebase/app-check-interop-types" "0.3.2" + "@firebase/auth-interop-types" "0.2.3" + "@firebase/component" "0.6.10" + "@firebase/messaging-interop-types" "0.2.2" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/installations-compat@0.2.10": + version "0.2.10" + resolved "https://registry.yarnpkg.com/@firebase/installations-compat/-/installations-compat-0.2.10.tgz#5bcb60f36db2028843f350199566d1065dc9a62a" + integrity sha512-YTonkcVz3AK7RF8xFhvs5CwDuJ0xbzzCJIwXoV14gnzdYbMgy6vWlUUbzkvbtEDXzPRHB0n7aGZl56oy9dLOFw== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/installations" "0.6.10" + "@firebase/installations-types" "0.5.2" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/installations-types@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@firebase/installations-types/-/installations-types-0.5.2.tgz#4d4949e0e83ced7f36cbee009355cd305a36e158" + integrity sha512-que84TqGRZJpJKHBlF2pkvc1YcXrtEDOVGiDjovP/a3s6W4nlbohGXEsBJo0JCeeg/UG9A+DEZVDUV9GpklUzA== + +"@firebase/installations@0.6.10": + version "0.6.10" + resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.6.10.tgz#cff44e441ff2fe8cb8f0111acf612ba64d32870b" + integrity sha512-TuGSOMqkFrllxa0X/8VZIqBCRH4POndU/iWKWkRmkh12+/xKSpdp+y/kWaVbsySrelltan6LeYlcYPmLibWbwg== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/util" "1.10.1" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/logger@0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.4.3.tgz#e7e55c022b62083307a428b6d03f86db012eca88" + integrity sha512-Th42bWJg18EF5bJwhRosn2M/eYxmbWCwXZr4hHX7ltO0SE3QLrpgiMKeRBR/NW7vJke7i0n3i8esbCW2s93qBw== + dependencies: + tslib "^2.1.0" + +"@firebase/messaging-compat@0.2.13": + version "0.2.13" + resolved "https://registry.yarnpkg.com/@firebase/messaging-compat/-/messaging-compat-0.2.13.tgz#6189e43a765edd9d9d88dc2bbf9e794ce4e33cb0" + integrity sha512-9ootPClS6m2c2KIzo7AqSHaWzAw28zWcjQPjVv7WeQDu6wjufpbOg+7tuVzb+gqpF9Issa3lDoYOwlO0ZudO3g== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/messaging" "0.12.13" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/messaging-interop-types@0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.2.tgz#81042f7e9739733fa4571d17f6eb6869522754d0" + integrity sha512-l68HXbuD2PPzDUOFb3aG+nZj5KA3INcPwlocwLZOzPp9rFM9yeuI9YLl6DQfguTX5eAGxO0doTR+rDLDvQb5tA== + +"@firebase/messaging@0.12.13": + version "0.12.13" + resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.12.13.tgz#7008a6d31b8dd1cdac067b9885f3fec927f565df" + integrity sha512-YLa8PWl+BgiOVR5WOyzl21fVJFJeBRfniNuN25d9DBrQzppSAahuN6yS+vt1OIjvZNPN4pZ/lcRLYupbGu4W0w== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/installations" "0.6.10" + "@firebase/messaging-interop-types" "0.2.2" + "@firebase/util" "1.10.1" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/performance-compat@0.2.10": + version "0.2.10" + resolved "https://registry.yarnpkg.com/@firebase/performance-compat/-/performance-compat-0.2.10.tgz#e42d3a7afc7650903e55c357fecf3a3227883a43" + integrity sha512-0h1qYkF6I79DSSpHfTQFvb91fo8shmmwiPzWFYAPdPK02bSWpKwVssNYlZX2iUnumxerDMbl7dWN+Im/W3bnXA== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/performance" "0.6.10" + "@firebase/performance-types" "0.2.2" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/performance-types@0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@firebase/performance-types/-/performance-types-0.2.2.tgz#7b78cd2ab2310bac89a63348d93e67e01eb06dd7" + integrity sha512-gVq0/lAClVH5STrIdKnHnCo2UcPLjJlDUoEB/tB4KM+hAeHUxWKnpT0nemUPvxZ5nbdY/pybeyMe8Cs29gEcHA== + +"@firebase/performance@0.6.10": + version "0.6.10" + resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.6.10.tgz#ae734d7f56105ef181f2bcbfb44eb0696c16f986" + integrity sha512-x/mNYKGxq7A+QV0EiEZeD2S+E+kw+UcZ8FXuE7qDJyGGt/0Wd+bIIL7RakG/VrFt7/UYc//nKygDc7/Ig7sOmQ== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/installations" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/remote-config-compat@0.2.10": + version "0.2.10" + resolved "https://registry.yarnpkg.com/@firebase/remote-config-compat/-/remote-config-compat-0.2.10.tgz#416238bc86b604682d866c54f659da0588ddb182" + integrity sha512-fIi5OB2zk0zpChMV/tTd0oEZcZI8TlwQDlLlcrDpMOV5l5dqd0JNlWKh6Fwmh4izmytk+rZIAIpnak/NjGVesQ== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/remote-config" "0.4.10" + "@firebase/remote-config-types" "0.3.2" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/remote-config-types@0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@firebase/remote-config-types/-/remote-config-types-0.3.2.tgz#a5d1009c6fd08036c5cd4f28764e3cd694f966d5" + integrity sha512-0BC4+Ud7y2aPTyhXJTMTFfrGGLqdYXrUB9sJVAB8NiqJswDTc4/2qrE/yfUbnQJhbSi6ZaTTBKyG3n1nplssaA== + +"@firebase/remote-config@0.4.10": + version "0.4.10" + resolved "https://registry.yarnpkg.com/@firebase/remote-config/-/remote-config-0.4.10.tgz#ad2ebab95d5cde6f096bdec288c8149376dba55b" + integrity sha512-jTRjy3TdqzVna19m5a1HEHE5BG4Z3BQTxBgvQRTmMKlHacx4QS0CToAas7R9M9UkxpgFcVuAE7FpWIOWQGCEWw== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/installations" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/storage-compat@0.3.13": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@firebase/storage-compat/-/storage-compat-0.3.13.tgz#da35d68fd2eeecbe84ab730229b855896299612f" + integrity sha512-15kje7JALswRCBKsCSvKg5FbqUYykaIMqMbZRD7I6uVRWwdyTvez5MBQfMhBia2JcEmPiDpXhJTXH4PAWFiA8g== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/storage" "0.13.3" + "@firebase/storage-types" "0.8.2" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/storage-types@0.8.2": + version "0.8.2" + resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.8.2.tgz#edb321b8a3872a9f74e1f27de046f160021c8e1f" + integrity sha512-0vWu99rdey0g53lA7IShoA2Lol1jfnPovzLDUBuon65K7uKG9G+L5uO05brD9pMw+l4HRFw23ah3GwTGpEav6g== + +"@firebase/storage@0.13.3": + version "0.13.3" + resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.13.3.tgz#b48e494bcbb9b662fd4cf78d18f48ae3059249a1" + integrity sha512-B5HiJ7isYKaT4dOEV43f2ySdhQxzq+SQEm7lqXebJ8AYCsebdHrgGzrPR0LR962xGjPzJHFKx63gA8Be/P2MCw== + dependencies: + "@firebase/component" "0.6.10" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/util@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@firebase/util/-/util-1.10.1.tgz#1af07dff98320b45c6eb46d7992e88800b97cba2" + integrity sha512-AIhFnCCjM8FmCqSNlNPTuOk3+gpHC1RkeNUBLtPbcqGYpN5MxI5q7Yby+rxycweOZOCboDzfIj8WyaY4tpQG/g== + dependencies: + tslib "^2.1.0" + +"@firebase/vertexai@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@firebase/vertexai/-/vertexai-1.0.0.tgz#da4310d0cae590b372939aacc2b1e16b86e30732" + integrity sha512-48N3Lp/9GgiCCRfrSdHS+Y1IiMdYXvnHFO/f+HL1PgUtBq7WQ/fWmYOX3mzAN36zvytq13nb68ImF+GALopp+Q== + dependencies: + "@firebase/app-check-interop-types" "0.3.2" + "@firebase/component" "0.6.10" + "@firebase/logger" "0.4.3" + "@firebase/util" "1.10.1" + tslib "^2.1.0" + +"@firebase/webchannel-wrapper@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.2.tgz#7f583968e0f9d18420ec9ce78520aaf90d7c8ba5" + integrity sha512-3F4iA2E+NtdMbOU0XC1cHE8q6MqpGIKRj62oGOF38S6AAx5VHR9cXmoDUSj7ejvTAT7m6jxuEeQkHeq0F+mU2w== + "@gar/promisify@^1.1.3": version "1.1.3" resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" @@ -5686,6 +6076,14 @@ google-auth-library "^6.1.1" semver "^6.2.0" +"@grpc/grpc-js@~1.9.0": + version "1.9.15" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.15.tgz#433d7ac19b1754af690ea650ab72190bd700739b" + integrity sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ== + dependencies: + "@grpc/proto-loader" "^0.7.8" + "@types/node" ">=12.12.47" + "@grpc/proto-loader@^0.5.1": version "0.5.6" resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.5.6.tgz#1dea4b8a6412b05e2d58514d507137b63a52a98d" @@ -5694,6 +6092,16 @@ lodash.camelcase "^4.3.0" protobufjs "^6.8.6" +"@grpc/proto-loader@^0.7.8": + version "0.7.13" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.13.tgz#f6a44b2b7c9f7b609f5748c6eac2d420e37670cf" + integrity sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw== + dependencies: + lodash.camelcase "^4.3.0" + long "^5.0.0" + protobufjs "^7.2.5" + yargs "^17.7.2" + "@handlebars/parser@~2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@handlebars/parser/-/parser-2.0.0.tgz#5e8b7298f31ff8f7b260e6b7363c7e9ceed7d9c5" @@ -9687,7 +10095,17 @@ dependencies: "@types/unist" "*" -"@types/history-4@npm:@types/history@4.7.8", "@types/history-5@npm:@types/history@4.7.8", "@types/history@*": +"@types/history-4@npm:@types/history@4.7.8": + version "4.7.8" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" + integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== + +"@types/history-5@npm:@types/history@4.7.8": + version "4.7.8" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" + integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== + +"@types/history@*": version "4.7.8" resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== @@ -10010,7 +10428,15 @@ "@types/history" "^3" "@types/react" "*" -"@types/react-router-4@npm:@types/react-router@5.1.14", "@types/react-router-5@npm:@types/react-router@5.1.14": +"@types/react-router-4@npm:@types/react-router@5.1.14": + version "5.1.14" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.14.tgz#e0442f4eb4c446541ad7435d44a97f8fe6df40da" + integrity sha512-LAJpqYUaCTMT2anZheoidiIymt8MuX286zoVFPM3DVb23aQBH0mAkFvzpd4LKqiolV8bBtZWT5Qp7hClCNDENw== + dependencies: + "@types/history" "*" + "@types/react" "*" + +"@types/react-router-5@npm:@types/react-router@5.1.14": version "5.1.14" resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.14.tgz#e0442f4eb4c446541ad7435d44a97f8fe6df40da" integrity sha512-LAJpqYUaCTMT2anZheoidiIymt8MuX286zoVFPM3DVb23aQBH0mAkFvzpd4LKqiolV8bBtZWT5Qp7hClCNDENw== @@ -18361,7 +18787,7 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -faye-websocket@^0.11.3: +faye-websocket@0.11.4, faye-websocket@^0.11.3: version "0.11.4" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== @@ -18615,6 +19041,40 @@ findup-sync@^4.0.0: micromatch "^4.0.2" resolve-dir "^1.0.1" +firebase@11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/firebase/-/firebase-11.0.1.tgz#e1c879f3473892adb88a467cf98c3b8cb9eeaea0" + integrity sha512-qsFb8dMcQINEDhJteG7RP+GqwgSRvfyiexQqHd5JToDdm87i9I2rGC4XQsGawKGxzKwZ/ISdgwNWxXAFYdCC6A== + dependencies: + "@firebase/analytics" "0.10.9" + "@firebase/analytics-compat" "0.2.15" + "@firebase/app" "0.10.15" + "@firebase/app-check" "0.8.9" + "@firebase/app-check-compat" "0.3.16" + "@firebase/app-compat" "0.2.45" + "@firebase/app-types" "0.9.2" + "@firebase/auth" "1.8.0" + "@firebase/auth-compat" "0.5.15" + "@firebase/data-connect" "0.1.1" + "@firebase/database" "1.0.9" + "@firebase/database-compat" "2.0.0" + "@firebase/firestore" "4.7.4" + "@firebase/firestore-compat" "0.3.39" + "@firebase/functions" "0.11.9" + "@firebase/functions-compat" "0.3.15" + "@firebase/installations" "0.6.10" + "@firebase/installations-compat" "0.2.10" + "@firebase/messaging" "0.12.13" + "@firebase/messaging-compat" "0.2.13" + "@firebase/performance" "0.6.10" + "@firebase/performance-compat" "0.2.10" + "@firebase/remote-config" "0.4.10" + "@firebase/remote-config-compat" "0.2.10" + "@firebase/storage" "0.13.3" + "@firebase/storage-compat" "0.3.13" + "@firebase/util" "1.10.1" + "@firebase/vertexai" "1.0.0" + fireworm@^0.7.0: version "0.7.1" resolved "https://registry.yarnpkg.com/fireworm/-/fireworm-0.7.1.tgz#ccf20f7941f108883fcddb99383dbe6e1861c758" @@ -20534,6 +20994,11 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== +idb@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b" + integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ== + ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -23173,7 +23638,7 @@ long@^4.0.0: resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== -long@^5.2.1: +long@^5.0.0, long@^5.2.1: version "5.2.3" resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== @@ -28178,6 +28643,24 @@ protobufjs@^6.10.2, protobufjs@^6.8.6: "@types/node" ">=13.7.0" long "^4.0.0" +protobufjs@^7.2.5: + version "7.4.0" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.4.0.tgz#7efe324ce9b3b61c82aae5de810d287bc08a248a" + integrity sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/node" ">=13.7.0" + long "^5.0.0" + protocols@^2.0.0, protocols@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/protocols/-/protocols-2.0.1.tgz#8f155da3fc0f32644e83c5782c8e8212ccf70a86" @@ -28461,7 +28944,7 @@ react-is@^18.0.0: dependencies: "@remix-run/router" "1.0.2" -"react-router-6@npm:react-router@6.3.0", react-router@6.3.0: +"react-router-6@npm:react-router@6.3.0": version "6.3.0" resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557" integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ== @@ -28476,6 +28959,13 @@ react-router-dom@^6.2.2: history "^5.2.0" react-router "6.3.0" +react-router@6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557" + integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ== + dependencies: + history "^5.2.0" + react@^18.0.0: version "18.0.0" resolved "https://registry.yarnpkg.com/react/-/react-18.0.0.tgz#b468736d1f4a5891f38585ba8e8fb29f91c3cb96" @@ -30916,7 +31406,16 @@ string-template@~0.2.1: resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" integrity sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0= -"string-width-cjs@npm:string-width@^4.2.0", string-width@4.2.3, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@4.2.3, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -31028,7 +31527,14 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -34069,7 +34575,16 @@ wrangler@^3.67.1: optionalDependencies: fsevents "~2.3.2" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@7.0.0, wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@7.0.0, wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -34293,7 +34808,7 @@ yargs@17.5.1: y18n "^5.0.5" yargs-parser "^21.0.0" -yargs@^17.2.1: +yargs@^17.2.1, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==