From 839bfea922bddeb7d3b15a292eb32ee0fcf4df20 Mon Sep 17 00:00:00 2001 From: Kirsty Williams Date: Wed, 20 Dec 2023 00:14:39 +0000 Subject: [PATCH 01/25] refactor(int): integration tests rewrite --- integration_test/.env.example | 7 + integration_test/.gitignore | 71 + integration_test/README.md | 38 +- integration_test/functions/src/index.ts | 225 +- integration_test/functions/src/testing.ts | 134 - integration_test/functions/src/utils.ts | 7 + .../functions/src/v1/analytics-tests.ts | 25 + .../functions/src/v1/auth-tests.ts | 126 +- .../functions/src/v1/database-tests.ts | 141 +- .../functions/src/v1/firestore-tests.ts | 100 +- .../functions/src/v1/https-tests.ts | 35 +- integration_test/functions/src/v1/index.ts | 8 +- .../functions/src/v1/pubsub-tests.ts | 89 +- .../functions/src/v1/remoteConfig-tests.ts | 36 +- .../functions/src/v1/storage-tests.ts | 102 +- .../functions/src/v1/tasks-tests.ts | 23 + .../functions/src/v1/testLab-tests.ts | 37 +- .../functions/src/v2/alerts-tests.ts | 234 + .../functions/src/v2/database-tests.ts | 114 + .../functions/src/v2/eventarc-tests.ts | 25 + .../functions/src/v2/firestore-tests.ts | 84 + .../functions/src/v2/https-tests.ts | 39 +- .../functions/src/v2/identity-tests.ts | 34 + integration_test/functions/src/v2/index.ts | 14 +- .../functions/src/v2/pubsub-tests.ts | 28 + .../functions/src/v2/remoteConfig-tests.ts | 23 + .../functions/src/v2/scheduled-tests.ts | 19 - .../functions/src/v2/scheduler-tests.ts | 27 + .../functions/src/v2/storage-tests.ts | 99 + .../functions/src/v2/tasks-tests.ts | 23 + .../functions/src/v2/testLab-tests.ts | 28 + integration_test/global.d.ts | 3 + integration_test/jest.config.js | 10 + integration_test/package-lock.json | 9864 +++++++++++++++++ integration_test/package.json | 26 + integration_test/run.ts | 263 + integration_test/run_tests.sh | 105 - integration_test/setup.ts | 87 + integration_test/tests/firebaseSetup.ts | 28 + integration_test/tests/globalTeardown.ts | 69 + integration_test/tests/utils.ts | 1 + integration_test/tests/v1/analytics.test.ts | 51 + integration_test/tests/v1/auth.test.ts | 222 + integration_test/tests/v1/database.test.ts | 87 + integration_test/tests/v1/firestore.test.ts | 67 + integration_test/tests/v1/https.test.ts | 55 + integration_test/tests/v1/pubsub.test.ts | 115 + .../tests/v1/remoteConfig.test.ts | 65 + integration_test/tests/v1/storage.test.ts | 71 + .../v1/testLab.test.ts} | 66 +- integration_test/tests/v2/https.test.ts | 54 + integration_test/tests/v2/scheduler.test.ts | 56 + integration_test/tsconfig.json | 14 + integration_test/tsconfig.test.json | 8 + 54 files changed, 12609 insertions(+), 773 deletions(-) create mode 100644 integration_test/.env.example create mode 100644 integration_test/.gitignore delete mode 100644 integration_test/functions/src/testing.ts create mode 100644 integration_test/functions/src/utils.ts create mode 100644 integration_test/functions/src/v1/analytics-tests.ts create mode 100644 integration_test/functions/src/v1/tasks-tests.ts create mode 100644 integration_test/functions/src/v2/alerts-tests.ts create mode 100644 integration_test/functions/src/v2/database-tests.ts create mode 100644 integration_test/functions/src/v2/eventarc-tests.ts create mode 100644 integration_test/functions/src/v2/firestore-tests.ts create mode 100644 integration_test/functions/src/v2/identity-tests.ts create mode 100644 integration_test/functions/src/v2/pubsub-tests.ts create mode 100644 integration_test/functions/src/v2/remoteConfig-tests.ts delete mode 100644 integration_test/functions/src/v2/scheduled-tests.ts create mode 100644 integration_test/functions/src/v2/scheduler-tests.ts create mode 100644 integration_test/functions/src/v2/storage-tests.ts create mode 100644 integration_test/functions/src/v2/tasks-tests.ts create mode 100644 integration_test/functions/src/v2/testLab-tests.ts create mode 100644 integration_test/global.d.ts create mode 100644 integration_test/jest.config.js create mode 100644 integration_test/package-lock.json create mode 100644 integration_test/package.json create mode 100644 integration_test/run.ts delete mode 100755 integration_test/run_tests.sh create mode 100644 integration_test/setup.ts create mode 100644 integration_test/tests/firebaseSetup.ts create mode 100644 integration_test/tests/globalTeardown.ts create mode 100644 integration_test/tests/utils.ts create mode 100644 integration_test/tests/v1/analytics.test.ts create mode 100644 integration_test/tests/v1/auth.test.ts create mode 100644 integration_test/tests/v1/database.test.ts create mode 100644 integration_test/tests/v1/firestore.test.ts create mode 100644 integration_test/tests/v1/https.test.ts create mode 100644 integration_test/tests/v1/pubsub.test.ts create mode 100644 integration_test/tests/v1/remoteConfig.test.ts create mode 100644 integration_test/tests/v1/storage.test.ts rename integration_test/{functions/src/v1/testLab-utils.ts => tests/v1/testLab.test.ts} (58%) create mode 100644 integration_test/tests/v2/https.test.ts create mode 100644 integration_test/tests/v2/scheduler.test.ts create mode 100644 integration_test/tsconfig.json create mode 100644 integration_test/tsconfig.test.json diff --git a/integration_test/.env.example b/integration_test/.env.example new file mode 100644 index 000000000..b08459747 --- /dev/null +++ b/integration_test/.env.example @@ -0,0 +1,7 @@ +REGION=us-central1 +PROJECT_ID= +DATABASE_URL= +STORAGE_BUCKET= +NODE_VERSION=18 +FIREBASE_ADMIN=^10.0.0 +GOOGLE_APPLICATION_CREDENTIALS= diff --git a/integration_test/.gitignore b/integration_test/.gitignore new file mode 100644 index 000000000..a34e5488e --- /dev/null +++ b/integration_test/.gitignore @@ -0,0 +1,71 @@ +# 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 + +# Firebase/GCP config +.firebaserc +serviceAccount.json +functions.yaml diff --git a/integration_test/README.md b/integration_test/README.md index 3b0f5413f..852d3ac82 100644 --- a/integration_test/README.md +++ b/integration_test/README.md @@ -1,22 +1,32 @@ -## How to Use +# Integration Test Suite -**_ATTENTION_**: Running this test will wipe the contents of the Firebase project(s) you run it against. Make sure you use disposable Firebase project(s)! +## How to use -Run the integration test as follows: +### Prerequisites -```bash -./run_tests.sh [] -``` +Tests use locally installed firebase to invoke commands for deploying function. +The test also requires that you have gcloud CLI installed and authenticated +(`gcloud auth login`). + +Tests are deployed with a unique identifier, which enables the teardown of its own resources, without affecting other test runs. -Test runs cycles of testing, once for Node.js 14 and another for Node.js 16. +1. Add a service account at root serviceAccount.json +2. Add a .env `cp .env.example .env` -Test uses locally installed firebase to invoke commands for deploying function. The test also requires that you have -gcloud CLI installed and authenticated (`gcloud auth login`). +### Running setup and tests -Integration test is triggered by invoking HTTP function integrationTest which in turns invokes each function trigger -by issuing actions necessary to trigger it (e.g. write to storage bucket). +This will deploy functions with unique names, set up environment for running the +jest files, and run the jest test suite. + +```bash +yarn start +``` -### Debugging +## TODO -The status and result of each test is stored in RTDB of the project used for testing. You can also inspect Cloud Logging -for more clues. +[x] Deploy functions with unique name +[x] Update existing tests to use jest (v1 and v2) +[] Add missing coverage for v1 and v2 (WIP) +[] Ensure proper teardown of resources (only those for current test run) +[] Python runtime support +[] Capture test outcome for use by CI diff --git a/integration_test/functions/src/index.ts b/integration_test/functions/src/index.ts index 623b690c7..80abc60ee 100644 --- a/integration_test/functions/src/index.ts +++ b/integration_test/functions/src/index.ts @@ -1,230 +1,7 @@ -import { PubSub } from "@google-cloud/pubsub"; -import { GoogleAuth } from "google-auth-library"; -import { Request, Response } from "express"; import * as admin from "firebase-admin"; -import * as functions from "firebase-functions"; -import * as fs from "fs"; -import fetch from "node-fetch"; - import * as v1 from "./v1"; import * as v2 from "./v2"; -const getNumTests = (m: object): number => { - return Object.keys(m).filter((k) => ({}.hasOwnProperty.call(m[k], "__endpoint"))).length; -}; -const numTests = getNumTests(v1) + getNumTests(v2); -export { v1, v2 }; -import { REGION } from "./region"; -import * as testLab from "./v1/testLab-utils"; +export { v1, v2 }; -const firebaseConfig = JSON.parse(process.env.FIREBASE_CONFIG); admin.initializeApp(); - -// Re-enable no-unused-var check once callable functions are testable again. -// eslint-disable-next-line @typescript-eslint/no-unused-vars -async function callHttpsTrigger(name: string, data: any) { - const url = `https://${REGION}-${firebaseConfig.projectId}.cloudfunctions.net/${name}`; - const client = await new GoogleAuth().getIdTokenClient("32555940559.apps.googleusercontent.com"); - const resp = await client.request({ - url, - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ data }), - }); - if (resp.status > 200) { - throw Error(resp.statusText); - } -} - -// Re-enable no-unused-var check once callable functions are testable again. -// eslint-disable-next-line @typescript-eslint/no-unused-vars -async function callV2HttpsTrigger(name: string, data: any, accessToken: string) { - const getFnResp = await fetch( - `https://cloudfunctions.googleapis.com/v2beta/projects/${firebaseConfig.projectId}/locations/${REGION}/functions/${name}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - }, - } - ); - if (!getFnResp.ok) { - throw new Error(getFnResp.statusText); - } - const fn = await getFnResp.json(); - const uri = fn.serviceConfig?.uri; - if (!uri) { - throw new Error(`Cannot call v2 https trigger ${name} - no uri found`); - } - - const client = await new GoogleAuth().getIdTokenClient("32555940559.apps.googleusercontent.com"); - const invokeFnREsp = await client.request({ - url: uri, - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ data }), - }); - if (invokeFnREsp.status > 200) { - throw Error(invokeFnREsp.statusText); - } -} - -async function callScheduleTrigger(functionName: string, region: string, accessToken: string) { - const response = await fetch( - `https://cloudscheduler.googleapis.com/v1/projects/${firebaseConfig.projectId}/locations/us-central1/jobs/firebase-schedule-${functionName}-${region}:run`, - { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${accessToken}`, - }, - } - ); - if (!response.ok) { - throw new Error(`Failed request with status ${response.status}!`); - } - const data = await response.text(); - functions.logger.log(`Successfully scheduled function ${functionName}`, data); - return; -} - -async function callV2ScheduleTrigger(functionName: string, region: string, accessToken: string) { - const response = await fetch( - `https://cloudscheduler.googleapis.com/v1/projects/${firebaseConfig.projectId}/locations/us-central1/jobs/firebase-schedule-${functionName}-${region}:run`, - { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${accessToken}`, - }, - } - ); - if (!response.ok) { - throw new Error(`Failed request with status ${response.status}!`); - } - const data = await response.text(); - functions.logger.log(`Successfully scheduled v2 function ${functionName}`, data); - return; -} - -async function updateRemoteConfig(testId: string, accessToken: string): Promise { - const resp = await fetch( - `https://firebaseremoteconfig.googleapis.com/v1/projects/${firebaseConfig.projectId}/remoteConfig`, - { - method: "PUT", - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/json; UTF-8", - "Accept-Encoding": "gzip", - "If-Match": "*", - }, - body: JSON.stringify({ version: { description: testId } }), - } - ); - if (!resp.ok) { - throw new Error(resp.statusText); - } -} - -function v1Tests(testId: string, accessToken: string): Array> { - return [ - // A database write to trigger the Firebase Realtime Database tests. - admin.database().ref(`dbTests/${testId}/start`).set({ ".sv": "timestamp" }), - // A Pub/Sub publish to trigger the Cloud Pub/Sub tests. - new PubSub().topic("pubsubTests").publish(Buffer.from(JSON.stringify({ testId }))), - // A user creation to trigger the Firebase Auth user creation tests. - admin - .auth() - .createUser({ - email: `${testId}@fake.com`, - password: "secret", - displayName: `${testId}`, - }) - .then(async (userRecord) => { - // A user deletion to trigger the Firebase Auth user deletion tests. - await admin.auth().deleteUser(userRecord.uid); - }), - // A firestore write to trigger the Cloud Firestore tests. - admin.firestore().collection("tests").doc(testId).set({ test: testId }), - // Invoke a callable HTTPS trigger. - // TODO: Temporarily disable - doesn't work unless running on projects w/ permission to create public functions. - // callHttpsTrigger("v1-callableTests", { foo: "bar", testId }), - // A Remote Config update to trigger the Remote Config tests. - updateRemoteConfig(testId, accessToken), - // A storage upload to trigger the Storage tests - admin - .storage() - .bucket() - .upload("/tmp/" + testId + ".txt"), - testLab.startTestRun(firebaseConfig.projectId, testId, accessToken), - // Invoke the schedule for our scheduled function to fire - callScheduleTrigger("v1-schedule", "us-central1", accessToken), - ]; -} - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -function v2Tests(testId: string, accessToken: string): Array> { - return [ - // Invoke a callable HTTPS trigger. - // TODO: Temporarily disable - doesn't work unless running on projects w/ permission to create public functions. - // callV2HttpsTrigger("v2-callabletests", { foo: "bar", testId }, accessToken), - // Invoke a scheduled trigger. - callV2ScheduleTrigger("v2-schedule", "us-central1", accessToken), - ]; -} - -export const integrationTests: any = functions - .region(REGION) - .runWith({ - timeoutSeconds: 540, - invoker: "private", - }) - .https.onRequest(async (req: Request, resp: Response) => { - const testId = admin.database().ref().push().key; - await admin.database().ref(`testRuns/${testId}/timestamp`).set(Date.now()); - const testIdRef = admin.database().ref(`testRuns/${testId}`); - functions.logger.info("testId is: ", testId); - fs.writeFile(`/tmp/${testId}.txt`, "test", () => undefined); - try { - const accessToken = await admin.credential.applicationDefault().getAccessToken(); - await Promise.all([ - ...v1Tests(testId, accessToken.access_token), - ...v2Tests(testId, accessToken.access_token), - ]); - // On test completion, check that all tests pass and reply "PASS", or provide further details. - functions.logger.info("Waiting for all tests to report they pass..."); - await new Promise((resolve, reject) => { - setTimeout(() => reject(new Error("Timeout")), 5 * 60 * 1000); - let testsExecuted = 0; - testIdRef.on("child_added", (snapshot) => { - if (snapshot.key === "timestamp") { - return; - } - testsExecuted += 1; - if (!snapshot.val().passed) { - reject(new Error(`test ${snapshot.key} failed; see database for details.`)); - return; - } - functions.logger.info(`${snapshot.key} passed (${testsExecuted} of ${numTests})`); - if (testsExecuted < numTests) { - // Not all tests have completed. Wait longer. - return; - } - // All tests have passed! - resolve(); - }); - }); - functions.logger.info("All tests pass!"); - resp.status(200).send("PASS \n"); - } catch (err) { - functions.logger.info(`Some tests failed: ${err}`, err); - resp - .status(500) - .send(`FAIL - details at ${functions.firebaseConfig().databaseURL}/testRuns/${testId}`); - } finally { - testIdRef.off("child_added"); - } - }); diff --git a/integration_test/functions/src/testing.ts b/integration_test/functions/src/testing.ts deleted file mode 100644 index 156e94242..000000000 --- a/integration_test/functions/src/testing.ts +++ /dev/null @@ -1,134 +0,0 @@ -import * as firebase from "firebase-admin"; -import * as functions from "firebase-functions"; - -export type TestCase = (data: T, context?: functions.EventContext) => any; -export interface TestCaseMap { - [key: string]: TestCase; -} - -export class TestSuite { - private name: string; - private tests: TestCaseMap; - - constructor(name: string, tests: TestCaseMap = {}) { - this.name = name; - this.tests = tests; - } - - it(name: string, testCase: TestCase): TestSuite { - this.tests[name] = testCase; - return this; - } - - run(testId: string, data: T, context?: functions.EventContext): Promise { - const running: Array> = []; - for (const testName in this.tests) { - if (!this.tests.hasOwnProperty(testName)) { - continue; - } - const run = Promise.resolve() - .then(() => this.tests[testName](data, context)) - .then( - (result) => { - functions.logger.info( - `${result ? "Passed" : "Failed with successful op"}: ${testName}` - ); - return { name: testName, passed: !!result }; - }, - (error) => { - console.error(`Failed: ${testName}`, error); - return { name: testName, passed: 0, error }; - } - ); - running.push(run); - } - return Promise.all(running).then((results) => { - let sum = 0; - // eslint-disable-next-line @typescript-eslint/restrict-plus-operands - results.forEach((val) => (sum = sum + val.passed)); - const summary = `passed ${sum} of ${running.length}`; - const passed = sum === running.length; - functions.logger.info(summary); - const result = { passed, summary, tests: results }; - return firebase.database().ref(`testRuns/${testId}/${this.name}`).set(result); - }); - } -} - -export function success() { - return Promise.resolve().then(() => true); -} - -function failure(reason: string) { - return Promise.reject(reason); -} - -export function evaluate(value: boolean, errMsg: string) { - if (value) { - return success(); - } - return failure(errMsg); -} - -export function expectEq(left: any, right: any) { - return evaluate( - left === right, - JSON.stringify(left) + " does not equal " + JSON.stringify(right) - ); -} - -function deepEq(left: any, right: any) { - if (left === right) { - return true; - } - - if (!(left instanceof Object && right instanceof Object)) { - return false; - } - - if (Object.keys(left).length !== Object.keys(right).length) { - return false; - } - - for (const key in left) { - if (Object.prototype.hasOwnProperty.call(left, key)) { - if (!Object.prototype.hasOwnProperty.call(right, key)) { - return false; - } - if (!deepEq(left[key], right[key])) { - return false; - } - } - } - - return true; -} - -export function expectDeepEq(left: any, right: any) { - return evaluate( - deepEq(left, right), - `${JSON.stringify(left)} does not deep equal ${JSON.stringify(right)}` - ); -} - -export function expectMatches(input: string, regexp: RegExp) { - return evaluate( - input.match(regexp) !== null, - `Input '${input}' did not match regexp '${regexp}'` - ); -} - -export function expectReject(f: (e: EventType) => Promise) { - return async (event: EventType) => { - let rejected = false; - try { - await f(event); - } catch { - rejected = true; - } - - if (!rejected) { - throw new Error("Test should have returned a rejected promise"); - } - }; -} diff --git a/integration_test/functions/src/utils.ts b/integration_test/functions/src/utils.ts new file mode 100644 index 000000000..4e90ebe1b --- /dev/null +++ b/integration_test/functions/src/utils.ts @@ -0,0 +1,7 @@ +export const sanitizeData = (data: any) => + Object.entries(data).reduce((acc, [key, value]) => { + if (value !== undefined) { + acc[key] = value; + } + return acc; + }, {}); diff --git a/integration_test/functions/src/v1/analytics-tests.ts b/integration_test/functions/src/v1/analytics-tests.ts new file mode 100644 index 000000000..be957742e --- /dev/null +++ b/integration_test/functions/src/v1/analytics-tests.ts @@ -0,0 +1,25 @@ +import * as admin from "firebase-admin"; +import * as functions from "firebase-functions"; +import { REGION } from "../region"; +import { sanitizeData } from "../utils"; + +export const analyticsEventTests: any = functions + .region(REGION) + .analytics.event("in_app_purchase") + .onLog(async (event, context) => { + const testId = event.params?.testId; + try { + await admin + .firestore() + .collection("analyticsEventTests") + .doc(testId) + .set( + sanitizeData({ + ...context, + event: JSON.stringify(event), + }) + ); + } catch (error) { + console.error(`Error in Analytics event function for testId: ${testId}`, error); + } + }); diff --git a/integration_test/functions/src/v1/auth-tests.ts b/integration_test/functions/src/v1/auth-tests.ts index 5d1b6188a..57c78c3de 100644 --- a/integration_test/functions/src/v1/auth-tests.ts +++ b/integration_test/functions/src/v1/auth-tests.ts @@ -1,65 +1,87 @@ import * as admin from "firebase-admin"; import * as functions from "firebase-functions"; import { REGION } from "../region"; -import { expectEq, TestSuite } from "../testing"; -import UserMetadata = admin.auth.UserRecord; +import { sanitizeData } from "../utils"; -export const createUserTests: any = functions +export const authUserOnCreateTests: any = functions .region(REGION) .auth.user() - .onCreate((u, c) => { - const testId: string = u.displayName; - functions.logger.info(`testId is ${testId}`); - - return new TestSuite("auth user onCreate") - .it("should have a project as resource", (user, context) => - expectEq(context.resource.name, `projects/${process.env.GCLOUD_PROJECT}`) - ) - - .it("should not have a path", (user, context) => expectEq((context as any).path, undefined)) - - .it("should have the correct eventType", (user, context) => - expectEq(context.eventType, "google.firebase.auth.user.create") - ) - - .it("should have an eventId", (user, context) => context.eventId) - - .it("should have a timestamp", (user, context) => context.timestamp) - - .it("should not have auth", (user, context) => expectEq((context as any).auth, undefined)) - - .it("should not have action", (user, context) => expectEq((context as any).action, undefined)) - - .it("should have properly defined meta", (user) => user.metadata) - - .run(testId, u, c); + .onCreate(async (user, context) => { + const { email, displayName, uid } = user; + try { + const userProfile = { + email, + displayName, + createdAt: admin.firestore.FieldValue.serverTimestamp(), + }; + await admin.firestore().collection("userProfiles").doc(uid).set(userProfile); + + await admin + .firestore() + .collection("authUserOnCreateTests") + .doc(uid) + .set( + sanitizeData({ + ...context, + metadata: JSON.stringify(user.metadata), + }) + ); + } catch (error) { + console.error(`Error in Auth user onCreate function for uid: ${uid}`, error); + } }); -export const deleteUserTests: any = functions +export const authUserOnDeleteTests: any = functions .region(REGION) .auth.user() - .onDelete((u, c) => { - const testId: string = u.displayName; - functions.logger.info(`testId is ${testId}`); - - return new TestSuite("auth user onDelete") - .it("should have a project as resource", (user, context) => - expectEq(context.resource.name, `projects/${process.env.GCLOUD_PROJECT}`) - ) - - .it("should not have a path", (user, context) => expectEq((context as any).path, undefined)) - - .it("should have the correct eventType", (user, context) => - expectEq(context.eventType, "google.firebase.auth.user.delete") - ) - - .it("should have an eventId", (user, context) => context.eventId) - - .it("should have a timestamp", (user, context) => context.timestamp) - - .it("should not have auth", (user, context) => expectEq((context as any).auth, undefined)) + .onDelete(async (user, context) => { + const { uid } = user; + try { + await admin + .firestore() + .collection("authUserOnDeleteTests") + .doc(uid) + .set( + sanitizeData({ + ...context, + metadata: JSON.stringify(user.metadata), + }) + ); + } catch (error) { + console.error(`Error in Auth user onDelete function for uid: ${uid}`, error); + } + }); - .it("should not have action", (user, context) => expectEq((context as any).action, undefined)) +export const authUserBeforeCreateTests: any = functions + .region(REGION) + .auth.user() + .beforeCreate(async (user, context) => { + const { uid } = user; + try { + await admin + .firestore() + .collection("authUserBeforeCreateTests") + .doc(uid) + .set(sanitizeData(context)); + } catch (error) { + console.error(`Error in Auth user beforeCreate function for uid: ${uid}`, error); + } + return user; + }); - .run(testId, u, c); +export const authUserBeforeSignInTests: any = functions + .region(REGION) + .auth.user() + .beforeSignIn(async (user, context) => { + const { uid } = user; + try { + await admin + .firestore() + .collection("authUserBeforeSignInTests") + .doc(uid) + .set(sanitizeData(context)); + } catch (error) { + console.error(`Error in Auth user beforeSignIn function for uid: ${uid}`, error); + } + return user; }); diff --git a/integration_test/functions/src/v1/database-tests.ts b/integration_test/functions/src/v1/database-tests.ts index df9d3cdd2..569cdd9f2 100644 --- a/integration_test/functions/src/v1/database-tests.ts +++ b/integration_test/functions/src/v1/database-tests.ts @@ -1,75 +1,96 @@ import * as admin from "firebase-admin"; import * as functions from "firebase-functions"; import { REGION } from "../region"; -import { expectEq, expectMatches, TestSuite } from "../testing"; -import DataSnapshot = admin.database.DataSnapshot; +import { sanitizeData } from "../utils"; -const testIdFieldName = "testId"; - -export const databaseTests: any = functions +export const databaseRefOnCreateTests: any = functions .region(REGION) .database.ref("dbTests/{testId}/start") - .onWrite((ch, ctx) => { - if (ch.after.val() === null) { - functions.logger.info( - `Event for ${ctx.params[testIdFieldName]} is null; presuming data cleanup, so skipping.` - ); - return; - } - - return new TestSuite>("database ref onWrite") + .onCreate(async (snapshot, context) => { + const testId = context.params.testId; - .it("should not have event.app", (change, context) => !(context as any).app) - - .it("should give refs access to admin data", (change) => - change.after.ref.parent - .child("adminOnly") - .update({ allowed: 1 }) - .then(() => true) - ) - - .it("should have a correct ref url", (change) => { - const url = change.after.ref.toString(); - return Promise.resolve() - .then(() => { - return expectMatches( - url, - new RegExp( - `^https://${process.env.GCLOUD_PROJECT}(-default-rtdb)*.firebaseio.com/dbTests` - ) - ); + try { + await admin + .firestore() + .collection("databaseRefOnCreateTests") + .doc(testId) + .set( + sanitizeData({ + ...context, + url: snapshot.ref.toString(), }) - .then(() => { - return expectMatches(url, /\/start$/); - }); - }) - - .it("should have refs resources", (change, context) => - expectMatches( - context.resource.name, - new RegExp( - `^projects/_/instances/${process.env.GCLOUD_PROJECT}(-default-rtdb)*/refs/dbTests/${context.params.testId}/start$` - ) - ) - ) - - .it("should not include path", (change, context) => - expectEq((context as any).path, undefined) - ) + ); + } catch (error) { + console.error(`Error in Database ref onCreate function for testId: ${testId}`, error); + } + }); - .it("should have the right eventType", (change, context) => - expectEq(context.eventType, "google.firebase.database.ref.write") - ) +export const databaseRefOnDeleteTests: any = functions + .region(REGION) + .database.ref("dbTests/{testId}/start") + .onDelete(async (snapshot, context) => { + const testId = context.params.testId; - .it("should have eventId", (change, context) => context.eventId) + try { + await admin + .firestore() + .collection("databaseRefOnDeleteTests") + .doc(testId) + .set( + sanitizeData({ + ...context, + url: snapshot.ref.toString(), + }) + ); + } catch (error) { + console.error(`Error in Database ref onDelete function for testId: ${testId}`, error); + } + }); - .it("should have timestamp", (change, context) => context.timestamp) +export const databaseRefOnUpdateTests: any = functions + .region(REGION) + .database.ref("dbTests/{testId}/start") + .onUpdate(async (change, context) => { + const testId = context.params.testId; - .it("should not have action", (change, context) => - expectEq((context as any).action, undefined) - ) + try { + await admin + .firestore() + .collection("databaseRefOnUpdateTests") + .doc(testId) + .set( + sanitizeData({ + ...context, + url: change.after.ref.toString(), + }) + ); + } catch (error) { + console.error(`Error in Database ref onUpdate function for testId: ${testId}`, error); + } + }); - .it("should have admin authType", (change, context) => expectEq(context.authType, "ADMIN")) +export const databaseRefOnWriteTests: any = functions + .region(REGION) + .database.ref("dbTests/{testId}/start") + .onWrite(async (change, context) => { + const testId = context.params.testId; + if (change.after.val() === null) { + functions.logger.info(`Event for ${testId} is null; presuming data cleanup, so skipping.`); + return; + } - .run(ctx.params[testIdFieldName], ch, ctx); + try { + await admin + .firestore() + .collection("databaseRefOnWriteTests") + .doc(testId) + .set( + sanitizeData({ + ...context, + url: change.after.ref.toString(), + }) + ); + } catch (error) { + console.error(`Error in Database ref onWrite function for testId: ${testId}`, error); + } }); diff --git a/integration_test/functions/src/v1/firestore-tests.ts b/integration_test/functions/src/v1/firestore-tests.ts index b986ca06a..25b0d7d1d 100644 --- a/integration_test/functions/src/v1/firestore-tests.ts +++ b/integration_test/functions/src/v1/firestore-tests.ts @@ -1,44 +1,80 @@ import * as admin from "firebase-admin"; import * as functions from "firebase-functions"; import { REGION } from "../region"; -import { expectDeepEq, expectEq, TestSuite } from "../testing"; -import DocumentSnapshot = admin.firestore.DocumentSnapshot; +import { sanitizeData } from "../utils"; -const testIdFieldName = "documentId"; - -export const firestoreTests: any = functions +export const firestoreDocumentOnCreateTests: any = functions .runWith({ timeoutSeconds: 540, }) .region(REGION) - .firestore.document("tests/{documentId}") - .onCreate((s, c) => { - return new TestSuite("firestore document onWrite") - - .it("should not have event.app", (snap, context) => !(context as any).app) - - .it("should give refs write access", (snap) => - snap.ref.set({ allowed: 1 }, { merge: true }).then(() => true) - ) - - .it("should have well-formatted resource", (snap, context) => - expectEq( - context.resource.name, - `projects/${process.env.GCLOUD_PROJECT}/databases/(default)/documents/tests/${context.params.documentId}` - ) - ) - - .it("should have the right eventType", (snap, context) => - expectEq(context.eventType, "google.firestore.document.create") - ) - - .it("should have eventId", (snap, context) => context.eventId) + .firestore.document("tests/{testId}") + .onCreate(async (snapshot, context) => { + const testId = context.params.testId; + try { + await admin + .firestore() + .collection("firestoreDocumentOnCreateTests") + .doc(testId) + .set(sanitizeData(context)); + } catch (error) { + console.error(`Error in Firestore document onCreate function for testId: ${testId}`, error); + } + }); - .it("should have timestamp", (snap, context) => context.timestamp) +export const firestoreDocumentOnDeleteTests: any = functions + .runWith({ + timeoutSeconds: 540, + }) + .region(REGION) + .firestore.document("tests/{testId}") + .onDelete(async (snapshot, context) => { + const testId = context.params.testId; + try { + await admin + .firestore() + .collection("firestoreDocumentOnDeleteTests") + .doc(testId) + .set(sanitizeData(context)); + } catch (error) { + console.error(`Error in Firestore document onDelete function for testId: ${testId}`, error); + } + }); - .it("should have the correct data", (snap, context) => - expectDeepEq(snap.data(), { test: context.params.documentId }) - ) +export const firestoreDocumentOnUpdateTests: any = functions + .runWith({ + timeoutSeconds: 540, + }) + .region(REGION) + .firestore.document("tests/{testId}") + .onUpdate(async (change, context) => { + const testId = context.params.testId; + try { + await admin + .firestore() + .collection("firestoreDocumentOnUpdateTests") + .doc(testId) + .set(sanitizeData(context)); + } catch (error) { + console.error(`Error in Firestore document onUpdate function for testId: ${testId}`, error); + } + }); - .run(c.params[testIdFieldName], s, c); +export const firestoreDocumentOnWriteTests: any = functions + .runWith({ + timeoutSeconds: 540, + }) + .region(REGION) + .firestore.document("tests/{testId}") + .onWrite(async (change, context) => { + const testId = context.params.testId; + try { + await admin + .firestore() + .collection("firestoreDocumentOnWriteTests") + .doc(testId) + .set(sanitizeData(context)); + } catch (error) { + console.error(`Error in Firestore document onWrite function for testId: ${testId}`, error); + } }); diff --git a/integration_test/functions/src/v1/https-tests.ts b/integration_test/functions/src/v1/https-tests.ts index 5a74a1903..584538794 100644 --- a/integration_test/functions/src/v1/https-tests.ts +++ b/integration_test/functions/src/v1/https-tests.ts @@ -1,12 +1,35 @@ +import * as admin from "firebase-admin"; import * as functions from "firebase-functions"; import { REGION } from "../region"; -import { expectEq, TestSuite } from "../testing"; +import { sanitizeData } from "../utils"; -export const callableTests: any = functions +export const httpsOnCallTests: any = functions .runWith({ invoker: "private" }) .region(REGION) - .https.onCall((d) => { - return new TestSuite("https onCall") - .it("should have the correct data", (data: any) => expectEq(data?.foo, "bar")) - .run(d.testId, d); + .https.onCall(async (data) => { + try { + await admin + .firestore() + .collection("httpsOnCallTests") + .doc(data?.testId) + .set(sanitizeData(data)); + } catch (error) { + console.error(`Error in Https onCall function for testId: ${data?.testId}`, error); + } + }); + +export const httpsOnRequestTests: any = functions + .runWith({ invoker: "private" }) + .region(REGION) + .https.onRequest(async (req: functions.https.Request) => { + const data = req?.body.data; + try { + await admin + .firestore() + .collection("httpsOnRequestTests") + .doc(data?.testId) + .set(sanitizeData(data)); + } catch (error) { + console.error(`Error in Https onRequest function for testId: ${data?.testId}`, error); + } }); diff --git a/integration_test/functions/src/v1/index.ts b/integration_test/functions/src/v1/index.ts index 0a1a2a35f..8c0d1ec4f 100644 --- a/integration_test/functions/src/v1/index.ts +++ b/integration_test/functions/src/v1/index.ts @@ -1,9 +1,11 @@ -export * from "./pubsub-tests"; -export * from "./database-tests"; +export * from "./analytics-tests"; export * from "./auth-tests"; +export * from "./database-tests"; export * from "./firestore-tests"; -// Temporarily disable http test - will not work unless running on projects w/ permission to create public functions. +// // Temporarily disable http test - will not work unless running on projects w/ permission to create public functions. // export * from "./https-tests"; +export * from "./pubsub-tests"; export * from "./remoteConfig-tests"; export * from "./storage-tests"; +export * from "./tasks-tests"; export * from "./testLab-tests"; diff --git a/integration_test/functions/src/v1/pubsub-tests.ts b/integration_test/functions/src/v1/pubsub-tests.ts index 152ad7b6a..629eb5994 100644 --- a/integration_test/functions/src/v1/pubsub-tests.ts +++ b/integration_test/functions/src/v1/pubsub-tests.ts @@ -1,67 +1,50 @@ import * as admin from "firebase-admin"; import * as functions from "firebase-functions"; import { REGION } from "../region"; -import { evaluate, expectEq, success, TestSuite } from "../testing"; -import PubsubMessage = functions.pubsub.Message; +import { sanitizeData } from "../utils"; -// TODO(inlined) use multiple queues to run inline. -// Expected message data: {"hello": "world"} -export const pubsubTests: any = functions +export const pubsubOnPublishTests: any = functions .region(REGION) .pubsub.topic("pubsubTests") - .onPublish((m, c) => { - let testId: string; + .onPublish(async (message, context) => { + let testId = message.json?.testId; + if (!testId) { + console.error("TestId not found for onPublish function execution"); + return; + } try { - testId = m.json.testId; - } catch (e) { - /* Ignored. Covered in another test case that `event.data.json` works. */ + await admin + .firestore() + .collection("pubsubOnPublishTests") + .doc(testId) + .set( + sanitizeData({ + ...context, + message: JSON.stringify(message), + }) + ); + } catch (error) { + console.error(`Error in Pub/Sub onPublish function for testId: ${testId}`, error); } - - return new TestSuite("pubsub onPublish") - .it("should have a topic as resource", (message, context) => - expectEq(context.resource.name, `projects/${process.env.GCLOUD_PROJECT}/topics/pubsubTests`) - ) - - .it("should not have a path", (message, context) => - expectEq((context as any).path, undefined) - ) - - .it("should have the correct eventType", (message, context) => - expectEq(context.eventType, "google.pubsub.topic.publish") - ) - - .it("should have an eventId", (message, context) => context.eventId) - - .it("should have a timestamp", (message, context) => context.timestamp) - - .it("should not have auth", (message, context) => expectEq((context as any).auth, undefined)) - - .it("should not have action", (message, context) => - expectEq((context as any).action, undefined) - ) - - .it("should have pubsub data", (message) => { - const decoded = new Buffer(message.data, "base64").toString(); - const parsed = JSON.parse(decoded); - return evaluate(parsed.hasOwnProperty("testId"), `Raw data was + ${message.data}`); - }) - - .it("should decode JSON payloads with the json helper", (message) => - evaluate(message.json.hasOwnProperty("testId"), message.json) - ) - - .run(testId, m, c); }); -export const schedule: any = functions +export const pubsubScheduleTests: any = functions .region(REGION) .pubsub.schedule("every 10 hours") // This is a dummy schedule, since we need to put a valid one in. // For the test, the job is triggered by the jobs:run api - .onRun(async () => { - const db = admin.database(); - const snap = await db.ref("testRuns").orderByChild("timestamp").limitToLast(1).once("value"); - const testId = Object.keys(snap.val())[0]; - return new TestSuite("pubsub scheduleOnRun") - .it("should trigger when the scheduler fires", () => success()) - .run(testId, null); + .onRun(async (context) => { + const testId = context.resource?.labels?.service_name?.split("-")[0]; + if (!testId) { + console.error("TestId not found for scheduled function execution"); + return; + } + try { + await admin + .firestore() + .collection("pubsubScheduleTests") + .doc(testId) + .set(sanitizeData(context)); + } catch (error) { + console.error(`Error in Pub/Sub schedule function for testId: ${testId}`, error); + } }); diff --git a/integration_test/functions/src/v1/remoteConfig-tests.ts b/integration_test/functions/src/v1/remoteConfig-tests.ts index 416621774..d416e9c44 100644 --- a/integration_test/functions/src/v1/remoteConfig-tests.ts +++ b/integration_test/functions/src/v1/remoteConfig-tests.ts @@ -1,23 +1,19 @@ import * as functions from "firebase-functions"; +import * as admin from "firebase-admin"; import { REGION } from "../region"; -import { expectEq, TestSuite } from "../testing"; -import TemplateVersion = functions.remoteConfig.TemplateVersion; +import { sanitizeData } from "../utils"; -export const remoteConfigTests: any = functions.region(REGION).remoteConfig.onUpdate((v, c) => { - return new TestSuite("remoteConfig onUpdate") - .it("should have a project as resource", (version, context) => - expectEq(context.resource.name, `projects/${process.env.GCLOUD_PROJECT}`) - ) - - .it("should have the correct eventType", (version, context) => - expectEq(context.eventType, "google.firebase.remoteconfig.update") - ) - - .it("should have an eventId", (version, context) => context.eventId) - - .it("should have a timestamp", (version, context) => context.timestamp) - - .it("should not have auth", (version, context) => expectEq((context as any).auth, undefined)) - - .run(v.description, v, c); -}); +export const remoteConfigOnUpdateTests: any = functions + .region(REGION) + .remoteConfig.onUpdate(async (version, context) => { + const testId = version.description; + try { + await admin + .firestore() + .collection("remoteConfigOnUpdateTests") + .doc(testId) + .set(sanitizeData(context)); + } catch (error) { + console.error(`Error in RemoteConfig onUpdate function for testId: ${testId}`, error); + } + }); diff --git a/integration_test/functions/src/v1/storage-tests.ts b/integration_test/functions/src/v1/storage-tests.ts index 6819c7a2a..a2a6a5bfc 100644 --- a/integration_test/functions/src/v1/storage-tests.ts +++ b/integration_test/functions/src/v1/storage-tests.ts @@ -1,28 +1,100 @@ +import * as admin from "firebase-admin"; import * as functions from "firebase-functions"; import { REGION } from "../region"; -import { expectEq, TestSuite } from "../testing"; -import ObjectMetadata = functions.storage.ObjectMetadata; +import { sanitizeData } from "../utils"; -export const storageTests: any = functions +export const storageOnArchiveTests: any = functions .runWith({ timeoutSeconds: 540, }) .region(REGION) .storage.bucket() .object() - .onFinalize((s, c) => { - const testId = s.name.split(".")[0]; - return new TestSuite("storage object finalize") - - .it("should not have event.app", (data, context) => !(context as any).app) - - .it("should have the right eventType", (snap, context) => - expectEq(context.eventType, "google.storage.object.finalize") - ) + .onArchive(async (object, context) => { + const testId = object.name?.split(".")[0]; + if (!testId) { + console.error("TestId not found for storage object archive"); + return; + } + try { + await admin + .firestore() + .collection("storageOnArchiveTests") + .doc(testId) + .set(sanitizeData(context)); + } catch (error) { + console.error(`Error in Storage onArchive function for testId: ${testId}`, error); + } + }); - .it("should have eventId", (snap, context) => context.eventId) +export const storageOnDeleteTests: any = functions + .runWith({ + timeoutSeconds: 540, + }) + .region(REGION) + .storage.bucket() + .object() + .onDelete(async (object, context) => { + const testId = object.name?.split(".")[0]; + if (!testId) { + console.error("TestId not found for storage object delete"); + return; + } + try { + await admin + .firestore() + .collection("storageOnDeleteTests") + .doc(testId) + .set(sanitizeData(context)); + } catch (error) { + console.error(`Error in Storage onDelete function for testId: ${testId}`, error); + } + }); - .it("should have timestamp", (snap, context) => context.timestamp) +export const storageOnFinalizeTests: any = functions + .runWith({ + timeoutSeconds: 540, + }) + .region(REGION) + .storage.bucket() + .object() + .onFinalize(async (object, context) => { + const testId = object.name?.split(".")[0]; + if (!testId) { + console.error("TestId not found for storage object finalize"); + return; + } + try { + await admin + .firestore() + .collection("storageOnFinalizeTests") + .doc(testId) + .set(sanitizeData(context)); + } catch (error) { + console.error(`Error in Storage onFinalize function for testId: ${testId}`, error); + } + }); - .run(testId, s, c); +export const storageOnMetadataUpdateTests: any = functions + .runWith({ + timeoutSeconds: 540, + }) + .region(REGION) + .storage.bucket() + .object() + .onMetadataUpdate(async (object, context) => { + const testId = object.name?.split(".")[0]; + if (!testId) { + console.error("TestId not found for storage object metadata update"); + return; + } + try { + await admin + .firestore() + .collection("storageOnMetadataUpdateTests") + .doc(testId) + .set(sanitizeData(context)); + } catch (error) { + console.error(`Error in Storage onMetadataUpdate function for testId: ${testId}`, error); + } }); diff --git a/integration_test/functions/src/v1/tasks-tests.ts b/integration_test/functions/src/v1/tasks-tests.ts new file mode 100644 index 000000000..5439fd8c2 --- /dev/null +++ b/integration_test/functions/src/v1/tasks-tests.ts @@ -0,0 +1,23 @@ +import * as admin from "firebase-admin"; +import * as functions from "firebase-functions"; +import { REGION } from "../region"; +import { sanitizeData } from "../utils"; + +export const tasksOnDispatchTests: any = functions + .runWith({ + timeoutSeconds: 540, + }) + .region(REGION) + .tasks.taskQueue() + .onDispatch(async (data, context) => { + const testId = data.testId; + try { + await admin + .firestore() + .collection("tasksOnDispatchTests") + .doc(testId) + .set(sanitizeData(context)); + } catch (error) { + console.error(`Error in Tasks onDispatch function for testId: ${testId}`, error); + } + }); diff --git a/integration_test/functions/src/v1/testLab-tests.ts b/integration_test/functions/src/v1/testLab-tests.ts index 242cd21f6..b44c89a3a 100644 --- a/integration_test/functions/src/v1/testLab-tests.ts +++ b/integration_test/functions/src/v1/testLab-tests.ts @@ -1,23 +1,32 @@ +import * as admin from "firebase-admin"; import * as functions from "firebase-functions"; import { REGION } from "../region"; -import { expectEq, TestSuite } from "../testing"; -import TestMatrix = functions.testLab.TestMatrix; +import { sanitizeData } from "../utils"; -export const testLabTests: any = functions +export const testLabOnCompleteTests: any = functions .runWith({ timeoutSeconds: 540, }) .region(REGION) .testLab.testMatrix() - .onComplete((matrix, context) => { - return new TestSuite("test matrix complete") - .it("should have eventId", (snap, context) => context.eventId) - - .it("should have right eventType", (_, context) => - expectEq(context.eventType, "google.testing.testMatrix.complete") - ) - - .it("should be in state 'INVALID'", (matrix) => expectEq(matrix.state, "INVALID")) - - .run(matrix?.clientInfo?.details?.testId, matrix, context); + .onComplete(async (matrix, context) => { + const testId = matrix?.clientInfo?.details?.testId; + if (!testId) { + console.error("TestId not found for test matrix completion"); + return; + } + try { + await admin + .firestore() + .collection("testLabOnCompleteTests") + .doc(testId) + .set( + sanitizeData({ + ...context, + matrix: JSON.stringify(matrix), + }) + ); + } catch (error) { + console.error(`Error in Test Matrix onComplete function for testId: ${testId}`, error); + } }); diff --git a/integration_test/functions/src/v2/alerts-tests.ts b/integration_test/functions/src/v2/alerts-tests.ts new file mode 100644 index 000000000..377bef89d --- /dev/null +++ b/integration_test/functions/src/v2/alerts-tests.ts @@ -0,0 +1,234 @@ +import * as admin from "firebase-admin"; +import { onAlertPublished } from "firebase-functions/v2/alerts"; +import { + onInAppFeedbackPublished, + onNewTesterIosDevicePublished, +} from "firebase-functions/v2/alerts/appDistribution"; +import { + onPlanAutomatedUpdatePublished, + onPlanUpdatePublished, +} from "firebase-functions/v2/alerts/billing"; +import { + onNewAnrIssuePublished, + onNewFatalIssuePublished, + onNewNonfatalIssuePublished, + onRegressionAlertPublished, + onStabilityDigestPublished, + onVelocityAlertPublished, +} from "firebase-functions/v2/alerts/crashlytics"; +import { onThresholdAlertPublished } from "firebase-functions/v2/alerts/performance"; +import { REGION } from "../region"; + +export const alertsOnAlertPublishedTests = onAlertPublished("crashlytics.issue", async (event) => { + const testId = event.data.payload.testId; + + try { + await admin + .firestore() + .collection("alertsOnAlertPublishedTests") + .doc(testId) + .set({ event: JSON.stringify(event) }); + } catch (error) { + console.error(`Error handling alert for testId: ${testId}`, error); + } +}); + +export const alertsOnInAppFeedbackPublishedTests = onInAppFeedbackPublished(async (event) => { + const testId = event.data.payload.testerName; + + if (!testId) { + console.error("TestId not found for onInAppFeedbackPublished"); + return; + } + + try { + await admin + .firestore() + .collection("alertsOnInAppFeedbackPublishedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } +}); + +export const alertsOnNewTesterIosDevicePublishedTests = onNewTesterIosDevicePublished( + async (event) => { + const testId = event.data.payload.testerName; + + if (!testId) { + console.error("TestId not found for onNewTesterIosDevicePublished"); + return; + } + + try { + await admin + .firestore() + .collection("alertsOnNewTesterIosDevicePublishedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } + } +); + +export const alertsOnPlanAutomatedUpdatePublishedTests = onPlanAutomatedUpdatePublished( + async (event) => { + const testId = event.data.payload.billingPlan; + + if (!testId) { + console.error("TestId not found for onPlanAutomatedUpdatePublished"); + return; + } + + try { + await admin + .firestore() + .collection("alertsOnPlanAutomatedUpdatePublishedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } + } +); + +export const alertsOnPlanUpdatePublishedTests = onPlanUpdatePublished(async (event) => { + const testId = event.data.payload.billingPlan; + + if (!testId) { + console.error("TestId not found for onPlanUpdatePublished"); + return; + } + + try { + await admin + .firestore() + .collection("alertsOnPlanUpdatePublishedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } +}); + +export const alertsOnNewAnrIssuePublishedTests = onNewAnrIssuePublished(async (event) => { + const testId = event.data.payload.issue.title; + + try { + await admin + .firestore() + .collection("alertsOnNewAnrIssuePublishedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } +}); + +export const alertsOnNewFatalIssuePublishedTests = onNewFatalIssuePublished(async (event) => { + const testId = event.data.payload.issue.title; + + try { + await admin + .firestore() + .collection("alertsOnNewFatalIssuePublishedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } +}); + +export const alertsOnNewNonFatalIssuePublishedTests = onNewNonfatalIssuePublished(async (event) => { + const testId = event.data.payload.issue.title; + + try { + await admin + .firestore() + .collection("alertsOnNewFatalIssuePublishedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } +}); + +export const alertsOnRegressionAlertPublishedTests = onRegressionAlertPublished(async (event) => { + const testId = event.data.payload.issue.title; + + try { + await admin + .firestore() + .collection("alertsOnRegressionAlertPublishedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } +}); + +export const alertsOnStabilityDigestPublishedTests = onStabilityDigestPublished(async (event) => { + const testId = event.data.payload.trendingIssues[0].issue.title; + + try { + await admin + .firestore() + .collection("alertsOnRegressionAlertPublishedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } +}); + +export const alertsOnVelocityAlertPublishedTests = onVelocityAlertPublished(async (event) => { + const testId = event.data.payload.issue.title; + + try { + await admin + .firestore() + .collection("alertsOnVelocityAlertPublishedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } +}); + +export const alertsOnThresholdAlertPublishedTests = onThresholdAlertPublished(async (event) => { + const testId = event.data.payload.eventName; + + try { + await admin + .firestore() + .collection("alertsOnThresholdAlertPublishedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } +}); diff --git a/integration_test/functions/src/v2/database-tests.ts b/integration_test/functions/src/v2/database-tests.ts new file mode 100644 index 000000000..72b5bc3a3 --- /dev/null +++ b/integration_test/functions/src/v2/database-tests.ts @@ -0,0 +1,114 @@ +import * as admin from "firebase-admin"; +import { + onValueWritten, + onValueCreated, + onValueUpdated, + onValueDeleted, +} from "firebase-functions/v2/database"; +import { sanitizeData } from "../utils"; +import { REGION } from "../region"; + +export const databaseCreatedTests = onValueCreated( + { + ref: "databaseCreatedTests/{testId}/start", + region: REGION, + }, + async (event) => { + const testId = event.params.testId; + + try { + await admin + .firestore() + .collection("databaseCreatedTests") + .doc(testId) + .set( + sanitizeData({ + testId, + url: event.ref.toString(), + }) + ); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } + } +); + +export const databaseDeletedTests = onValueDeleted( + { + ref: "databaseDeletedTests/{testId}/start", + region: REGION, + }, + async (event) => { + const testId = event.params.testId; + + try { + await admin + .firestore() + .collection("databaseDeletedTests") + .doc(testId) + .set( + sanitizeData({ + testId, + url: event.ref.toString(), + }) + ); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } + } +); + +export const databaseUpdatedTests = onValueUpdated( + { + ref: "databaseUpdatedTests/{testId}/start", + region: REGION, + }, + async (event) => { + const testId = event.params.testId; + + try { + await admin + .firestore() + .collection("databaseUpdatedTests") + .doc(testId) + .set( + sanitizeData({ + testId, + url: event.ref.toString(), + }) + ); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } + } +); + +export const databaseWrittenTests = onValueWritten( + { + ref: "databaseWrittenTests/{testId}/start", + region: REGION, + }, + async (event) => { + const testId = event.params.testId; + + if (!event.data.after.exists()) { + console.info(`Event for ${testId} is null; presuming data cleanup, so skipping.`); + return; + } + + try { + await admin + .firestore() + .collection("databaseWrittenTests") + .doc(testId) + .set( + sanitizeData({ + testId, + url: event.ref.toString(), + }) + ); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } + } +); diff --git a/integration_test/functions/src/v2/eventarc-tests.ts b/integration_test/functions/src/v2/eventarc-tests.ts new file mode 100644 index 000000000..22dd60612 --- /dev/null +++ b/integration_test/functions/src/v2/eventarc-tests.ts @@ -0,0 +1,25 @@ +import * as admin from "firebase-admin"; +import { onCustomEventPublished } from "firebase-functions/v2/eventarc"; +import { REGION } from "../region"; + +export const eventarcOnCustomEventPublishedTests = onCustomEventPublished( + { + eventType: "custom_event_tests", + region: REGION, + }, + async (event) => { + const testId = event.data.payload.testId; + + try { + await admin + .firestore() + .collection("eventarcOnCustomEventPublishedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error creating test record for testId: ${testId}`, error); + } + } +); diff --git a/integration_test/functions/src/v2/firestore-tests.ts b/integration_test/functions/src/v2/firestore-tests.ts new file mode 100644 index 000000000..59a7f436b --- /dev/null +++ b/integration_test/functions/src/v2/firestore-tests.ts @@ -0,0 +1,84 @@ +import * as admin from "firebase-admin"; +import { onDocumentCreated, onDocumentDeleted } from "firebase-functions/v2/firestore"; +import { REGION } from "../region"; +import { sanitizeData } from "../utils"; + +export const firestoreOnDocumentCreatedTests = onDocumentCreated( + { + document: "tests/{documentId}", + region: REGION, + timeoutSeconds: 540, + }, + async (event) => { + const documentId = event.params.documentId; + try { + await admin + .firestore() + .collection("firestoreOnDocumentCreatedTests") + .doc(documentId) + .set(sanitizeData(event)); + } catch (error) { + console.error(`Error creating test record for testId: ${documentId}`, error); + } + } +); + +export const firestoreOnDocumentDeletedTests = onDocumentDeleted( + { + document: "tests/{documentId}", + region: REGION, + timeoutSeconds: 540, + }, + async (event) => { + const documentId = event.params.documentId; + try { + await admin + .firestore() + .collection("firestoreOnDocumentCreatedTests") + .doc(documentId) + .set(sanitizeData(event)); + } catch (error) { + console.error(`Error creating test record for testId: ${documentId}`, error); + } + } +); + +export const firestoreOnDocumentUpdatedTests = onDocumentDeleted( + { + document: "tests/{documentId}", + region: REGION, + timeoutSeconds: 540, + }, + async (event) => { + const documentId = event.params.documentId; + try { + await admin + .firestore() + .collection("firestoreOnDocumentUpdatedTests") + .doc(documentId) + .set(sanitizeData(event)); + } catch (error) { + console.error(`Error creating test record for testId: ${documentId}`, error); + } + } +); + +export const firestoreOnDocumentWrittenTests = onDocumentDeleted( + { + document: "tests/{documentId}", + region: REGION, + timeoutSeconds: 540, + }, + async (event) => { + const documentId = event.params.documentId; + try { + await admin + .firestore() + .collection("firestoreOnDocumentWrittenTests") + .doc(documentId) + .set(sanitizeData(event)); + } catch (error) { + console.error(`Error creating test record for testId: ${documentId}`, error); + } + } +); diff --git a/integration_test/functions/src/v2/https-tests.ts b/integration_test/functions/src/v2/https-tests.ts index b787ac602..5b572ab73 100644 --- a/integration_test/functions/src/v2/https-tests.ts +++ b/integration_test/functions/src/v2/https-tests.ts @@ -1,8 +1,33 @@ -import { onCall } from "firebase-functions/v2/https"; -import { expectEq, TestSuite } from "../testing"; +import { onCall, onRequest } from "firebase-functions/v2/https"; +import * as admin from "firebase-admin"; +import { REGION } from "../region"; -export const callabletests = onCall({ invoker: "private" }, (req) => { - return new TestSuite("v2 https onCall") - .it("should have the correct data", (data: any) => expectEq(data?.foo, "bar")) - .run(req.data.testId, req.data); -}); +export const httpsOnCallV2Tests = onCall( + { + invoker: "private", + region: REGION, + }, + async (req) => { + const data = req?.data; + try { + await admin.firestore().collection("httpsOnCallV2Tests").doc(data?.testId).set(data); + } catch (error) { + console.error(`Error creating test record for testId: ${data?.testId}`, error); + } + } +); + +export const httpsOnRequestV2Tests = onRequest( + { + invoker: "private", + region: REGION, + }, + async (req) => { + const data = req?.body.data; + try { + await admin.firestore().collection("httpsOnRequestV2Tests").doc(data?.testId).set(data); + } catch (error) { + console.error(`Error creating test record for testId: ${data?.testId}`, error); + } + } +); diff --git a/integration_test/functions/src/v2/identity-tests.ts b/integration_test/functions/src/v2/identity-tests.ts new file mode 100644 index 000000000..0b3381a2f --- /dev/null +++ b/integration_test/functions/src/v2/identity-tests.ts @@ -0,0 +1,34 @@ +import * as admin from "firebase-admin"; +import { beforeUserCreated, beforeUserSignedIn } from "firebase-functions/v2/identity"; + +export const identityBeforeUserCreatedTests = beforeUserCreated(async (event) => { + const { uid } = event.data; + try { + await admin + .firestore() + .collection("identityBeforeUserCreatedTests") + .doc(uid) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error in identity beforeUserCreated function for uid: ${uid}`, error); + } + return event.data; +}); + +export const identityBeforeUserSignedInTests = beforeUserSignedIn(async (event) => { + const { uid } = event.data; + try { + await admin + .firestore() + .collection("identityBeforeUserSignedInTests") + .doc(uid) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error in identity beforeUserCreated function for uid: ${uid}`, error); + } + return event.data; +}); diff --git a/integration_test/functions/src/v2/index.ts b/integration_test/functions/src/v2/index.ts index 38cde5f92..9fdd9807a 100644 --- a/integration_test/functions/src/v2/index.ts +++ b/integration_test/functions/src/v2/index.ts @@ -2,6 +2,16 @@ import { setGlobalOptions } from "firebase-functions/v2"; import { REGION } from "../region"; setGlobalOptions({ region: REGION }); -// TODO: Temporarily disable - doesn't work unless running on projects w/ permission to create public functions. +export * from "./alerts-tests"; +// export * from "./database-tests"; +// export * from "./eventarc-tests"; +// export * from "./firestore-tests"; // export * from './https-tests'; -export * from "./scheduled-tests"; +// TODO: cannot deploy multiple auth blocking funcs at once. +// update framework to run v1 tests in isolation, tear down, then run v2 tests +// export * from "./identity-tests"; +// export * from './pubsub-tests'; +// export * from "./scheduler-tests"; +// export * from "./storage-tests"; +// export * from "./tasks-tests"; +// export * from "./testLab-tests"; diff --git a/integration_test/functions/src/v2/pubsub-tests.ts b/integration_test/functions/src/v2/pubsub-tests.ts new file mode 100644 index 000000000..b7aae851b --- /dev/null +++ b/integration_test/functions/src/v2/pubsub-tests.ts @@ -0,0 +1,28 @@ +import * as admin from "firebase-admin"; +import { onMessagePublished } from "firebase-functions/v2/pubsub"; +import { REGION } from "../region"; + +export const pubsubOnMessagePublishedTests = onMessagePublished( + { + topic: "custom_message_tests", + region: REGION, + }, + async (event) => { + let testId = event.data.message.json?.testId; + if (!testId) { + console.error("TestId not found for onMessagePublished function execution"); + return; + } + try { + await admin + .firestore() + .collection("pubsubOnMessagePublishedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error in Pub/Sub onMessagePublished function for testId: ${testId}`, error); + } + } +); diff --git a/integration_test/functions/src/v2/remoteConfig-tests.ts b/integration_test/functions/src/v2/remoteConfig-tests.ts new file mode 100644 index 000000000..018a9d9eb --- /dev/null +++ b/integration_test/functions/src/v2/remoteConfig-tests.ts @@ -0,0 +1,23 @@ +import { onConfigUpdated } from "firebase-functions/v2/remoteConfig"; +import * as admin from "firebase-admin"; +import { REGION } from "../region"; + +export const remoteConfigOnConfigUpdatedTests = onConfigUpdated( + { + region: REGION, + }, + async (event) => { + const testId = event.data.description; + try { + await admin + .firestore() + .collection("remoteConfigOnConfigUpdatedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error in RemoteConfig onConfigUpdated function for testId: ${testId}`, error); + } + } +); diff --git a/integration_test/functions/src/v2/scheduled-tests.ts b/integration_test/functions/src/v2/scheduled-tests.ts deleted file mode 100644 index cc13bed62..000000000 --- a/integration_test/functions/src/v2/scheduled-tests.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as admin from "firebase-admin"; -import { onSchedule } from "firebase-functions/v2/scheduler"; -import { REGION } from "../region"; -import { success, TestSuite } from "../testing"; - -export const schedule: any = onSchedule( - { - schedule: "every 10 hours", - region: REGION, - }, - async () => { - const db = admin.database(); - const snap = await db.ref("testRuns").orderByChild("timestamp").limitToLast(1).once("value"); - const testId = Object.keys(snap.val())[0]; - return new TestSuite("scheduler scheduleOnRun") - .it("should trigger when the scheduler fires", () => success()) - .run(testId, null); - } -); diff --git a/integration_test/functions/src/v2/scheduler-tests.ts b/integration_test/functions/src/v2/scheduler-tests.ts new file mode 100644 index 000000000..09bad2612 --- /dev/null +++ b/integration_test/functions/src/v2/scheduler-tests.ts @@ -0,0 +1,27 @@ +import * as admin from "firebase-admin"; +import { onSchedule } from "firebase-functions/v2/scheduler"; +import { REGION } from "../region"; + +export const schedulerOnScheduleTests: any = onSchedule( + { + schedule: "every 10 hours", + region: REGION, + }, + async (event) => { + const testId = event.jobName; + if (!testId) { + console.error("TestId not found for scheduled function execution"); + return; + } + try { + await admin + .firestore() + .collection("schedulerOnScheduleTests") + .doc(testId) + .set({ success: true }); + } catch (error) { + console.error(`Error in scheduler onSchedule function for testId: ${testId}`, error); + } + return; + } +); diff --git a/integration_test/functions/src/v2/storage-tests.ts b/integration_test/functions/src/v2/storage-tests.ts new file mode 100644 index 000000000..821ddc338 --- /dev/null +++ b/integration_test/functions/src/v2/storage-tests.ts @@ -0,0 +1,99 @@ +import * as admin from "firebase-admin"; +import { + onObjectArchived, + onObjectDeleted, + onObjectFinalized, + onObjectMetadataUpdated, +} from "firebase-functions/v2/storage"; +import { REGION } from "../region"; + +export const storageOnObjectArchiveTests = onObjectArchived( + { + region: REGION, + }, + async (event) => { + const testId = event.data.name?.split(".")[0]; + if (!testId) { + console.error("TestId not found for storage onObjectArchived"); + return; + } + try { + await admin + .firestore() + .collection("storageOnObjectArchivedTests") + .doc(testId) + .set({ event: JSON.stringify(event) }); + } catch (error) { + console.error(`Error in Storage onObjectArchived function for testId: ${testId}`, error); + } + } +); + +export const storageOnDeleteTests = onObjectDeleted( + { + region: REGION, + }, + async (event) => { + const testId = event.data.name?.split(".")[0]; + if (!testId) { + console.error("TestId not found for storage onObjectDeleted"); + return; + } + try { + await admin + .firestore() + .collection("storageOnObjectDeletedTests") + .doc(testId) + .set({ event: JSON.stringify(event) }); + } catch (error) { + console.error(`Error in Storage onObjectDeleted function for testId: ${testId}`, error); + } + } +); + +export const storageOnFinalizeTests = onObjectFinalized( + { + region: REGION, + }, + async (event) => { + const testId = event.data.name?.split(".")[0]; + if (!testId) { + console.error("TestId not found for storage onObjectFinalized"); + return; + } + try { + await admin + .firestore() + .collection("storageOnObjectFinalizedTests") + .doc(testId) + .set({ event: JSON.stringify(event) }); + } catch (error) { + console.error(`Error in Storage onObjectFinalized function for testId: ${testId}`, error); + } + } +); + +export const storageOnMetadataUpdateTests = onObjectMetadataUpdated( + { + region: REGION, + }, + async (event) => { + const testId = event.data.name?.split(".")[0]; + if (!testId) { + console.error("TestId not found for storage onObjectMetadataUpdated"); + return; + } + try { + await admin + .firestore() + .collection("storageOnObjectMetadataUpdatedTests") + .doc(testId) + .set({ event: JSON.stringify(event) }); + } catch (error) { + console.error( + `Error in Storage onObjectMetadataUpdated function for testId: ${testId}`, + error + ); + } + } +); diff --git a/integration_test/functions/src/v2/tasks-tests.ts b/integration_test/functions/src/v2/tasks-tests.ts new file mode 100644 index 000000000..c4af36232 --- /dev/null +++ b/integration_test/functions/src/v2/tasks-tests.ts @@ -0,0 +1,23 @@ +import * as admin from "firebase-admin"; +import { onTaskDispatched } from "firebase-functions/v2/tasks"; +import { REGION } from "../region"; + +export const tasksOnTaskDispatchedTests = onTaskDispatched( + { + region: REGION, + }, + async (event) => { + const testId = event.data.testId; + try { + await admin + .firestore() + .collection("tasksOnTaskDispatchedTests") + .doc(testId) + .set({ + event: JSON.stringify(event), + }); + } catch (error) { + console.error(`Error in Tasks onTaskDispatched function for testId: ${testId}`, error); + } + } +); diff --git a/integration_test/functions/src/v2/testLab-tests.ts b/integration_test/functions/src/v2/testLab-tests.ts new file mode 100644 index 000000000..1235d8848 --- /dev/null +++ b/integration_test/functions/src/v2/testLab-tests.ts @@ -0,0 +1,28 @@ +import * as admin from "firebase-admin"; +import { onTestMatrixCompleted } from "firebase-functions/v2/testLab"; +import { REGION } from "../region"; + +export const testLabOnTestMatrixCompletedTests = onTestMatrixCompleted( + { + region: REGION, + }, + async (event) => { + const testId = event.data.clientInfo?.details?.testId; + if (!testId) { + console.error("TestId not found for test matrix completion"); + return; + } + try { + await admin + .firestore() + .collection("testLabOnTestMatrixCompletedTests") + .doc(testId) + .set({ event: JSON.stringify(event) }); + } catch (error) { + console.error( + `Error in Test Matrix onTestMatrixCompleted function for testId: ${testId}`, + error + ); + } + } +); diff --git a/integration_test/global.d.ts b/integration_test/global.d.ts new file mode 100644 index 000000000..68ce9f603 --- /dev/null +++ b/integration_test/global.d.ts @@ -0,0 +1,3 @@ +declare module "firebase-tools"; +declare module "firebase-tools/lib/deploy/functions/runtimes/index.js"; +declare module "firebase-tools/lib/deploy/functions/runtimes/discovery/index.js"; diff --git a/integration_test/jest.config.js b/integration_test/jest.config.js new file mode 100644 index 000000000..30052fdc7 --- /dev/null +++ b/integration_test/jest.config.js @@ -0,0 +1,10 @@ +export default { + preset: "ts-jest", + testEnvironment: "node", + testMatch: ["**/tests/**/*.test.ts"], + testTimeout: 30000, + globalTeardown: "./tests/globalTeardown.ts", + transform: { + "^.+\\.(t|j)s$": ["ts-jest", { tsconfig: "tsconfig.test.json" }], + }, +}; diff --git a/integration_test/package-lock.json b/integration_test/package-lock.json new file mode 100644 index 000000000..b0f450999 --- /dev/null +++ b/integration_test/package-lock.json @@ -0,0 +1,9864 @@ +{ + "name": "integration_test", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "integration_test", + "dependencies": { + "@firebase/analytics": "^0.10.0", + "firebase": "^8.2.3", + "firebase-admin": "^11.11.0", + "firebase-tools": "^12.9.1", + "js-yaml": "^4.1.0" + }, + "devDependencies": { + "@types/firebase": "^3.2.1", + "@types/jest": "^29.5.11", + "@types/js-yaml": "^4.0.9", + "@types/node-fetch": "^2.6.9", + "jest": "^29.7.0", + "ts-jest": "^29.1.1" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "9.1.2", + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.5", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.5", + "@babel/parser": "^7.23.5", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.5", + "@babel/types": "^7.23.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.23.5", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.5", + "@babel/types": "^7.23.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.5", + "dev": true, + "license": "MIT", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.23.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.23.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.5", + "@babel/types": "^7.23.5", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.23.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "license": "MIT", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "node_modules/@fastify/busboy": { + "version": "1.2.1", + "license": "MIT", + "dependencies": { + "text-decoding": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@firebase/analytics": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.0.tgz", + "integrity": "sha512-Locv8gAqx0e+GX/0SI3dzmBY5e9kjVDtD+3zCFLJ0tH2hJwuCAiL+5WkHuxKj92rqQj/rvkBUCfA1ewlX2hehg==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/installations": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/analytics-types": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.6.0.tgz", + "integrity": "sha512-kbMawY0WRPyL/lbknBkme4CNLl+Gw+E9G4OpNeXAauqoQiNkBgpIvZYy7BRT4sNGhZbxdxXxXbruqUwDzLmvTw==" + }, + "node_modules/@firebase/app": { + "version": "0.9.25", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.9.25.tgz", + "integrity": "sha512-fX22gL5USXhOK21Hlh3oTeOzQZ6th6S2JrjXNEpBARmwzuUkqmVGVdsOCIFYIsLpK0dQE3o8xZnLrRg5wnzZ/g==", + "peer": true, + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "idb": "7.1.1", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.3.2.tgz", + "integrity": "sha512-YjpsnV1xVTO1B836IKijRcDeceLgHQNJ/DWa+Vky9UHkm1Mi4qosddX8LZzldaWRTWKX7BN1MbZOLY8r7M/MZQ==", + "dependencies": { + "@firebase/app-check-interop-types": "0.1.0", + "@firebase/app-check-types": "0.3.1", + "@firebase/component": "0.5.6", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/app-check-interop-types": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.1.0.tgz", + "integrity": "sha512-uZfn9s4uuRsaX5Lwx+gFP3B6YsyOKUE+Rqa6z9ojT4VSRAsZFko9FRn6OxQUA1z5t5d08fY4pf+/+Dkd5wbdbA==" + }, + "node_modules/@firebase/app-check-types": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.3.1.tgz", + "integrity": "sha512-KJ+BqJbdNsx4QT/JIT1yDj5p6D+QN97iJs3GuHnORrqL+DU3RWc9nSYQsrY6Tv9jVWcOkMENXAgDT484vzsm2w==" + }, + "node_modules/@firebase/app-check/node_modules/@firebase/component": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", + "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "dependencies": { + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-check/node_modules/@firebase/logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", + "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" + }, + "node_modules/@firebase/app-check/node_modules/@firebase/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", + "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-types": { + "version": "0.9.0", + "license": "Apache-2.0" + }, + "node_modules/@firebase/auth": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.16.8.tgz", + "integrity": "sha512-mR0UXG4LirWIfOiCWxVmvz1o23BuKGxeItQ2cCUgXLTjNtWJXdcky/356iTUsd7ZV5A78s2NHeN5tIDDG6H4rg==", + "dependencies": { + "@firebase/auth-types": "0.10.3" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.2.1", + "license": "Apache-2.0" + }, + "node_modules/@firebase/auth-types": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.10.3.tgz", + "integrity": "sha512-zExrThRqyqGUbXOFrH/sowuh2rRtfKHp9SBVY2vOqKWdCX1Ztn682n9WLtlUDsiYVIbBcwautYWk2HyCGFv0OA==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/component": { + "version": "0.6.4", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database": { + "version": "0.14.4", + "license": "Apache-2.0", + "dependencies": { + "@firebase/auth-interop-types": "0.2.1", + "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-compat": { + "version": "0.3.4", + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/database": "0.14.4", + "@firebase/database-types": "0.10.4", + "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.3", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-types": { + "version": "0.10.4", + "license": "Apache-2.0", + "dependencies": { + "@firebase/app-types": "0.9.0", + "@firebase/util": "1.9.3" + } + }, + "node_modules/@firebase/firestore": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-2.4.1.tgz", + "integrity": "sha512-S51XnILdhNt0ZA6bPnbxpqKPI5LatbGY9RQjA2TmATrjSPE3aWndJsLIrutI6aS9K+YFwy5+HLDKVRFYQfmKAw==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/firestore-types": "2.4.0", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "@firebase/webchannel-wrapper": "0.5.1", + "@grpc/grpc-js": "^1.3.2", + "@grpc/proto-loader": "^0.6.0", + "node-fetch": "2.6.7", + "tslib": "^2.1.0" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/firestore-types": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-2.4.0.tgz", + "integrity": "sha512-0dgwfuNP7EN6/OlK2HSNSQiQNGLGaRBH0gvgr1ngtKKJuJFuq0Z48RBMeJX9CGjV4TP9h2KaB+KrUKJ5kh1hMg==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/firestore/node_modules/@firebase/component": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", + "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "dependencies": { + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/firestore/node_modules/@firebase/logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", + "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" + }, + "node_modules/@firebase/firestore/node_modules/@firebase/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", + "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/firestore/node_modules/@grpc/proto-loader": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", + "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", + "dependencies": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.11.3", + "yargs": "^16.2.0" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@firebase/firestore/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/@firebase/firestore/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/@firebase/firestore/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@firebase/firestore/node_modules/protobufjs": { + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/@firebase/firestore/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@firebase/firestore/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@firebase/functions": { + "version": "0.6.16", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.6.16.tgz", + "integrity": "sha512-KDPjLKSjtR/zEH06YXXbdWTi8gzbKHGRzL/+ibZQA/1MLq0IilfM+1V1Fh8bADsMCUkxkqoc1yiA4SUbH5ajJA==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/functions-types": "0.4.0", + "@firebase/messaging-types": "0.5.0", + "node-fetch": "2.6.7", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/functions-types": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.4.0.tgz", + "integrity": "sha512-3KElyO3887HNxtxNF1ytGFrNmqD+hheqjwmT3sI09FaDCuaxGbOnsXAXH2eQ049XRXw9YQpHMgYws/aUNgXVyQ==" + }, + "node_modules/@firebase/functions/node_modules/@firebase/component": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", + "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "dependencies": { + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/functions/node_modules/@firebase/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", + "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/functions/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@firebase/installations": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.4.tgz", + "integrity": "sha512-u5y88rtsp7NYkCHC3ElbFBrPtieUybZluXyzl7+4BsIz4sqb4vSAuwHEUgCgCeaQhvsnxDEU6icly8U9zsJigA==", + "dependencies": { + "@firebase/component": "0.6.4", + "@firebase/util": "1.9.3", + "idb": "7.0.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/installations-types": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.3.4.tgz", + "integrity": "sha512-RfePJFovmdIXb6rYwtngyxuEcWnOrzdZd9m7xAW0gRxDIjBT20n3BOhjpmgRWXo/DAxRmS7bRjWAyTHY9cqN7Q==", + "peerDependencies": { + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/installations/node_modules/idb": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz", + "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg==" + }, + "node_modules/@firebase/logger": { + "version": "0.4.0", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/messaging": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.8.0.tgz", + "integrity": "sha512-hkFHDyVe1kMcY9KEG+prjCbvS6MtLUgVFUbbQqq7JQfiv58E07YCzRUcMrJolbNi/1QHH6Jv16DxNWjJB9+/qA==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/installations": "0.4.32", + "@firebase/messaging-types": "0.5.0", + "@firebase/util": "1.3.0", + "idb": "3.0.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/messaging-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/messaging-types/-/messaging-types-0.5.0.tgz", + "integrity": "sha512-QaaBswrU6umJYb/ZYvjR5JDSslCGOH6D9P136PhabFAHLTR4TWjsaACvbBXuvwrfCXu10DtcjMxqfhdNIB1Xfg==", + "peerDependencies": { + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/messaging/node_modules/@firebase/component": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", + "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "dependencies": { + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/messaging/node_modules/@firebase/installations": { + "version": "0.4.32", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.32.tgz", + "integrity": "sha512-K4UlED1Vrhd2rFQQJih+OgEj8OTtrtH4+Izkx7ip2bhXSc+unk8ZhnF69D0kmh7zjXAqEDJrmHs9O5fI3rV6Tw==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/installations-types": "0.3.4", + "@firebase/util": "1.3.0", + "idb": "3.0.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/messaging/node_modules/@firebase/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", + "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/messaging/node_modules/idb": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", + "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" + }, + "node_modules/@firebase/performance": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.4.18.tgz", + "integrity": "sha512-lvZW/TVDne2TyOpWbv++zjRn277HZpbjxbIPfwtnmKjVY1gJ+H77Qi1c2avVIc9hg80uGX/5tNf4pOApNDJLVg==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/installations": "0.4.32", + "@firebase/logger": "0.2.6", + "@firebase/performance-types": "0.0.13", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/performance-types": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.0.13.tgz", + "integrity": "sha512-6fZfIGjQpwo9S5OzMpPyqgYAUZcFzZxHFqOyNtorDIgNXq33nlldTL/vtaUZA8iT9TT5cJlCrF/jthKU7X21EA==" + }, + "node_modules/@firebase/performance/node_modules/@firebase/component": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", + "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "dependencies": { + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/performance/node_modules/@firebase/installations": { + "version": "0.4.32", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.32.tgz", + "integrity": "sha512-K4UlED1Vrhd2rFQQJih+OgEj8OTtrtH4+Izkx7ip2bhXSc+unk8ZhnF69D0kmh7zjXAqEDJrmHs9O5fI3rV6Tw==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/installations-types": "0.3.4", + "@firebase/util": "1.3.0", + "idb": "3.0.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/performance/node_modules/@firebase/logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", + "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" + }, + "node_modules/@firebase/performance/node_modules/@firebase/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", + "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/performance/node_modules/idb": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", + "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" + }, + "node_modules/@firebase/polyfill": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@firebase/polyfill/-/polyfill-0.3.36.tgz", + "integrity": "sha512-zMM9oSJgY6cT2jx3Ce9LYqb0eIpDE52meIzd/oe/y70F+v9u1LDqk5kUF5mf16zovGBWMNFmgzlsh6Wj0OsFtg==", + "dependencies": { + "core-js": "3.6.5", + "promise-polyfill": "8.1.3", + "whatwg-fetch": "2.0.4" + } + }, + "node_modules/@firebase/polyfill/node_modules/whatwg-fetch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + }, + "node_modules/@firebase/remote-config": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.43.tgz", + "integrity": "sha512-laNM4MN0CfeSp7XCVNjYOC4DdV6mj0l2rzUh42x4v2wLTweCoJ/kc1i4oWMX9TI7Jw8Am5Wl71Awn1J2pVe5xA==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/installations": "0.4.32", + "@firebase/logger": "0.2.6", + "@firebase/remote-config-types": "0.1.9", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/remote-config-types": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.1.9.tgz", + "integrity": "sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA==" + }, + "node_modules/@firebase/remote-config/node_modules/@firebase/component": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", + "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "dependencies": { + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/remote-config/node_modules/@firebase/installations": { + "version": "0.4.32", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.32.tgz", + "integrity": "sha512-K4UlED1Vrhd2rFQQJih+OgEj8OTtrtH4+Izkx7ip2bhXSc+unk8ZhnF69D0kmh7zjXAqEDJrmHs9O5fI3rV6Tw==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/installations-types": "0.3.4", + "@firebase/util": "1.3.0", + "idb": "3.0.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/remote-config/node_modules/@firebase/logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", + "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" + }, + "node_modules/@firebase/remote-config/node_modules/@firebase/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", + "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/remote-config/node_modules/idb": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", + "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" + }, + "node_modules/@firebase/storage": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.7.1.tgz", + "integrity": "sha512-T7uH6lAgNs/Zq8V3ElvR3ypTQSGWon/R7WRM2I5Td/d0PTsNIIHSAGB6q4Au8mQEOz3HDTfjNQ9LuQ07R6S2ug==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/storage-types": "0.5.0", + "@firebase/util": "1.3.0", + "node-fetch": "2.6.7", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/storage-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.5.0.tgz", + "integrity": "sha512-6Wv3Lu7s18hsgW7HG4BFwycTquZ3m/C8bjBoOsmPu0TD6M1GKwCzOC7qBdN7L6tRYPh8ipTj5+rPFrmhGfUVKA==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/storage/node_modules/@firebase/component": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", + "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "dependencies": { + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/storage/node_modules/@firebase/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", + "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/storage/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@firebase/util": { + "version": "1.9.3", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/webchannel-wrapper": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.5.1.tgz", + "integrity": "sha512-dZMzN0uAjwJXWYYAcnxIwXqRTZw3o14hGe7O6uhwjD1ZQWPVYA5lASgnNskEBra0knVBsOXB4KXg+HnlKewN/A==" + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "license": "MIT", + "optional": true + }, + "node_modules/@google-cloud/firestore": { + "version": "6.8.0", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^3.5.7", + "protobufjs": "^7.2.5" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@google-cloud/firestore/node_modules/protobufjs": { + "version": "7.2.5", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@google-cloud/paginator": { + "version": "3.0.7", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/precise-date": { + "version": "3.0.1", + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@google-cloud/projectify": { + "version": "3.0.0", + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@google-cloud/promisify": { + "version": "2.0.4", + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/pubsub": { + "version": "3.7.5", + "license": "Apache-2.0", + "dependencies": { + "@google-cloud/paginator": "^4.0.0", + "@google-cloud/precise-date": "^3.0.0", + "@google-cloud/projectify": "^3.0.0", + "@google-cloud/promisify": "^2.0.0", + "@opentelemetry/api": "^1.6.0", + "@opentelemetry/semantic-conventions": "~1.3.0", + "@types/duplexify": "^3.6.0", + "@types/long": "^4.0.0", + "arrify": "^2.0.0", + "extend": "^3.0.2", + "google-auth-library": "^8.0.2", + "google-gax": "^3.6.1", + "heap-js": "^2.2.0", + "is-stream-ended": "^0.1.4", + "lodash.snakecase": "^4.1.1", + "p-defer": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@google-cloud/pubsub/node_modules/@google-cloud/paginator": { + "version": "4.0.1", + "license": "Apache-2.0", + "dependencies": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@google-cloud/storage": { + "version": "6.12.0", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@google-cloud/paginator": "^3.0.7", + "@google-cloud/projectify": "^3.0.0", + "@google-cloud/promisify": "^3.0.0", + "abort-controller": "^3.0.0", + "async-retry": "^1.3.3", + "compressible": "^2.0.12", + "duplexify": "^4.0.0", + "ent": "^2.2.0", + "extend": "^3.0.2", + "fast-xml-parser": "^4.2.2", + "gaxios": "^5.0.0", + "google-auth-library": "^8.0.1", + "mime": "^3.0.0", + "mime-types": "^2.0.8", + "p-limit": "^3.0.1", + "retry-request": "^5.0.0", + "teeny-request": "^8.0.0", + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@google-cloud/storage/node_modules/@google-cloud/promisify": { + "version": "3.0.1", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@google-cloud/storage/node_modules/mime": { + "version": "3.0.0", + "license": "MIT", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.8.21", + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.10", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.4", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/proto-loader/node_modules/protobufjs": { + "version": "7.2.5", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/reporters/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/write-file-atomic": { + "version": "4.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "license": "MIT" + }, + "node_modules/@jsdoc/salty": { + "version": "0.2.5", + "license": "Apache-2.0", + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, + "node_modules/@npmcli/fs": { + "version": "2.1.2", + "license": "ISC", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/fs/node_modules/semver": { + "version": "7.5.4", + "license": "ISC", + "optional": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@opentelemetry/api": { + "version": "1.6.0", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.3.1", + "license": "Apache-2.0", + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "license": "ISC" + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.2.2", + "license": "MIT", + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "license": "BSD-3-Clause" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/duplexify": { + "version": "3.6.3", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.41", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/firebase": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/firebase/-/firebase-3.2.1.tgz", + "integrity": "sha512-G8XgHMu2jHlElfc2xVNaYP50F0qrqeTCjgeG1v5b4SRwWG4XKC4fCuEdVZuZaMRmVygcnbRZBAo9O7RsDvmkGQ==", + "deprecated": "This is a stub types definition for Firebase API (https://www.firebase.com/docs/javascript/firebase). Firebase API provides its own type definitions, so you don't need @types/firebase installed!", + "dev": true, + "dependencies": { + "firebase": "*" + } + }, + "node_modules/@types/glob": { + "version": "8.1.0", + "license": "MIT", + "dependencies": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.11", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", + "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.14", + "license": "MIT" + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.5", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/linkify-it": { + "version": "3.0.4", + "license": "MIT" + }, + "node_modules/@types/long": { + "version": "4.0.2", + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "12.2.3", + "license": "MIT", + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.4", + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "3.0.4", + "license": "MIT" + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.8.10", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-fetch": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-bQVlnMLFJ2d35DkPNjEPmd9ueO/rh5EiaZt2bhqiSarPjZIuIV6bPQVqcrEyvNo+AfTrRGVazle1tl597w3gfA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/qs": { + "version": "6.9.10", + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "license": "MIT" + }, + "node_modules/@types/rimraf": { + "version": "3.0.2", + "license": "MIT", + "dependencies": { + "@types/glob": "*", + "@types/node": "*" + } + }, + "node_modules/@types/send": { + "version": "0.17.4", + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/send/node_modules/@types/mime": { + "version": "1.3.5", + "license": "MIT" + }, + "node_modules/@types/send/node_modules/@types/node": { + "version": "20.8.10", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.5", + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/triple-beam": { + "version": "1.3.4", + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "license": "ISC", + "optional": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.2", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "license": "MIT", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "license": "MIT", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv/node_modules/json-schema-traverse": { + "version": "0.4.1", + "license": "MIT" + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansi-styles/node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ansicolors": { + "version": "0.3.2", + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "license": "ISC", + "optional": true + }, + "node_modules/archiver": { + "version": "5.3.2", + "license": "MIT", + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.4", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver-utils/node_modules/isarray": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.8", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/archiver-utils/node_modules/safe-buffer": { + "version": "5.1.2", + "license": "MIT" + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "license": "Python-2.0" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/arrify": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/as-array": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/asn1": { + "version": "0.2.6", + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ast-types": { + "version": "0.13.4", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/async": { + "version": "3.2.4", + "license": "MIT" + }, + "node_modules/async-lock": { + "version": "1.3.2", + "license": "MIT" + }, + "node_modules/async-retry": { + "version": "1.3.3", + "license": "MIT", + "optional": true, + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "license": "MIT" + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.12.0", + "license": "MIT" + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth-connect": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "license": "MIT" + }, + "node_modules/basic-ftp": { + "version": "5.0.3", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.2", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/boxen": { + "version": "5.1.2", + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/type-fest": { + "version": "0.20.2", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "license": "MIT", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.1", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "16.1.3", + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "8.1.0", + "license": "ISC", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.18.3", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "5.1.6", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/call-bind": { + "version": "1.0.5", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/callsites": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001565", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/cardinal": { + "version": "2.1.1", + "license": "MIT", + "dependencies": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + }, + "bin": { + "cdl": "bin/cdl.js" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "license": "Apache-2.0" + }, + "node_modules/catharsis": { + "version": "0.9.0", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "license": "MIT" + }, + "node_modules/chokidar": { + "version": "3.5.3", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "dev": true, + "license": "MIT" + }, + "node_modules/cjson": { + "version": "0.3.3", + "license": "MIT", + "dependencies": { + "json-parse-helpfulerror": "^1.0.3" + }, + "engines": { + "node": ">= 0.3.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.1", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table": { + "version": "0.3.11", + "dependencies": { + "colors": "1.0.3" + }, + "engines": { + "node": ">= 0.2.0" + } + }, + "node_modules/cli-table3": { + "version": "0.6.3", + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/@colors/colors": { + "version": "1.5.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "license": "ISC", + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/co": { + "version": "4.6.0", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/color": { + "version": "3.2.1", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-convert/node_modules/color-name": { + "version": "1.1.3", + "license": "MIT" + }, + "node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "license": "ISC", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "license": "MIT" + }, + "node_modules/colors": { + "version": "1.0.3", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/colorspace": { + "version": "1.1.4", + "license": "MIT", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/compress-commons": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/bytes": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/config-chain": { + "version": "1.1.13", + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/configstore": { + "version": "5.0.1", + "license": "BSD-2-Clause", + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/connect": { + "version": "3.7.0", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/finalhandler": { + "version": "1.1.2", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/connect/node_modules/on-finished": { + "version": "2.3.0", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/connect/node_modules/statuses": { + "version": "1.5.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "license": "ISC", + "optional": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.5.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "license": "MIT" + }, + "node_modules/core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.3", + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-env": { + "version": "5.2.1", + "license": "MIT", + "dependencies": { + "cross-spawn": "^6.0.5" + }, + "bin": { + "cross-env": "dist/bin/cross-env.js", + "cross-env-shell": "dist/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/cross-env/node_modules/cross-spawn": { + "version": "6.0.5", + "license": "MIT", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/cross-env/node_modules/path-key": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/cross-env/node_modules/semver": { + "version": "5.7.2", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/cross-env/node_modules/shebang-command": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cross-env/node_modules/shebang-regex": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cross-env/node_modules/which": { + "version": "1.3.1", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/csv-parse": { + "version": "5.5.2", + "license": "MIT" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.1", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/dedent": { + "version": "1.5.1", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-freeze": { + "version": "0.0.1", + "license": "public domain" + }, + "node_modules/deep-is": { + "version": "0.1.4", + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "license": "MIT", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/degenerator/node_modules/escodegen": { + "version": "2.1.0", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "license": "MIT", + "optional": true + }, + "node_modules/depd": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dom-storage": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.1.0.tgz", + "integrity": "sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q==", + "engines": { + "node": "*" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "license": "MIT", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.598", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT" + }, + "node_modules/enabled": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/ent": { + "version": "2.2.0", + "license": "MIT", + "optional": true + }, + "node_modules/entities": { + "version": "2.1.0", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "license": "MIT", + "optional": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "1.14.3", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "4.3.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events-listener": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/execa": { + "version": "5.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exegesis": { + "version": "4.1.1", + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^9.0.3", + "ajv": "^8.3.0", + "ajv-formats": "^2.1.0", + "body-parser": "^1.18.3", + "content-type": "^1.0.4", + "deep-freeze": "0.0.1", + "events-listener": "^1.1.0", + "glob": "^7.1.3", + "json-ptr": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "lodash": "^4.17.11", + "openapi3-ts": "^3.1.1", + "promise-breaker": "^6.0.0", + "pump": "^3.0.0", + "qs": "^6.6.0", + "raw-body": "^2.3.3", + "semver": "^7.0.0" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">5.0.0" + } + }, + "node_modules/exegesis-express": { + "version": "4.0.0", + "license": "MIT", + "dependencies": { + "exegesis": "^4.1.0" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">5.0.0" + } + }, + "node_modules/exegesis/node_modules/ajv": { + "version": "8.12.0", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/exegesis/node_modules/ajv-formats": { + "version": "2.1.1", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/exegesis/node_modules/qs": { + "version": "6.11.2", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/exegesis/node_modules/semver": { + "version": "7.5.4", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/express": { + "version": "4.18.2", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/body-parser": { + "version": "1.20.1", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/express/node_modules/raw-body": { + "version": "2.5.1", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "license": "MIT" + }, + "node_modules/external-editor": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/external-editor/node_modules/tmp": { + "version": "0.0.33", + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "license": "MIT" + }, + "node_modules/fast-text-encoding": { + "version": "1.0.6", + "license": "Apache-2.0" + }, + "node_modules/fast-url-parser": { + "version": "1.1.3", + "license": "MIT", + "dependencies": { + "punycode": "^1.3.2" + } + }, + "node_modules/fast-url-parser/node_modules/punycode": { + "version": "1.4.1", + "license": "MIT" + }, + "node_modules/fast-xml-parser": { + "version": "4.3.2", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "license": "Apache-2.0", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fecha": { + "version": "4.2.3", + "license": "MIT" + }, + "node_modules/figures": { + "version": "3.2.0", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/filesize": { + "version": "6.4.0", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/firebase": { + "version": "8.10.1", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-8.10.1.tgz", + "integrity": "sha512-84z/zqF8Y5IpUYN8nREZ/bxbGtF5WJDOBy4y0hAxRzGpB5+2tw9PQgtTnUzk6MQiVEf/WOniMUL3pCVXKsxALw==", + "dependencies": { + "@firebase/analytics": "0.6.18", + "@firebase/app": "0.6.30", + "@firebase/app-check": "0.3.2", + "@firebase/app-types": "0.6.3", + "@firebase/auth": "0.16.8", + "@firebase/database": "0.11.0", + "@firebase/firestore": "2.4.1", + "@firebase/functions": "0.6.16", + "@firebase/installations": "0.4.32", + "@firebase/messaging": "0.8.0", + "@firebase/performance": "0.4.18", + "@firebase/polyfill": "0.3.36", + "@firebase/remote-config": "0.1.43", + "@firebase/storage": "0.7.1", + "@firebase/util": "1.3.0" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/firebase-admin": { + "version": "11.11.0", + "license": "Apache-2.0", + "dependencies": { + "@fastify/busboy": "^1.2.1", + "@firebase/database-compat": "^0.3.4", + "@firebase/database-types": "^0.10.4", + "@types/node": ">=12.12.47", + "jsonwebtoken": "^9.0.0", + "jwks-rsa": "^3.0.1", + "node-forge": "^1.3.1", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "@google-cloud/firestore": "^6.6.0", + "@google-cloud/storage": "^6.9.5" + } + }, + "node_modules/firebase-admin/node_modules/uuid": { + "version": "9.0.1", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/firebase-tools": { + "version": "12.9.1", + "license": "MIT", + "dependencies": { + "@google-cloud/pubsub": "^3.0.1", + "abort-controller": "^3.0.0", + "ajv": "^6.12.6", + "archiver": "^5.0.0", + "async-lock": "1.3.2", + "body-parser": "^1.19.0", + "chokidar": "^3.0.2", + "cjson": "^0.3.1", + "cli-table": "0.3.11", + "colorette": "^2.0.19", + "commander": "^4.0.1", + "configstore": "^5.0.1", + "cors": "^2.8.5", + "cross-env": "^5.1.3", + "cross-spawn": "^7.0.3", + "csv-parse": "^5.0.4", + "exegesis": "^4.1.0", + "exegesis-express": "^4.0.0", + "express": "^4.16.4", + "filesize": "^6.1.0", + "form-data": "^4.0.0", + "fs-extra": "^10.1.0", + "glob": "^7.1.2", + "google-auth-library": "^7.11.0", + "inquirer": "^8.2.0", + "js-yaml": "^3.13.1", + "jsonwebtoken": "^9.0.0", + "leven": "^3.1.0", + "libsodium-wrappers": "^0.7.10", + "lodash": "^4.17.21", + "marked": "^4.0.14", + "marked-terminal": "^5.1.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "morgan": "^1.10.0", + "node-fetch": "^2.6.7", + "open": "^6.3.0", + "ora": "^5.4.1", + "p-limit": "^3.0.1", + "portfinder": "^1.0.32", + "progress": "^2.0.3", + "proxy-agent": "^6.3.0", + "request": "^2.87.0", + "retry": "^0.13.1", + "rimraf": "^3.0.0", + "semver": "^7.5.2", + "stream-chain": "^2.2.4", + "stream-json": "^1.7.3", + "strip-ansi": "^6.0.1", + "superstatic": "^9.0.3", + "tar": "^6.1.11", + "tcp-port-used": "^1.0.2", + "tmp": "^0.2.1", + "triple-beam": "^1.3.0", + "universal-analytics": "^0.5.3", + "update-notifier-cjs": "^5.1.6", + "uuid": "^8.3.2", + "winston": "^3.0.0", + "winston-transport": "^4.4.0", + "ws": "^7.2.3" + }, + "bin": { + "firebase": "lib/bin/firebase.js" + }, + "engines": { + "node": ">=16.13.0 || >=18.0.0" + } + }, + "node_modules/firebase-tools/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/firebase-tools/node_modules/gaxios": { + "version": "4.3.3", + "license": "Apache-2.0", + "dependencies": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/firebase-tools/node_modules/gcp-metadata": { + "version": "4.3.1", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/firebase-tools/node_modules/google-auth-library": { + "version": "7.14.1", + "license": "Apache-2.0", + "dependencies": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/firebase-tools/node_modules/google-p12-pem": { + "version": "3.1.4", + "license": "MIT", + "dependencies": { + "node-forge": "^1.3.1" + }, + "bin": { + "gp12-pem": "build/src/bin/gp12-pem.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/firebase-tools/node_modules/gtoken": { + "version": "5.3.2", + "license": "MIT", + "dependencies": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/firebase-tools/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/firebase-tools/node_modules/semver": { + "version": "7.5.4", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/firebase/node_modules/@firebase/analytics": { + "version": "0.6.18", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.6.18.tgz", + "integrity": "sha512-FXNtYDxbs9ynPbzUVuG94BjFPOPpgJ7156660uvCBuKgoBCIVcNqKkJQQ7TH8384fqvGjbjdcgARY9jgAHbtog==", + "dependencies": { + "@firebase/analytics-types": "0.6.0", + "@firebase/component": "0.5.6", + "@firebase/installations": "0.4.32", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/firebase/node_modules/@firebase/app": { + "version": "0.6.30", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.30.tgz", + "integrity": "sha512-uAYEDXyK0mmpZ8hWQj5TNd7WVvfsU8PgsqKpGljbFBG/HhsH8KbcykWAAA+c1PqL7dt/dbt0Reh1y9zEdYzMhg==", + "dependencies": { + "@firebase/app-types": "0.6.3", + "@firebase/component": "0.5.6", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "dom-storage": "2.1.0", + "tslib": "^2.1.0", + "xmlhttprequest": "1.8.0" + } + }, + "node_modules/firebase/node_modules/@firebase/app-types": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.6.3.tgz", + "integrity": "sha512-/M13DPPati7FQHEQ9Minjk1HGLm/4K4gs9bR4rzLCWJg64yGtVC0zNg9gDpkw9yc2cvol/mNFxqTtd4geGrwdw==" + }, + "node_modules/firebase/node_modules/@firebase/auth-interop-types": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.6.tgz", + "integrity": "sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/firebase/node_modules/@firebase/component": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", + "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "dependencies": { + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, + "node_modules/firebase/node_modules/@firebase/database": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.11.0.tgz", + "integrity": "sha512-b/kwvCubr6G9coPlo48PbieBDln7ViFBHOGeVt/bt82yuv5jYZBEYAac/mtOVSxpf14aMo/tAN+Edl6SWqXApw==", + "dependencies": { + "@firebase/auth-interop-types": "0.1.6", + "@firebase/component": "0.5.6", + "@firebase/database-types": "0.8.0", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "faye-websocket": "0.11.3", + "tslib": "^2.1.0" + } + }, + "node_modules/firebase/node_modules/@firebase/database-types": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.8.0.tgz", + "integrity": "sha512-7IdjAFRfPWyG3b4wcXyghb3Y1CLCSJFZIg1xl5GbTVMttSQFT4B5NYdhsfA34JwAsv5pMzPpjOaS3/K9XJ2KiA==", + "dependencies": { + "@firebase/app-types": "0.6.3", + "@firebase/util": "1.3.0" + } + }, + "node_modules/firebase/node_modules/@firebase/installations": { + "version": "0.4.32", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.32.tgz", + "integrity": "sha512-K4UlED1Vrhd2rFQQJih+OgEj8OTtrtH4+Izkx7ip2bhXSc+unk8ZhnF69D0kmh7zjXAqEDJrmHs9O5fI3rV6Tw==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/installations-types": "0.3.4", + "@firebase/util": "1.3.0", + "idb": "3.0.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/firebase/node_modules/@firebase/logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", + "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" + }, + "node_modules/firebase/node_modules/@firebase/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", + "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/firebase/node_modules/faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/firebase/node_modules/idb": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", + "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" + }, + "node_modules/fn.name": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "license": "MIT", + "optional": true + }, + "node_modules/gauge": { + "version": "4.0.4", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gaxios": { + "version": "5.1.3", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/gcp-metadata": { + "version": "5.3.0", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^5.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-uri": { + "version": "6.0.2", + "license": "MIT", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.0", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/get-uri/node_modules/fs-extra": { + "version": "8.1.0", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/get-uri/node_modules/jsonfile": { + "version": "4.0.0", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/get-uri/node_modules/universalify": { + "version": "0.1.2", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-slash": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/glob-slasher": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "glob-slash": "^1.0.0", + "lodash.isobject": "^2.4.1", + "toxic": "^1.0.0" + } + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "license": "MIT", + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/google-auth-library": { + "version": "8.9.0", + "license": "Apache-2.0", + "dependencies": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^5.0.0", + "gcp-metadata": "^5.3.0", + "gtoken": "^6.1.0", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/google-gax": { + "version": "3.6.1", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "~1.8.0", + "@grpc/proto-loader": "^0.7.0", + "@types/long": "^4.0.0", + "@types/rimraf": "^3.0.2", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "fast-text-encoding": "^1.0.3", + "google-auth-library": "^8.0.2", + "is-stream-ended": "^0.1.4", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^1.0.0", + "protobufjs": "7.2.4", + "protobufjs-cli": "1.1.1", + "retry-request": "^5.0.0" + }, + "bin": { + "compileProtos": "build/tools/compileProtos.js", + "minifyProtoJson": "build/tools/minify.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/google-p12-pem": { + "version": "4.0.1", + "license": "MIT", + "dependencies": { + "node-forge": "^1.3.1" + }, + "bin": { + "gp12-pem": "build/src/bin/gp12-pem.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "license": "ISC" + }, + "node_modules/gtoken": { + "version": "6.1.2", + "license": "MIT", + "dependencies": { + "gaxios": "^5.0.1", + "google-p12-pem": "^4.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "license": "ISC", + "optional": true + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/heap-js": { + "version": "2.3.0", + "license": "BSD-3-Clause", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "license": "MIT" + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", + "peer": true + }, + "node_modules/ieee754": { + "version": "1.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/import-lazy": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "license": "ISC", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "license": "ISC" + }, + "node_modules/inquirer": { + "version": "8.2.6", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/node_modules/wrap-ansi": { + "version": "6.2.0", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/install-artifact-from-github": { + "version": "1.3.3", + "license": "BSD-3-Clause", + "optional": true, + "bin": { + "install-from-cache": "bin/install-from-cache.js", + "save-to-github-cache": "bin/save-to-github-cache.js" + } + }, + "node_modules/ip": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/ip-regex": { + "version": "4.3.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-ci/node_modules/ci-info": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "license": "MIT", + "optional": true + }, + "node_modules/is-npm": { + "version": "5.0.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream-ended": { + "version": "0.1.4", + "license": "MIT" + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-url": { + "version": "1.2.4", + "license": "MIT" + }, + "node_modules/is-wsl": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-yarn-global": { + "version": "0.3.0", + "license": "MIT" + }, + "node_modules/is2": { + "version": "2.0.9", + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "ip-regex": "^4.1.0", + "is-url": "^1.2.4" + }, + "engines": { + "node": ">=v0.10.0" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "license": "ISC" + }, + "node_modules/isomorphic-fetch": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "license": "MIT" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.6", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jju": { + "version": "1.4.0", + "license": "MIT" + }, + "node_modules/join-path": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "as-array": "^2.0.0", + "url-join": "0.0.1", + "valid-url": "^1" + } + }, + "node_modules/jose": { + "version": "4.15.4", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "license": "Apache-2.0", + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "license": "MIT" + }, + "node_modules/jsdoc": { + "version": "4.0.2", + "license": "Apache-2.0", + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc/node_modules/@babel/parser": { + "version": "7.23.0", + "license": "MIT", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-helpfulerror": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "jju": "^1.1.0" + } + }, + "node_modules/json-ptr": { + "version": "3.1.1", + "license": "MIT" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "license": "ISC" + }, + "node_modules/json5": { + "version": "2.2.3", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/jwa": { + "version": "1.4.1", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/jws": { + "version": "3.2.2", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "7.5.4", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "license": "MIT", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jwa": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwks-rsa": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "@types/express": "^4.17.17", + "@types/jsonwebtoken": "^9.0.2", + "debug": "^4.3.4", + "jose": "^4.14.6", + "limiter": "^1.1.5", + "lru-memoizer": "^2.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/jws": { + "version": "4.0.0", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/klaw": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/kuler": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/lazystream": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/isarray": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "license": "MIT" + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/libsodium": { + "version": "0.7.13", + "license": "ISC" + }, + "node_modules/libsodium-wrappers": { + "version": "0.7.13", + "license": "ISC", + "dependencies": { + "libsodium": "^0.7.13" + } + }, + "node_modules/limiter": { + "version": "1.1.5" + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "dev": true, + "license": "MIT" + }, + "node_modules/linkify-it": { + "version": "3.0.3", + "license": "MIT", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "license": "MIT" + }, + "node_modules/lodash._objecttypes": { + "version": "2.4.1", + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "license": "MIT" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "license": "MIT" + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "license": "MIT" + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "license": "MIT" + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "license": "MIT" + }, + "node_modules/lodash.isobject": { + "version": "2.4.1", + "license": "MIT", + "dependencies": { + "lodash._objecttypes": "~2.4.1" + } + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "license": "MIT" + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "license": "MIT" + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/logform": { + "version": "2.6.0", + "license": "MIT", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/long": { + "version": "5.2.3", + "license": "Apache-2.0" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lru-memoizer": { + "version": "2.2.0", + "license": "MIT", + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "lru-cache": "~4.0.0" + } + }, + "node_modules/lru-memoizer/node_modules/lru-cache": { + "version": "4.0.2", + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.1", + "yallist": "^2.0.0" + } + }, + "node_modules/lru-memoizer/node_modules/yallist": { + "version": "2.1.2", + "license": "ISC" + }, + "node_modules/make-dir": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "license": "ISC", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/agent-base": { + "version": "6.0.2", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.18.3", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-fetch-happen/node_modules/socks-proxy-agent": { + "version": "7.0.0", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/markdown-it": { + "version": "12.3.2", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "license": "Unlicense", + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/marked-terminal": { + "version": "5.2.0", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^6.2.0", + "cardinal": "^2.1.1", + "chalk": "^5.2.0", + "cli-table3": "^0.6.3", + "node-emoji": "^1.11.0", + "supports-hyperlinks": "^2.3.0" + }, + "engines": { + "node": ">=14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "marked": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/marked-terminal/node_modules/ansi-escapes": { + "version": "6.2.0", + "license": "MIT", + "dependencies": { + "type-fest": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked-terminal/node_modules/chalk": { + "version": "5.3.0", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/marked-terminal/node_modules/type-fest": { + "version": "3.13.1", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/methods": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimatch/node_modules/brace-expansion": { + "version": "1.1.11", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "2.1.2", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/morgan": { + "version": "1.10.0", + "license": "MIT", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "license": "ISC" + }, + "node_modules/nan": { + "version": "2.18.0", + "license": "MIT", + "optional": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/netmask": { + "version": "2.0.2", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/nice-try": { + "version": "1.0.5", + "license": "MIT" + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-gyp": { + "version": "9.4.1", + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" + } + }, + "node_modules/node-gyp/node_modules/semver": { + "version": "7.5.4", + "license": "ISC", + "optional": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.13", + "dev": true, + "license": "MIT" + }, + "node_modules/nopt": { + "version": "6.0.0", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/one-time": { + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "fn.name": "1.x.x" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "6.4.0", + "license": "MIT", + "dependencies": { + "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/openapi3-ts": { + "version": "3.2.0", + "license": "MIT", + "dependencies": { + "yaml": "^2.2.1" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "license": "MIT", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-defer": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "license": "MIT", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pac-proxy-agent": { + "version": "7.0.1", + "license": "MIT", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "pac-resolver": "^7.0.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/http-proxy-agent": { + "version": "7.0.0", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.2", + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.0", + "license": "MIT", + "dependencies": { + "degenerator": "^5.0.0", + "ip": "^1.1.8", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver/node_modules/ip": { + "version": "1.1.8", + "license": "MIT" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "dev": true, + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "license": "MIT" + }, + "node_modules/performance-now": { + "version": "2.1.0", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/portfinder": { + "version": "1.0.32", + "license": "MIT", + "dependencies": { + "async": "^2.6.4", + "debug": "^3.2.7", + "mkdirp": "^0.5.6" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/async": { + "version": "2.6.4", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/portfinder/node_modules/mkdirp": { + "version": "0.5.6", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "license": "MIT" + }, + "node_modules/progress": { + "version": "2.0.3", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-breaker": { + "version": "6.0.0", + "license": "MIT" + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "license": "ISC", + "optional": true + }, + "node_modules/promise-polyfill": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz", + "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g==" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/promise-retry/node_modules/retry": { + "version": "0.12.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "license": "ISC" + }, + "node_modules/proto3-json-serializer": { + "version": "1.1.1", + "license": "Apache-2.0", + "dependencies": { + "protobufjs": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/protobufjs": { + "version": "7.2.4", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/protobufjs-cli": { + "version": "1.1.1", + "license": "BSD-3-Clause", + "dependencies": { + "chalk": "^4.0.0", + "escodegen": "^1.13.0", + "espree": "^9.0.0", + "estraverse": "^5.1.0", + "glob": "^8.0.0", + "jsdoc": "^4.0.0", + "minimist": "^1.2.0", + "semver": "^7.1.2", + "tmp": "^0.2.1", + "uglify-js": "^3.7.7" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "protobufjs": "^7.0.0" + } + }, + "node_modules/protobufjs-cli/node_modules/glob": { + "version": "8.1.0", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/protobufjs-cli/node_modules/minimatch": { + "version": "5.1.6", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/protobufjs-cli/node_modules/semver": { + "version": "7.5.4", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-agent": { + "version": "6.3.1", + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/http-proxy-agent": { + "version": "7.0.0", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.2", + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "license": "ISC" + }, + "node_modules/psl": { + "version": "1.9.0", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pupa": { + "version": "2.1.1", + "license": "MIT", + "dependencies": { + "escape-goat": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pure-rand": { + "version": "6.0.4", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.11.0", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/re2": { + "version": "1.20.5", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "install-artifact-from-github": "^1.3.3", + "nan": "^2.18.0", + "node-gyp": "^9.4.0" + } + }, + "node_modules/react-is": { + "version": "18.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/redeyed": { + "version": "2.1.1", + "license": "MIT", + "dependencies": { + "esprima": "~4.0.0" + } + }, + "node_modules/registry-auth-token": { + "version": "5.0.2", + "license": "MIT", + "dependencies": { + "@pnpm/npm-conf": "^2.1.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/registry-url": { + "version": "5.1.0", + "license": "MIT", + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/request": { + "version": "2.88.2", + "license": "Apache-2.0", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requizzle": { + "version": "0.2.4", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/retry-request": { + "version": "5.0.2", + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/router": { + "version": "1.3.8", + "license": "MIT", + "dependencies": { + "array-flatten": "3.0.0", + "debug": "2.6.9", + "methods": "~1.1.2", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "setprototypeof": "1.2.0", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/router/node_modules/array-flatten": { + "version": "3.0.0", + "license": "MIT" + }, + "node_modules/router/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/router/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/run-async": { + "version": "2.4.1", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-diff": { + "version": "3.1.1", + "license": "MIT", + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/send": { + "version": "0.18.0", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "license": "MIT", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "license": "ISC", + "optional": true + }, + "node_modules/set-function-length": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "license": "ISC" + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "license": "MIT" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "license": "MIT", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/sshpk": { + "version": "1.18.0", + "license": "MIT", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ssri": { + "version": "9.0.1", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stream-chain": { + "version": "2.2.5", + "license": "BSD-3-Clause" + }, + "node_modules/stream-events": { + "version": "1.0.5", + "license": "MIT", + "optional": true, + "dependencies": { + "stubs": "^3.0.0" + } + }, + "node_modules/stream-json": { + "version": "1.8.0", + "license": "BSD-3-Clause", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strnum": { + "version": "1.0.5", + "license": "MIT", + "optional": true + }, + "node_modules/stubs": { + "version": "3.0.0", + "license": "MIT", + "optional": true + }, + "node_modules/superstatic": { + "version": "9.0.3", + "license": "MIT", + "dependencies": { + "basic-auth-connect": "^1.0.0", + "commander": "^10.0.0", + "compression": "^1.7.0", + "connect": "^3.7.0", + "destroy": "^1.0.4", + "fast-url-parser": "^1.1.3", + "glob-slasher": "^1.0.1", + "is-url": "^1.2.2", + "join-path": "^1.1.1", + "lodash": "^4.17.19", + "mime-types": "^2.1.35", + "minimatch": "^6.1.6", + "morgan": "^1.8.2", + "on-finished": "^2.2.0", + "on-headers": "^1.0.0", + "path-to-regexp": "^1.8.0", + "router": "^1.3.1", + "update-notifier-cjs": "^5.1.6" + }, + "bin": { + "superstatic": "lib/bin/server.js" + }, + "engines": { + "node": "^14.18.0 || >=16.4.0" + }, + "optionalDependencies": { + "re2": "^1.17.7" + } + }, + "node_modules/superstatic/node_modules/commander": { + "version": "10.0.1", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/superstatic/node_modules/minimatch": { + "version": "6.2.0", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/superstatic/node_modules/path-to-regexp": { + "version": "1.8.0", + "license": "MIT", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar": { + "version": "6.2.0", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tcp-port-used": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "debug": "4.3.1", + "is2": "^2.0.6" + } + }, + "node_modules/tcp-port-used/node_modules/debug": { + "version": "4.3.1", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/tcp-port-used/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/teeny-request": { + "version": "8.0.3", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.1", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/teeny-request/node_modules/uuid": { + "version": "9.0.1", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-decoding": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/text-hex": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/through": { + "version": "2.3.8", + "license": "MIT" + }, + "node_modules/tmp": { + "version": "0.2.1", + "license": "MIT", + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/toxic": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.10" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "license": "MIT" + }, + "node_modules/triple-beam": { + "version": "1.4.1", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "license": "0BSD" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "license": "Unlicense" + }, + "node_modules/type-check": { + "version": "0.3.2", + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "license": "MIT" + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "license": "BSD-2-Clause", + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/underscore": { + "version": "1.13.6", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "5.26.5", + "license": "MIT" + }, + "node_modules/unique-filename": { + "version": "2.0.1", + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/unique-slug": { + "version": "3.0.0", + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universal-analytics": { + "version": "0.5.3", + "license": "MIT", + "dependencies": { + "debug": "^4.3.1", + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=12.18.2" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/update-notifier-cjs": { + "version": "5.1.6", + "license": "BSD-2-Clause", + "dependencies": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "isomorphic-fetch": "^3.0.0", + "pupa": "^2.1.1", + "registry-auth-token": "^5.0.1", + "registry-url": "^5.1.0", + "semver": "^7.3.7", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/update-notifier-cjs/node_modules/semver": { + "version": "7.5.4", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-join": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.2.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/valid-url": { + "version": "1.0.9" + }, + "node_modules/vary": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/verror/node_modules/extsprintf": { + "version": "1.4.1", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, + "node_modules/walker": { + "version": "1.0.8", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "license": "BSD-2-Clause" + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "license": "Apache-2.0", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.19", + "license": "MIT" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/winston": { + "version": "3.11.0", + "license": "MIT", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.6.0", + "license": "MIT", + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.9", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "license": "Apache-2.0" + }, + "node_modules/xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.3.4", + "license": "ISC", + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zip-stream": { + "version": "4.1.1", + "license": "MIT", + "dependencies": { + "archiver-utils": "^3.0.4", + "compress-commons": "^4.1.2", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/archiver-utils": { + "version": "3.0.4", + "license": "MIT", + "dependencies": { + "glob": "^7.2.3", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + } + } +} diff --git a/integration_test/package.json b/integration_test/package.json new file mode 100644 index 000000000..fbe878cde --- /dev/null +++ b/integration_test/package.json @@ -0,0 +1,26 @@ +{ + "name": "integration_test", + "module": "index.ts", + "type": "module", + "dependencies": { + "@firebase/analytics": "^0.10.0", + "firebase": "^8.2.3", + "firebase-admin": "^11.11.0", + "firebase-tools": "^12.9.1", + "js-yaml": "^4.1.0" + }, + "scripts": { + "copyfiles": "cp ./serviceAccount.json ./dist/serviceAccount.json", + "build": "tsc && npm run copyfiles", + "test": "jest", + "start": "npm run build && node dist/run.js" + }, + "devDependencies": { + "@types/firebase": "^3.2.1", + "@types/jest": "^29.5.11", + "@types/js-yaml": "^4.0.9", + "@types/node-fetch": "^2.6.9", + "jest": "^29.7.0", + "ts-jest": "^29.1.1" + } +} diff --git a/integration_test/run.ts b/integration_test/run.ts new file mode 100644 index 000000000..712d1c9a1 --- /dev/null +++ b/integration_test/run.ts @@ -0,0 +1,263 @@ +import path from "path"; +import fs from "fs"; +import yaml from "js-yaml"; +import { spawn } from "child_process"; +import { fileURLToPath } from "url"; +import portfinder from "portfinder"; +import client from "firebase-tools"; +import { getRuntimeDelegate } from "firebase-tools/lib/deploy/functions/runtimes/index.js"; +import { detectFromPort } from "firebase-tools/lib/deploy/functions/runtimes/discovery/index.js"; +import setup from "./setup.js"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +function loadEnv(): void { + try { + const envPath = path.resolve(process.cwd(), ".env"); + console.log("Loading .env file from", envPath); + const envFileContent = fs.readFileSync(envPath, "utf-8"); + envFileContent.split("\n").forEach((variable) => { + const [key, value] = variable.split("="); + if (key && value) process.env[key.trim()] = value.trim(); + }); + } catch (error: any) { + console.error("Error loading .env file:", error.message); + } +} + +loadEnv(); + +const { + NODE_VERSION = "18", + FIREBASE_ADMIN = "^10.0.0", + PROJECT_ID, + DATABASE_URL, + STORAGE_BUCKET, +} = process.env; +const TEST_RUN_ID = `t${Date.now()}`; + +if (!PROJECT_ID || !DATABASE_URL || !STORAGE_BUCKET) { + console.error("Required environment variables are not set. Exiting..."); + process.exit(1); +} + +setup(TEST_RUN_ID, NODE_VERSION, FIREBASE_ADMIN); + +const config = { + projectId: PROJECT_ID, + projectDir: process.cwd(), + sourceDir: `${process.cwd()}/functions`, + runtime: "nodejs18", +}; + +const firebaseConfig = { + databaseURL: DATABASE_URL, + projectId: PROJECT_ID, + storageBucket: STORAGE_BUCKET, +}; +const env = { + FIRESTORE_PREFER_REST: "true", + GCLOUD_PROJECT: config.projectId, + FIREBASE_CONFIG: JSON.stringify(firebaseConfig), +}; + +let modifiedYaml: any; + +function generateUniqueHash(originalName: string): string { + return `${TEST_RUN_ID}-${originalName}`; +} + +/** + * Discovers endpoints and modifies functions.yaml file. + * @returns A promise that resolves with a function to kill the server. + */ +async function discoverAndModifyEndpoints() { + console.log("Discovering endpoints..."); + try { + const port = await portfinder.getPortPromise({ port: 9000 }); + const delegate = await getRuntimeDelegate(config); + const killServer = await delegate.serveAdmin(port.toString(), {}, env); + + console.log("Started on port", port); + const originalYaml = await detectFromPort(port, config.projectId, config.runtime, 10000); + + modifiedYaml = { + ...originalYaml, + endpoints: Object.fromEntries( + Object.entries(originalYaml.endpoints).map(([key, value]) => { + const modifiedKey = generateUniqueHash(key); + const modifiedValue: any = value; + delete modifiedValue.project; + delete modifiedValue.runtime; + return [modifiedKey, modifiedValue]; + }) + ), + specVersion: "v1alpha1", + }; + + writeFunctionsYaml("./functions/functions.yaml", modifiedYaml); + + return killServer; + } catch (err) { + console.error("Error discovering endpoints. Exiting.", err); + process.exit(1); + } +} + +function writeFunctionsYaml(filePath: string, data: any): void { + try { + fs.writeFileSync(filePath, yaml.dump(data)); + } catch (err) { + console.error("Error writing functions.yaml. Exiting.", err); + process.exit(1); + } +} + +async function deployModifiedFunctions(): Promise { + console.log("Deploying functions with id:", TEST_RUN_ID); + try { + const targetNames = ["functions", "database", "firestore"]; + const options = { + targetNames, + project: config.projectId, + config: "./firebase.json", + debug: true, + nonInteractive: true, + force: true, + }; + + await client.deploy(options); + + console.log("Functions have been deployed successfully."); + } catch (err) { + console.error("Error deploying functions. Exiting.", err); + throw err; + } +} + +async function removeDeployedFunctions(functionNames: string[]): Promise { + console.log("Removing deployed functions..."); + + try { + const options = { + project: config.projectId, + config: "./firebase.json", + debug: true, + nonInteractive: true, + force: true, + }; + + console.log("Removing functions with id:", TEST_RUN_ID); + await client.functions.delete(functionNames, options); + + console.log("Deployed functions have been removed."); + } catch (err) { + console.error("Error removing deployed functions. Exiting.", err); + process.exit(1); + } +} + +function cleanFiles(): void { + console.log("Cleaning files..."); + const functionsDir = "functions"; + process.chdir(functionsDir); // go to functions + try { + const files = fs.readdirSync("."); + files.forEach((file) => { + if (file.match(`firebase-functions-${TEST_RUN_ID}.tgz`)) { + fs.rmSync(file); + } + if (file.match("package.json")) { + fs.rmSync(file); + } + if (file.match("firebase-debug.log")) { + fs.rmSync(file); + } + if (file.match("functions.yaml")) { + fs.rmSync(file); + } + }); + + fs.rmSync("lib", { recursive: true }); + // fs.existsSync("node_modules") && fs.rmSync("node_modules", { recursive: true }); + } catch (error) { + console.error("Error occurred while cleaning files:", error); + } + + process.chdir("../"); // go back to integration_test +} + +const spawnAsync = (command: string, args: string[], options: any): Promise => { + return new Promise((resolve, reject) => { + const child = spawn(command, args, options); + + let output = ""; + if (child.stdout) { + child.stdout.on("data", (data) => { + output += data.toString(); + }); + } + + child.on("error", reject); + + child.on("close", (code) => { + if (code === 0) { + resolve(output); + } else { + reject(new Error(`Command failed with exit code ${code}`)); + } + }); + }); +}; + +async function runTests(): Promise { + try { + console.log("Starting Node.js Tests..."); + const output = await spawnAsync("npm", ["test"], { + env: { + ...process.env, + GOOGLE_APPLICATION_CREDENTIALS: path.join(__dirname, "serviceAccount.json"), + TEST_RUN_ID, + }, + stdio: "inherit", + }); + console.log(output); + console.log("Node.js Tests Completed."); + } catch (error) { + console.error("Error during testing:", error); + } +} + +async function handleCleanUp(): Promise { + console.log("Cleaning up..."); + if (modifiedYaml) { + const endpoints = Object.keys(modifiedYaml.endpoints); + await removeDeployedFunctions(endpoints); + } + cleanFiles(); +} + +async function gracefulShutdown(): Promise { + console.log("SIGINT received..."); + await handleCleanUp(); + process.exit(1); +} + +async function runIntegrationTests(): Promise { + process.on("SIGINT", gracefulShutdown); + + try { + const killServer = await discoverAndModifyEndpoints(); + await deployModifiedFunctions(); + await killServer(); + await runTests(); + } catch (err) { + console.error("Error occurred during integration tests", err); + } finally { + await handleCleanUp(); + } +} + +runIntegrationTests() + .then(() => console.log("Integration tests completed")) + .catch((error) => console.error("An error occurred during integration tests", error)); diff --git a/integration_test/run_tests.sh b/integration_test/run_tests.sh deleted file mode 100755 index 681d2dc1e..000000000 --- a/integration_test/run_tests.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env bash - -# Exit immediately if a command exits with a non-zero status. -set -e - -PROJECT_ID="${GCLOUD_PROJECT}" -TIMESTAMP=$(date +%s) - -if [[ "${PROJECT_ID}" == "" ]]; then - echo "process.env.GCLOUD_PROJECT cannot be empty" - exit 1 -fi - -# Directory where this script lives. -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -function announce { - echo -e "\n\n##### $1" -} - -function build_sdk { - announce "Building SDK..." - cd "${DIR}/.." - rm -f firebase-functions-*.tgz - npm run build:pack - mv firebase-functions-*.tgz "integration_test/functions/firebase-functions-${TIMESTAMP}.tgz" -} - -# Creates a Package.json from package.json.template -# @param timestmap of the current SDK build -# @param Node version to test under -function create_package_json { - cd "${DIR}" - cp package.json.template functions/package.json - # we have to do the -e flag here so that it work both on linux and mac os, but that creates an extra - # backup file called package.json-e that we should clean up afterwards. - sed -i -e "s/__SDK_TARBALL__/firebase-functions-$1.tgz/g" functions/package.json - sed -i -e "s/__NODE_VERSION__/$2/g" functions/package.json - sed -i -e "s/__FIREBASE_ADMIN__/$3/g" functions/package.json - rm -f functions/package.json-e -} - -function install_deps { - announce "Installing dependencies..." - cd "${DIR}/functions" - rm -rf node_modules/firebase-functions - npm install -} - -function delete_all_functions { - announce "Deleting all functions in project..." - cd "${DIR}" - # Try to delete, if there are errors it is because the project is already empty, - # in that case do nothing. - firebase functions:delete integrationTests v1 v2 --force --project=$PROJECT_ID || : & - wait - announce "Project emptied." -} - -function deploy { - # Deploy functions, and security rules for database and Firestore. If the deploy fails, retry twice - for i in 1 2; do firebase deploy --project="${PROJECT_ID}" --only functions,database,firestore && break; done -} - -function run_tests { - announce "Running integration tests..." - - # Construct the URL for the test function. This may change in the future, - # causing this script to start failing, but currently we don't have a very - # reliable way of determining the URL dynamically. - TEST_DOMAIN="cloudfunctions.net" - if [[ "${FIREBASE_FUNCTIONS_TEST_REGION}" == "" ]]; then - FIREBASE_FUNCTIONS_TEST_REGION="us-central1" - fi - TEST_URL="https://${FIREBASE_FUNCTIONS_TEST_REGION}-${PROJECT_ID}.${TEST_DOMAIN}/integrationTests" - echo "${TEST_URL}" - - curl --fail -H "Authorization: Bearer $(gcloud auth print-identity-token)" "${TEST_URL}" -} - -function cleanup { - announce "Performing cleanup..." - delete_all_functions - rm "${DIR}/functions/firebase-functions-${TIMESTAMP}.tgz" - rm "${DIR}/functions/package.json" - rm -f "${DIR}/functions/firebase-debug.log" - rm -rf "${DIR}/functions/lib" - rm -rf "${DIR}/functions/node_modules" -} - -# Setup -build_sdk -delete_all_functions - -for version in 14 16; do - create_package_json $TIMESTAMP $version "^10.0.0" - install_deps - announce "Re-deploying the same functions to Node $version runtime ..." - deploy - run_tests -done - -# Cleanup -cleanup -announce "All tests pass!" diff --git a/integration_test/setup.ts b/integration_test/setup.ts new file mode 100644 index 000000000..95a0876e7 --- /dev/null +++ b/integration_test/setup.ts @@ -0,0 +1,87 @@ +import { execSync } from "child_process"; +import fs from "fs"; +import path from "path"; + +const DIR = process.cwd(); + +/** + * Build SDK, and Functions + */ +export default function setup(testRunId: string, nodeVersion: string, firebaseAdmin: string) { + buildSdk(testRunId); + createPackageJson(testRunId, nodeVersion, firebaseAdmin); + installDependencies(); + buildFunctions(); +} + +function buildSdk(testRunId: string) { + console.log("Building SDK..."); + process.chdir(path.join(DIR, "..")); // go up to root + + // remove existing firebase-functions-*.tgz files + const files = fs.readdirSync("."); + files.forEach((file) => { + if (file.match(/^firebase-functions-.*\.tgz$/)) { + fs.rmSync(file); + } + }); + // build the package + execSync("npm run build:pack", { stdio: "inherit" }); + + // move the generated tarball package to functions + const generatedFile = fs + .readdirSync(".") + .find((file) => file.match(/^firebase-functions-.*\.tgz$/)); + + if (generatedFile) { + const targetPath = path.join( + "integration_test", + "functions", + `firebase-functions-${testRunId}.tgz` + ); + fs.renameSync(generatedFile, targetPath); + console.log("SDK moved to", targetPath); + } + + process.chdir(DIR); // go back to integration_test +} + +function createPackageJson(testRunId: string, nodeVersion: string, firebaseAdmin: string) { + console.log("Creating package.json..."); + const packageJsonTemplatePath = `${DIR}/package.json.template`; + const packageJsonPath = `${DIR}/functions/package.json`; + + fs.copyFileSync(packageJsonTemplatePath, packageJsonPath); + + let packageJsonContent = fs.readFileSync(packageJsonPath, "utf8"); + packageJsonContent = packageJsonContent.replace( + /__SDK_TARBALL__/g, + `firebase-functions-${testRunId}.tgz` + ); + packageJsonContent = packageJsonContent.replace(/__NODE_VERSION__/g, nodeVersion); + packageJsonContent = packageJsonContent.replace(/__FIREBASE_ADMIN__/g, firebaseAdmin); + + fs.writeFileSync(packageJsonPath, packageJsonContent); +} + +function installDependencies() { + console.log("Installing dependencies..."); + const functionsDir = "functions"; + process.chdir(functionsDir); // go to functions + + const modulePath = path.join("node_modules", "firebase-functions"); + if (fs.existsSync(modulePath)) { + execSync(`rm -rf ${modulePath}`, { stdio: "inherit" }); + } + + execSync("npm install", { stdio: "inherit" }); + process.chdir("../"); // go back to integration_test +} + +function buildFunctions() { + console.log("Building functions..."); + process.chdir(path.join(DIR, "functions")); // go to functions + + execSync("npm run build", { stdio: "inherit" }); + process.chdir(DIR); // go back to integration_test +} diff --git a/integration_test/tests/firebaseSetup.ts b/integration_test/tests/firebaseSetup.ts new file mode 100644 index 000000000..7d0ce39dc --- /dev/null +++ b/integration_test/tests/firebaseSetup.ts @@ -0,0 +1,28 @@ +import * as admin from "firebase-admin"; +import "@firebase/analytics"; +import { cert } from "firebase-admin/app"; + +/** + * Initializes Firebase Admin SDK. + */ +export async function initializeFirebase(): Promise { + if (admin.apps.length === 0) { + try { + const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; + if (!serviceAccountPath) { + throw new Error("Environment configured incorrectly."); + } + const serviceAccount = await import(serviceAccountPath); + const app = admin.initializeApp({ + credential: cert(serviceAccount), + databaseURL: process.env.DATABASE_URL, + storageBucket: process.env.STORAGE_BUCKET, + projectId: process.env.PROJECT_ID, + }); + return app; + } catch (error) { + console.error("Error initializing Firebase:", error); + } + } + return admin.app(); +} diff --git a/integration_test/tests/globalTeardown.ts b/integration_test/tests/globalTeardown.ts new file mode 100644 index 000000000..88615a43c --- /dev/null +++ b/integration_test/tests/globalTeardown.ts @@ -0,0 +1,69 @@ +import * as admin from "firebase-admin"; +import { initializeFirebase } from "./firebaseSetup"; + +async function deleteCollection( + db: admin.firestore.Firestore, + collectionPath: string, + batchSize: number +) { + const collectionRef = db.collection(collectionPath); + const query = collectionRef.orderBy("__name__").limit(batchSize); + + return new Promise((resolve, reject) => { + deleteQueryBatch(db, query, batchSize, resolve, reject).then(resolve).catch(reject); + }); +} + +async function deleteQueryBatch( + db: admin.firestore.Firestore, + query: admin.firestore.Query, + batchSize: number, + resolve: (value?: unknown) => void, + reject: (reason: any) => void +): Promise { + try { + const snapshot = await query.get(); + + if (snapshot.size === 0) { + resolve(); + return; + } + + const batch = db.batch(); + snapshot.docs.forEach((doc) => { + batch.delete(doc.ref); + }); + + await batch.commit(); + + process.nextTick(() => deleteQueryBatch(db, query, batchSize, resolve, reject)); + } catch (error) { + reject(error); + } +} + +export default async () => { + await initializeFirebase(); + + try { + // TODO: Only delete resources created by this test run. + // const db = admin.firestore(); + // await Promise.all([ + // deleteCollection(db, "userProfiles", 100), + // deleteCollection(db, "createUserTests", 100), + // deleteCollection(db, "deleteUserTests", 100), + // deleteCollection(db, "databaseOnWriteTests", 100), + // deleteCollection(db, "firestoreOnCreateTests", 100), + // deleteCollection(db, "firestoreOnUpdateTests", 100), + // deleteCollection(db, "firestoreOnDeleteTests", 100), + // deleteCollection(db, "httpsOnCallTests", 100), + // deleteCollection(db, "pubsubOnPublishTests", 100), + // deleteCollection(db, "pubsubScheduleTests", 100), + // deleteCollection(db, "tests", 100), + // ]); + } catch (error) { + console.error("Error in global teardown:", error); + } + + await admin.app().delete(); +}; diff --git a/integration_test/tests/utils.ts b/integration_test/tests/utils.ts new file mode 100644 index 000000000..367d17239 --- /dev/null +++ b/integration_test/tests/utils.ts @@ -0,0 +1 @@ +export const timeout = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); diff --git a/integration_test/tests/v1/analytics.test.ts b/integration_test/tests/v1/analytics.test.ts new file mode 100644 index 000000000..3c244abca --- /dev/null +++ b/integration_test/tests/v1/analytics.test.ts @@ -0,0 +1,51 @@ +import admin from "firebase-admin"; +import firebase from "firebase/app"; +import { timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; + +describe("Firebase Analytics event onLog trigger", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + await initializeFirebase(); + const analytics = firebase.analytics(); + await analytics.logEvent("in_app_purchase", { testId }); + await timeout(20000); + const logSnapshot = await admin.firestore().collection("analyticsEventTests").doc(testId).get(); + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should not include path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.analytics.event.onlog"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); +}); diff --git a/integration_test/tests/v1/auth.test.ts b/integration_test/tests/v1/auth.test.ts new file mode 100644 index 000000000..8e7ec1884 --- /dev/null +++ b/integration_test/tests/v1/auth.test.ts @@ -0,0 +1,222 @@ +import admin from "firebase-admin"; +import { timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; +import { UserRecord } from "firebase-admin/lib/auth/user-record"; + +describe("Firebase Auth", () => { + describe("user onCreate trigger", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + let userRecord: UserRecord; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + await initializeFirebase(); + + userRecord = await admin.auth().createUser({ + email: `${testId}@fake.com`, + password: "secret", + displayName: `${testId}`, + }); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("authUserOnCreateTests") + .doc(userRecord.uid) + .get(); + + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + await admin.auth().deleteUser(userRecord.uid); + }); + + it("should perform expected actions", async () => { + const userProfile = await admin + .firestore() + .collection("userProfiles") + .doc(userRecord.uid) + .get(); + expect(userProfile.exists).toBeTruthy(); + }); + + it("should have a project as resource", () => { + expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); + }); + + it("should not have a path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.auth.user.create"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have auth", () => { + expect(loggedContext?.auth).toBeUndefined(); + }); + + it("should not have an action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + + it("should have properly defined metadata", () => { + const parsedMetadata = JSON.parse(loggedContext?.metadata); + // TODO: better handle date format mismatch and precision + const expectedCreationTime = new Date(userRecord.metadata.creationTime) + .toISOString() + .replace(/\.\d{3}/, ""); + const expectedMetadata = { + ...userRecord.metadata, + creationTime: expectedCreationTime, + }; + + expect(expectedMetadata).toEqual(expect.objectContaining(parsedMetadata)); + }); + }); + + describe("user onDelete trigger", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + let userRecord: UserRecord; + let logSnapshot; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + await initializeFirebase(); + + userRecord = await admin.auth().createUser({ + email: `${testId}@fake.com`, + password: "secret", + displayName: `${testId}`, + }); + await admin.auth().deleteUser(userRecord.uid); + + await timeout(20000); + + logSnapshot = await admin + .firestore() + .collection("authUserOnDeleteTests") + .doc(userRecord.uid) + .get(); + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have a project as resource", () => { + expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); + }); + + it("should not have a path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the correct eventType", async () => { + expect(loggedContext?.eventType).toEqual("google.firebase.auth.user.delete"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have auth", () => { + expect(loggedContext?.auth).toBeUndefined(); + }); + + it("should not have an action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + }); + + describe("user beforeCreate trigger", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + let userRecord; + let loggedContext; + + beforeAll(async () => { + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + await initializeFirebase(); + userRecord = await admin.auth().createUser({ + email: `${testId}@fake.com`, + password: "secret", + displayName: `${testId}`, + }); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("userBeforeCreateTests") + .doc(userRecord.uid) + .get(); + + loggedContext = logSnapshot.data(); + }); + + afterAll(async () => { + await admin.auth().deleteUser(userRecord.uid); + }); + + it("should have a project as resource", () => { + expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); + }); + + it("should not have a path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the correct eventType", async () => { + expect(loggedContext?.eventType).toEqual("google.firebase.auth.user.beforeCreate"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have auth", () => { + expect(loggedContext?.auth).toBeUndefined(); + }); + + it("should not have an action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + }); +}); diff --git a/integration_test/tests/v1/database.test.ts b/integration_test/tests/v1/database.test.ts new file mode 100644 index 000000000..564f4face --- /dev/null +++ b/integration_test/tests/v1/database.test.ts @@ -0,0 +1,87 @@ +import admin from "firebase-admin"; +import { timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; +import { Reference } from "@firebase/database-types"; + +describe("Firebase Database ref onWrite trigger", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + await initializeFirebase(); + + ref = admin.database().ref(`dbTests/${testId}/start`); + await ref.set({ ".sv": "timestamp" }); + await timeout(20000); + const logSnapshot = await admin + .firestore() + .collection("databaseRefOnWriteTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + await ref.parent?.remove(); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + await ref.parent?.child("adminOnly").update({ allowed: 1 }); + + // Retrieve the updated data to verify the update operation + const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); + const adminData = adminDataSnapshot?.val(); + + expect(adminData).toEqual({ allowed: 1 }); + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch( + new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests`) + ); + expect(loggedContext?.url).toMatch(/\/start$/); + }); + + it("should have refs resources", () => + expect(loggedContext?.resource.name).toMatch( + new RegExp(`^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$`) + )); + + it("should not include path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.write"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + + it("should have admin authType", () => { + expect(loggedContext?.authType).toEqual("ADMIN"); + }); +}); diff --git a/integration_test/tests/v1/firestore.test.ts b/integration_test/tests/v1/firestore.test.ts new file mode 100644 index 000000000..858e0730a --- /dev/null +++ b/integration_test/tests/v1/firestore.test.ts @@ -0,0 +1,67 @@ +import admin from "firebase-admin"; +import { timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; + +describe("Firestore document onCreate trigger", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + await initializeFirebase(); + + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({ test: testId }); + dataSnapshot = await docRef.get(); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("firestoreDocumentOnCreateTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + const result = await docRef.set({ allowed: 1 }, { merge: true }); + expect(result).toBeTruthy(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.resource.name).toMatch( + `projects/${projectId}/databases/(default)/documents/tests/${testId}` + ); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firestore.document.create"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should have the correct data", () => { + expect(dataSnapshot.data()).toEqual({ test: testId }); + }); +}); diff --git a/integration_test/tests/v1/https.test.ts b/integration_test/tests/v1/https.test.ts new file mode 100644 index 000000000..4ab3c6046 --- /dev/null +++ b/integration_test/tests/v1/https.test.ts @@ -0,0 +1,55 @@ +import admin from "firebase-admin"; +import { initializeFirebase } from "../firebaseSetup"; +import { timeout } from "../utils"; +import fetch from "node-fetch"; + +// TODO: Temporarily disable - doesn't work unless running on projects w/ permission to create public functions. +// describe("HTTP onCall trigger", () => { +// const projectId = process.env.PROJECT_ID; +// const testId = process.env.TEST_RUN_ID; +// const region = process.env.REGION; +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// if (!testId || !projectId || !region) { +// throw new Error("Environment configured incorrectly."); +// } +// await initializeFirebase(); + +// const accessToken = await admin.credential.applicationDefault().getAccessToken(); +// const data = { foo: "bar", testId }; +// const response = await fetch( +// `https://${region}-${projectId}.cloudfunctions.net/${testId}-v2-callableTests`, +// { +// method: "POST", +// headers: { +// "Content-Type": "application/json", +// Authorization: `Bearer ${accessToken.access_token}`, +// }, +// body: JSON.stringify({ data }), +// } +// ); +// if (!response.ok) { +// throw new Error(response.statusText); +// } + +// await timeout(20000); + +// const logSnapshot = await admin.firestore().collection("httpsOnCallTests").doc(testId).get(); +// loggedContext = logSnapshot.data(); + +// if (!loggedContext) { +// throw new Error("loggedContext is undefined"); +// } +// }); + +// it("should have the correct data", () => { +// expect(loggedContext?.foo).toEqual("bar"); +// }); +// }); + +describe("HTTP onCall trigger (DISABLED)", () => { + it("should be disabled", () => { + expect(true).toBeTruthy(); + }); +}); diff --git a/integration_test/tests/v1/pubsub.test.ts b/integration_test/tests/v1/pubsub.test.ts new file mode 100644 index 000000000..5d677debb --- /dev/null +++ b/integration_test/tests/v1/pubsub.test.ts @@ -0,0 +1,115 @@ +import admin from "firebase-admin"; +import { timeout } from "../utils"; +import { PubSub } from "@google-cloud/pubsub"; +// import fetch from "node-fetch"; +import { initializeFirebase } from "../firebaseSetup"; + +describe("Pub/Sub onPublish trigger", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + if (!testId || !projectId || !serviceAccountPath) { + throw new Error("Environment configured incorrectly."); + } + + await initializeFirebase(); + + const serviceAccount = await import(serviceAccountPath); + const topic = new PubSub({ + credentials: serviceAccount.default, + projectId, + }).topic("pubsubTests"); + + await topic.publish(Buffer.from(JSON.stringify({ testId }))); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("pubsubOnPublishTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have a topic as resource", () => { + expect(loggedContext?.resource.name).toEqual( + `projects/${process.env.PROJECT_ID}/topics/pubsubTests` + ); + }); + + it("should not have a path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual("google.pubsub.topic.publish"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + + it("should have admin auth", () => { + expect(loggedContext?.auth).toBeUndefined(); + }); + + it("should have pubsub data", () => { + const decodedMessage = JSON.parse(loggedContext?.message); + const decoded = new Buffer(decodedMessage.data, "base64").toString(); + const parsed = JSON.parse(decoded); + expect(parsed.testId).toEqual(testId); + }); +}); + +// TODO: Uncomment this test when solution for test id access in scheduler. +// describe("Pub/Sub schedule trigger", () => { +// const testRunId = process.env.TEST_RUN_ID; +// let loggedContext; +// let logSnapshot; + +// beforeAll(async () => { +// try { +// await initializeFirebase(); +// const accessToken = await admin.credential.applicationDefault().getAccessToken(); +// const response = await fetch( +// `https://cloudscheduler.googleapis.com/v1/projects/${process.env.PROJECT_ID}/locations/${process.env.REGION}/jobs/firebase-schedule-${testRunId}-v1-schedule-${process.env.REGION}:run`, +// { +// method: "POST", +// headers: { +// "Content-Type": "application/json", +// Authorization: `Bearer ${accessToken.access_token}`, +// }, +// } +// ); +// if (!response.ok) { +// throw new Error(`Failed request with status ${response.status}!`); +// } + +// await timeout(15000); +// logSnapshot = await admin.firestore().collection("pubsubScheduleTests").doc(testRunId).get(); +// loggedContext = logSnapshot.data(); +// } catch (error) { +// console.error("Error in beforeAll:", error); +// throw error; +// } +// }); + +// it("should have been called", () => { +// expect(loggedContext).toBeDefined(); +// }); +// }); diff --git a/integration_test/tests/v1/remoteConfig.test.ts b/integration_test/tests/v1/remoteConfig.test.ts new file mode 100644 index 000000000..26e4e65bb --- /dev/null +++ b/integration_test/tests/v1/remoteConfig.test.ts @@ -0,0 +1,65 @@ +import admin from "firebase-admin"; +import { timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; +import fetch from "node-fetch"; + +describe("Firebase Remote Config onUpdate trigger", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + await initializeFirebase(); + + const accessToken = await admin.credential.applicationDefault().getAccessToken(); + const resp = await fetch( + `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/remoteConfig`, + { + method: "PUT", + headers: { + Authorization: `Bearer ${accessToken.access_token}`, + "Content-Type": "application/json; UTF-8", + "Accept-Encoding": "gzip", + "If-Match": "*", + }, + body: JSON.stringify({ version: { description: testId } }), + } + ); + if (!resp.ok) { + throw new Error(resp.statusText); + } + await timeout(20000); + const logSnapshot = await admin + .firestore() + .collection("remoteConfigOnUpdateTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have refs resources", () => + expect(loggedContext?.resource.name).toMatch(`projects/${process.env.PROJECT_ID}`)); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.remoteconfig.update"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have auth", () => { + expect(loggedContext?.auth).toBeUndefined(); + }); +}); diff --git a/integration_test/tests/v1/storage.test.ts b/integration_test/tests/v1/storage.test.ts new file mode 100644 index 000000000..7ba440e38 --- /dev/null +++ b/integration_test/tests/v1/storage.test.ts @@ -0,0 +1,71 @@ +import * as admin from "firebase-admin"; +import { timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; + +async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { + const bucket = admin.storage().bucket(); + + const file = bucket.file(fileName); + await file.save(buffer, { + metadata: { + contentType: "text/plain", + }, + }); +} + +describe("Firebase Storage object onFinalize trigger", () => { + const testId = process.env.TEST_RUN_ID; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + if (!testId) { + throw new Error("Environment configured incorrectly."); + } + + await initializeFirebase(); + + const testContent = testId; + const buffer = Buffer.from(testContent, "utf-8"); + + await uploadBufferToFirebase(buffer, testId + ".txt"); + + await timeout(20000); + const logSnapshot = await admin + .firestore() + .collection("storageOnFinalizeTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + + const [exists] = await file.exists(); + if (exists) { + await file.delete(); + } + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.storage.object.finalize"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); +}); diff --git a/integration_test/functions/src/v1/testLab-utils.ts b/integration_test/tests/v1/testLab.test.ts similarity index 58% rename from integration_test/functions/src/v1/testLab-utils.ts rename to integration_test/tests/v1/testLab.test.ts index 7ba32e112..ee931163b 100644 --- a/integration_test/functions/src/v1/testLab-utils.ts +++ b/integration_test/tests/v1/testLab.test.ts @@ -1,4 +1,6 @@ -import * as admin from "firebase-admin"; +import admin from "firebase-admin"; +import { timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; import fetch from "node-fetch"; interface AndroidDevice { @@ -10,25 +12,17 @@ interface AndroidDevice { const TESTING_API_SERVICE_NAME = "testing.googleapis.com"; -/** - * Creates a new TestMatrix in Test Lab which is expected to be rejected as - * invalid. - * - * @param projectId Project for which the test run will be created - * @param testId Test id which will be encoded in client info details - * @param accessToken accessToken to attach to requested for authentication - */ export async function startTestRun(projectId: string, testId: string, accessToken: string) { const device = await fetchDefaultDevice(accessToken); return await createTestMatrix(accessToken, projectId, testId, device); } -async function fetchDefaultDevice(accessToken: string): Promise { +async function fetchDefaultDevice(accessToken: string) { const resp = await fetch( `https://${TESTING_API_SERVICE_NAME}/v1/testEnvironmentCatalog/ANDROID`, { headers: { - Authorization: "Bearer " + accessToken, + Authorization: `Bearer ${accessToken}`, "Content-Type": "application/json", }, } @@ -39,7 +33,7 @@ async function fetchDefaultDevice(accessToken: string): Promise { const data = await resp.json(); const models = data?.androidDeviceCatalog?.models || []; const defaultModels = models.filter( - (m) => + (m: any) => m.tags !== undefined && m.tags.indexOf("default") > -1 && m.supportedVersionIds !== undefined && @@ -99,7 +93,7 @@ async function createTestMatrix( { method: "POST", headers: { - Authorization: "Bearer " + accessToken, + Authorization: `Bearer ${accessToken}`, "Content-Type": "application/json", }, body: JSON.stringify(body), @@ -110,3 +104,49 @@ async function createTestMatrix( } return; } + +describe("TestLab test matrix onComplete trigger", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + await initializeFirebase(); + + const accessToken = await admin.credential.applicationDefault().getAccessToken(); + await startTestRun(projectId, testId, accessToken.access_token); + await timeout(20000); + const logSnapshot = await admin + .firestore() + .collection("testLabOnCompleteTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.testing.testMatrix.complete"); + }); + + it("should be in state 'INVALID'", () => { + const matrix = JSON.parse(loggedContext?.matrix); + expect(matrix?.state).toEqual("INVALID"); + }); +}); + +// describe("Firebase TestLab onComplete trigger", () => { +// test("should have refs resources", async () => { +// console.log("test"); +// }); +// }); diff --git a/integration_test/tests/v2/https.test.ts b/integration_test/tests/v2/https.test.ts new file mode 100644 index 000000000..ab4b8b6ec --- /dev/null +++ b/integration_test/tests/v2/https.test.ts @@ -0,0 +1,54 @@ +import admin from "firebase-admin"; +import fetch from "node-fetch"; +import { timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; + +// describe("HTTPS onCall trigger", () => { +// const projectId = process.env.PROJECT_ID; +// const region = process.env.REGION; +// const testId = process.env.TEST_RUN_ID; +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// if (!testId || !projectId || !region) { +// throw new Error("Environment configured incorrectly."); +// } +// await initializeFirebase(); + +// const accessToken = await admin.credential.applicationDefault().getAccessToken(); +// const data = { foo: "bar", testId }; +// const response = await fetch( +// `https://${region}-${projectId}.cloudfunctions.net/${testId}-v2-callableTests`, +// { +// method: "POST", +// headers: { +// "Content-Type": "application/json", +// Authorization: `Bearer ${accessToken.access_token}`, +// }, +// body: JSON.stringify({ data }), +// } +// ); +// if (!response.ok) { +// throw new Error(response.statusText); +// } + +// await timeout(15000); + +// const logSnapshot = await admin.firestore().collection("httpsOnCallV2Tests").doc(testId).get(); +// loggedContext = logSnapshot.data(); + +// if (!loggedContext) { +// throw new Error("loggedContext is undefined"); +// } +// }); + +// it("should have the correct data", () => { +// expect(loggedContext?.foo).toMatch("bar"); +// }); +// }); + +describe("HTTP onCall trigger (DISABLED)", () => { + it("should be disabled", () => { + expect(true).toBeTruthy(); + }); +}); diff --git a/integration_test/tests/v2/scheduler.test.ts b/integration_test/tests/v2/scheduler.test.ts new file mode 100644 index 000000000..4d75bd5d5 --- /dev/null +++ b/integration_test/tests/v2/scheduler.test.ts @@ -0,0 +1,56 @@ +import admin from "firebase-admin"; +import { timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; + +// describe("Scheduler onSchedule trigger", () => { +// const projectId = process.env.PROJECT_ID; +// const region = process.env.REGION; +// const testId = process.env.TEST_RUN_ID; +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// if (!testId || !projectId || !region) { +// throw new Error("Environment configured incorrectly."); +// } +// await initializeFirebase(); + +// const accessToken = await admin.credential.applicationDefault().getAccessToken(); + +// const response = await fetch( +// `https://cloudscheduler.googleapis.com/v1/projects/${projectId}/locations/us-central1/jobs/firebase-schedule-${testId}-v2-schedule-${region}:run`, +// { +// method: "POST", +// headers: { +// "Content-Type": "application/json", +// Authorization: `Bearer ${accessToken.access_token}`, +// }, +// } +// ); +// if (!response.ok) { +// throw new Error(`Failed request with status ${response.status}!`); +// } + +// await timeout(15000); + +// const logSnapshot = await admin +// .firestore() +// .collection("schedulerOnScheduleV2Tests") +// .doc(testId) +// .get(); +// loggedContext = logSnapshot.data(); + +// if (!loggedContext) { +// throw new Error("loggedContext is undefined"); +// } +// }); + +// it("should trigger when the scheduler fires", () => { +// expect(loggedContext?.success).toBeTruthy(); +// }); +// }); + +describe("HTTP onCall trigger (DISABLED)", () => { + it("should be disabled", () => { + expect(true).toBeTruthy(); + }); +}); diff --git a/integration_test/tsconfig.json b/integration_test/tsconfig.json new file mode 100644 index 000000000..0aa0e8b37 --- /dev/null +++ b/integration_test/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "es2020", + "outDir": "./dist", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node" + }, + "include": ["**/*.ts"], + "exclude": ["node_modules", "functions/*", "tests/*"] +} diff --git a/integration_test/tsconfig.test.json b/integration_test/tsconfig.test.json new file mode 100644 index 000000000..681998ce1 --- /dev/null +++ b/integration_test/tsconfig.test.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "resolveJsonModule": true + }, + "include": ["**/*.test.ts"] +} From 59529befc662c624dc48e091a82259d8b481febe Mon Sep 17 00:00:00 2001 From: Kirsty Williams Date: Thu, 4 Jan 2024 14:08:09 +0000 Subject: [PATCH 02/25] chore: update gitignore --- integration_test/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/integration_test/.gitignore b/integration_test/.gitignore index a34e5488e..e6918b9b4 100644 --- a/integration_test/.gitignore +++ b/integration_test/.gitignore @@ -69,3 +69,4 @@ node_modules/ .firebaserc serviceAccount.json functions.yaml +functions/src/package.json From bca95fb72980288494f30051f876af5e83aef866 Mon Sep 17 00:00:00 2001 From: Kirsty Williams Date: Fri, 16 Feb 2024 19:32:10 -0400 Subject: [PATCH 03/25] feat: integration tests --- integration_test/.env.example | 7 +- integration_test/README.md | 24 +- .../functions/src/v1/analytics-tests.ts | 20 +- .../functions/src/v1/auth-tests.ts | 94 +- .../functions/src/v1/database-tests.ts | 98 +- .../functions/src/v1/firestore-tests.ts | 56 +- .../functions/src/v1/https-tests.ts | 28 +- integration_test/functions/src/v1/index.ts | 4 +- .../functions/src/v1/pubsub-tests.ts | 51 +- .../functions/src/v1/remoteConfig-tests.ts | 14 +- .../functions/src/v1/storage-tests.ts | 74 +- .../functions/src/v1/tasks-tests.ts | 17 +- .../functions/src/v1/testLab-tests.ts | 27 +- .../functions/src/v2/alerts-tests.ts | 278 +-- .../functions/src/v2/database-tests.ts | 118 +- .../functions/src/v2/eventarc-tests.ts | 30 +- .../functions/src/v2/firestore-tests.ts | 104 +- .../functions/src/v2/https-tests.ts | 13 +- .../functions/src/v2/identity-tests.ts | 37 +- integration_test/functions/src/v2/index.ts | 27 +- .../functions/src/v2/pubsub-tests.ts | 30 +- .../functions/src/v2/remoteConfig-tests.ts | 18 +- .../functions/src/v2/scheduler-tests.ts | 21 +- .../functions/src/v2/storage-tests.ts | 80 +- .../functions/src/v2/tasks-tests.ts | 22 +- .../functions/src/v2/testLab-tests.ts | 23 +- integration_test/jest.config.js | 1 - integration_test/package-lock.json | 2089 ++++++++++++++--- integration_test/package.json | 14 +- integration_test/package.json.template | 6 +- integration_test/run.ts | 30 +- integration_test/tests/firebaseSetup.ts | 1 - integration_test/tests/globalTeardown.ts | 69 - integration_test/tests/utils.ts | 156 ++ integration_test/tests/v1/analytics.test.ts | 51 - integration_test/tests/v1/auth.test.ts | 157 +- integration_test/tests/v1/database.test.ts | 343 ++- integration_test/tests/v1/firestore.test.ts | 280 ++- integration_test/tests/v1/https.test.ts | 55 - integration_test/tests/v1/pubsub.test.ts | 183 +- .../tests/v1/remoteConfig.test.ts | 101 +- integration_test/tests/v1/storage.test.ts | 195 +- integration_test/tests/v1/tasks.test.ts | 46 + integration_test/tests/v1/testLab.test.ts | 176 +- integration_test/tests/v2/database.test.ts | 215 ++ integration_test/tests/v2/eventarc.test.ts | 73 + integration_test/tests/v2/firestore.test.ts | 247 ++ integration_test/tests/v2/https.test.ts | 54 - integration_test/tests/v2/identity.test.ts | 140 ++ integration_test/tests/v2/pubsub.test.ts | 74 + .../tests/v2/remoteConfig.test.ts | 68 + integration_test/tests/v2/scheduler.test.ts | 104 +- integration_test/tests/v2/storage.test.ts | 175 ++ integration_test/tests/v2/tasks.test.ts | 45 + integration_test/tests/v2/testLab.test.ts | 51 + 55 files changed, 4676 insertions(+), 1838 deletions(-) delete mode 100644 integration_test/tests/globalTeardown.ts delete mode 100644 integration_test/tests/v1/analytics.test.ts delete mode 100644 integration_test/tests/v1/https.test.ts create mode 100644 integration_test/tests/v1/tasks.test.ts create mode 100644 integration_test/tests/v2/database.test.ts create mode 100644 integration_test/tests/v2/eventarc.test.ts create mode 100644 integration_test/tests/v2/firestore.test.ts delete mode 100644 integration_test/tests/v2/https.test.ts create mode 100644 integration_test/tests/v2/identity.test.ts create mode 100644 integration_test/tests/v2/pubsub.test.ts create mode 100644 integration_test/tests/v2/remoteConfig.test.ts create mode 100644 integration_test/tests/v2/storage.test.ts create mode 100644 integration_test/tests/v2/tasks.test.ts create mode 100644 integration_test/tests/v2/testLab.test.ts diff --git a/integration_test/.env.example b/integration_test/.env.example index b08459747..c4e6136e8 100644 --- a/integration_test/.env.example +++ b/integration_test/.env.example @@ -4,4 +4,9 @@ DATABASE_URL= STORAGE_BUCKET= NODE_VERSION=18 FIREBASE_ADMIN=^10.0.0 -GOOGLE_APPLICATION_CREDENTIALS= +FIREBASE_APP_ID= +FIREBASE_MEASUREMENT_ID= +FIREBASE_AUTH_DOMAIN= +FIREBASE_API_KEY= +GOOGLE_APPLICATION_CREDENTIALS=./serviceAccount.json +GOOGLE_ANALYTICS_API_SECRET= diff --git a/integration_test/README.md b/integration_test/README.md index 852d3ac82..e774d0418 100644 --- a/integration_test/README.md +++ b/integration_test/README.md @@ -4,19 +4,20 @@ ### Prerequisites -Tests use locally installed firebase to invoke commands for deploying function. -The test also requires that you have gcloud CLI installed and authenticated +Tests use locally installed firebase to invoke commands for deploying functions. +The tests also require that you have gcloud CLI installed and authenticated (`gcloud auth login`). Tests are deployed with a unique identifier, which enables the teardown of its own resources, without affecting other test runs. 1. Add a service account at root serviceAccount.json 2. Add a .env `cp .env.example .env` +3. Ensure service account has required roles for each cloud service +4. Ensure any resources such as eventarc channel ("firebase" is used as default) are configured ### Running setup and tests -This will deploy functions with unique names, set up environment for running the -jest files, and run the jest test suite. +This will deploy functions with unique names, set up environment for running the jest files, and run the jest test suite. ```bash yarn start @@ -26,7 +27,16 @@ yarn start [x] Deploy functions with unique name [x] Update existing tests to use jest (v1 and v2) -[] Add missing coverage for v1 and v2 (WIP) -[] Ensure proper teardown of resources (only those for current test run) +[x] Add missing coverage for v1 and v2 (WIP) +[x] Ensure proper teardown of resources (only those for current test run) +[] Check that we are properly tearing down all docs as side-effects +[] Analytics: since you cannot directly trigger onLog events from Firebase Analytics in a CI environment, the primary strategy is to isolate and test the logic within the Cloud Functions by mocking Firebase services and the Analytics event data. This is done elsewhere via unit tests, so no additional coverage necessary. +[] Alerts: same as analytics +[] Auth blocking functions can only be deployed one at a time, half-way solution is to deploy v1 functions, run v1 tests, teardown, and repeat for v2. However, this still won't allow for multiple runs to happen in parallel. Solution needed before re-enabling auth/identity tests. +[] Https tests were commented out previously, comments remain as before for same reasons [] Python runtime support -[] Capture test outcome for use by CI + +## Troubleshooting + +- Sometimes I ran into this reported [issue](https://github.com/firebase/firebase-tools/issues/793), I had to give it some period of time and attempt deploy again. Probably an upstream issue but may affect our approach here. Seems to struggle with deploying the large amount of trigger functions...? Falls over on Firebase Storage functions (if you comment these out everything else deploys as expected). +- Ensure service account has the necessary permissions for each service, and enable object versioning for the storage onArchive tests. diff --git a/integration_test/functions/src/v1/analytics-tests.ts b/integration_test/functions/src/v1/analytics-tests.ts index be957742e..1b7cc35ca 100644 --- a/integration_test/functions/src/v1/analytics-tests.ts +++ b/integration_test/functions/src/v1/analytics-tests.ts @@ -1,25 +1,7 @@ -import * as admin from "firebase-admin"; import * as functions from "firebase-functions"; import { REGION } from "../region"; -import { sanitizeData } from "../utils"; export const analyticsEventTests: any = functions .region(REGION) .analytics.event("in_app_purchase") - .onLog(async (event, context) => { - const testId = event.params?.testId; - try { - await admin - .firestore() - .collection("analyticsEventTests") - .doc(testId) - .set( - sanitizeData({ - ...context, - event: JSON.stringify(event), - }) - ); - } catch (error) { - console.error(`Error in Analytics event function for testId: ${testId}`, error); - } - }); + .onLog(async () => {}); diff --git a/integration_test/functions/src/v1/auth-tests.ts b/integration_test/functions/src/v1/auth-tests.ts index 57c78c3de..b0adcdab7 100644 --- a/integration_test/functions/src/v1/auth-tests.ts +++ b/integration_test/functions/src/v1/auth-tests.ts @@ -8,27 +8,23 @@ export const authUserOnCreateTests: any = functions .auth.user() .onCreate(async (user, context) => { const { email, displayName, uid } = user; - try { - const userProfile = { - email, - displayName, - createdAt: admin.firestore.FieldValue.serverTimestamp(), - }; - await admin.firestore().collection("userProfiles").doc(uid).set(userProfile); + const userProfile = { + email, + displayName, + createdAt: admin.firestore.FieldValue.serverTimestamp(), + }; + await admin.firestore().collection("userProfiles").doc(uid).set(userProfile); - await admin - .firestore() - .collection("authUserOnCreateTests") - .doc(uid) - .set( - sanitizeData({ - ...context, - metadata: JSON.stringify(user.metadata), - }) - ); - } catch (error) { - console.error(`Error in Auth user onCreate function for uid: ${uid}`, error); - } + await admin + .firestore() + .collection("authUserOnCreateTests") + .doc(uid) + .set( + sanitizeData({ + ...context, + metadata: JSON.stringify(user.metadata), + }) + ); }); export const authUserOnDeleteTests: any = functions @@ -36,36 +32,29 @@ export const authUserOnDeleteTests: any = functions .auth.user() .onDelete(async (user, context) => { const { uid } = user; - try { - await admin - .firestore() - .collection("authUserOnDeleteTests") - .doc(uid) - .set( - sanitizeData({ - ...context, - metadata: JSON.stringify(user.metadata), - }) - ); - } catch (error) { - console.error(`Error in Auth user onDelete function for uid: ${uid}`, error); - } + await admin + .firestore() + .collection("authUserOnDeleteTests") + .doc(uid) + .set( + sanitizeData({ + ...context, + metadata: JSON.stringify(user.metadata), + }) + ); }); export const authUserBeforeCreateTests: any = functions .region(REGION) .auth.user() .beforeCreate(async (user, context) => { - const { uid } = user; - try { - await admin - .firestore() - .collection("authUserBeforeCreateTests") - .doc(uid) - .set(sanitizeData(context)); - } catch (error) { - console.error(`Error in Auth user beforeCreate function for uid: ${uid}`, error); - } + await admin.firestore().collection("authBeforeCreateTests").doc(user.uid).set({ + eventId: context.eventId, + eventType: context.eventType, + timestamp: context.timestamp, + resource: context.resource, + }); + return user; }); @@ -73,15 +62,12 @@ export const authUserBeforeSignInTests: any = functions .region(REGION) .auth.user() .beforeSignIn(async (user, context) => { - const { uid } = user; - try { - await admin - .firestore() - .collection("authUserBeforeSignInTests") - .doc(uid) - .set(sanitizeData(context)); - } catch (error) { - console.error(`Error in Auth user beforeSignIn function for uid: ${uid}`, error); - } + await admin.firestore().collection("authBeforeSignInTests").doc(user.uid).set({ + eventId: context.eventId, + eventType: context.eventType, + timestamp: context.timestamp, + resource: context.resource, + }); + return user; }); diff --git a/integration_test/functions/src/v1/database-tests.ts b/integration_test/functions/src/v1/database-tests.ts index 569cdd9f2..0bb65cd42 100644 --- a/integration_test/functions/src/v1/database-tests.ts +++ b/integration_test/functions/src/v1/database-tests.ts @@ -9,20 +9,16 @@ export const databaseRefOnCreateTests: any = functions .onCreate(async (snapshot, context) => { const testId = context.params.testId; - try { - await admin - .firestore() - .collection("databaseRefOnCreateTests") - .doc(testId) - .set( - sanitizeData({ - ...context, - url: snapshot.ref.toString(), - }) - ); - } catch (error) { - console.error(`Error in Database ref onCreate function for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("databaseRefOnCreateTests") + .doc(testId) + .set( + sanitizeData({ + ...context, + url: snapshot.ref.toString(), + }) + ); }); export const databaseRefOnDeleteTests: any = functions @@ -31,20 +27,16 @@ export const databaseRefOnDeleteTests: any = functions .onDelete(async (snapshot, context) => { const testId = context.params.testId; - try { - await admin - .firestore() - .collection("databaseRefOnDeleteTests") - .doc(testId) - .set( - sanitizeData({ - ...context, - url: snapshot.ref.toString(), - }) - ); - } catch (error) { - console.error(`Error in Database ref onDelete function for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("databaseRefOnDeleteTests") + .doc(testId) + .set( + sanitizeData({ + ...context, + url: snapshot.ref.toString(), + }) + ); }); export const databaseRefOnUpdateTests: any = functions @@ -52,21 +44,19 @@ export const databaseRefOnUpdateTests: any = functions .database.ref("dbTests/{testId}/start") .onUpdate(async (change, context) => { const testId = context.params.testId; + const data = change.after.val(); - try { - await admin - .firestore() - .collection("databaseRefOnUpdateTests") - .doc(testId) - .set( - sanitizeData({ - ...context, - url: change.after.ref.toString(), - }) - ); - } catch (error) { - console.error(`Error in Database ref onUpdate function for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("databaseRefOnUpdateTests") + .doc(testId) + .set( + sanitizeData({ + ...context, + url: change.after.ref.toString(), + data: data ? JSON.stringify(data) : null, + }) + ); }); export const databaseRefOnWriteTests: any = functions @@ -79,18 +69,14 @@ export const databaseRefOnWriteTests: any = functions return; } - try { - await admin - .firestore() - .collection("databaseRefOnWriteTests") - .doc(testId) - .set( - sanitizeData({ - ...context, - url: change.after.ref.toString(), - }) - ); - } catch (error) { - console.error(`Error in Database ref onWrite function for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("databaseRefOnWriteTests") + .doc(testId) + .set( + sanitizeData({ + ...context, + url: change.after.ref.toString(), + }) + ); }); diff --git a/integration_test/functions/src/v1/firestore-tests.ts b/integration_test/functions/src/v1/firestore-tests.ts index 25b0d7d1d..a075f18aa 100644 --- a/integration_test/functions/src/v1/firestore-tests.ts +++ b/integration_test/functions/src/v1/firestore-tests.ts @@ -11,15 +11,11 @@ export const firestoreDocumentOnCreateTests: any = functions .firestore.document("tests/{testId}") .onCreate(async (snapshot, context) => { const testId = context.params.testId; - try { - await admin - .firestore() - .collection("firestoreDocumentOnCreateTests") - .doc(testId) - .set(sanitizeData(context)); - } catch (error) { - console.error(`Error in Firestore document onCreate function for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("firestoreDocumentOnCreateTests") + .doc(testId) + .set(sanitizeData(context)); }); export const firestoreDocumentOnDeleteTests: any = functions @@ -30,15 +26,11 @@ export const firestoreDocumentOnDeleteTests: any = functions .firestore.document("tests/{testId}") .onDelete(async (snapshot, context) => { const testId = context.params.testId; - try { - await admin - .firestore() - .collection("firestoreDocumentOnDeleteTests") - .doc(testId) - .set(sanitizeData(context)); - } catch (error) { - console.error(`Error in Firestore document onDelete function for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("firestoreDocumentOnDeleteTests") + .doc(testId) + .set(sanitizeData(context)); }); export const firestoreDocumentOnUpdateTests: any = functions @@ -49,15 +41,11 @@ export const firestoreDocumentOnUpdateTests: any = functions .firestore.document("tests/{testId}") .onUpdate(async (change, context) => { const testId = context.params.testId; - try { - await admin - .firestore() - .collection("firestoreDocumentOnUpdateTests") - .doc(testId) - .set(sanitizeData(context)); - } catch (error) { - console.error(`Error in Firestore document onUpdate function for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("firestoreDocumentOnUpdateTests") + .doc(testId) + .set(sanitizeData(context)); }); export const firestoreDocumentOnWriteTests: any = functions @@ -68,13 +56,9 @@ export const firestoreDocumentOnWriteTests: any = functions .firestore.document("tests/{testId}") .onWrite(async (change, context) => { const testId = context.params.testId; - try { - await admin - .firestore() - .collection("firestoreDocumentOnWriteTests") - .doc(testId) - .set(sanitizeData(context)); - } catch (error) { - console.error(`Error in Firestore document onWrite function for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("firestoreDocumentOnWriteTests") + .doc(testId) + .set(sanitizeData(context)); }); diff --git a/integration_test/functions/src/v1/https-tests.ts b/integration_test/functions/src/v1/https-tests.ts index 584538794..e74614862 100644 --- a/integration_test/functions/src/v1/https-tests.ts +++ b/integration_test/functions/src/v1/https-tests.ts @@ -7,15 +7,11 @@ export const httpsOnCallTests: any = functions .runWith({ invoker: "private" }) .region(REGION) .https.onCall(async (data) => { - try { - await admin - .firestore() - .collection("httpsOnCallTests") - .doc(data?.testId) - .set(sanitizeData(data)); - } catch (error) { - console.error(`Error in Https onCall function for testId: ${data?.testId}`, error); - } + await admin + .firestore() + .collection("httpsOnCallTests") + .doc(data?.testId) + .set(sanitizeData(data)); }); export const httpsOnRequestTests: any = functions @@ -23,13 +19,9 @@ export const httpsOnRequestTests: any = functions .region(REGION) .https.onRequest(async (req: functions.https.Request) => { const data = req?.body.data; - try { - await admin - .firestore() - .collection("httpsOnRequestTests") - .doc(data?.testId) - .set(sanitizeData(data)); - } catch (error) { - console.error(`Error in Https onRequest function for testId: ${data?.testId}`, error); - } + await admin + .firestore() + .collection("httpsOnRequestTests") + .doc(data?.testId) + .set(sanitizeData(data)); }); diff --git a/integration_test/functions/src/v1/index.ts b/integration_test/functions/src/v1/index.ts index 8c0d1ec4f..b9f43a177 100644 --- a/integration_test/functions/src/v1/index.ts +++ b/integration_test/functions/src/v1/index.ts @@ -1,8 +1,8 @@ export * from "./analytics-tests"; -export * from "./auth-tests"; +// export * from "./auth-tests"; export * from "./database-tests"; export * from "./firestore-tests"; -// // Temporarily disable http test - will not work unless running on projects w/ permission to create public functions. +// Temporarily disable http test - will not work unless running on projects w/ permission to create public functions. // export * from "./https-tests"; export * from "./pubsub-tests"; export * from "./remoteConfig-tests"; diff --git a/integration_test/functions/src/v1/pubsub-tests.ts b/integration_test/functions/src/v1/pubsub-tests.ts index 629eb5994..6bb556f0e 100644 --- a/integration_test/functions/src/v1/pubsub-tests.ts +++ b/integration_test/functions/src/v1/pubsub-tests.ts @@ -8,24 +8,16 @@ export const pubsubOnPublishTests: any = functions .pubsub.topic("pubsubTests") .onPublish(async (message, context) => { let testId = message.json?.testId; - if (!testId) { - console.error("TestId not found for onPublish function execution"); - return; - } - try { - await admin - .firestore() - .collection("pubsubOnPublishTests") - .doc(testId) - .set( - sanitizeData({ - ...context, - message: JSON.stringify(message), - }) - ); - } catch (error) { - console.error(`Error in Pub/Sub onPublish function for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("pubsubOnPublishTests") + .doc(testId) + .set( + sanitizeData({ + ...context, + message: JSON.stringify(message), + }) + ); }); export const pubsubScheduleTests: any = functions @@ -33,18 +25,17 @@ export const pubsubScheduleTests: any = functions .pubsub.schedule("every 10 hours") // This is a dummy schedule, since we need to put a valid one in. // For the test, the job is triggered by the jobs:run api .onRun(async (context) => { - const testId = context.resource?.labels?.service_name?.split("-")[0]; - if (!testId) { - console.error("TestId not found for scheduled function execution"); + const topicName = /\/topics\/([a-zA-Z0-9\-\_]+)/gi.exec(context.resource.name)[1]; + + if (!topicName) { + functions.logger.error( + "Topic name not found in resource name for scheduled function execution" + ); return; } - try { - await admin - .firestore() - .collection("pubsubScheduleTests") - .doc(testId) - .set(sanitizeData(context)); - } catch (error) { - console.error(`Error in Pub/Sub schedule function for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("pubsubScheduleTests") + .doc(topicName) + .set(sanitizeData(context)); }); diff --git a/integration_test/functions/src/v1/remoteConfig-tests.ts b/integration_test/functions/src/v1/remoteConfig-tests.ts index d416e9c44..1418a5c97 100644 --- a/integration_test/functions/src/v1/remoteConfig-tests.ts +++ b/integration_test/functions/src/v1/remoteConfig-tests.ts @@ -7,13 +7,9 @@ export const remoteConfigOnUpdateTests: any = functions .region(REGION) .remoteConfig.onUpdate(async (version, context) => { const testId = version.description; - try { - await admin - .firestore() - .collection("remoteConfigOnUpdateTests") - .doc(testId) - .set(sanitizeData(context)); - } catch (error) { - console.error(`Error in RemoteConfig onUpdate function for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("remoteConfigOnUpdateTests") + .doc(testId) + .set(sanitizeData(context)); }); diff --git a/integration_test/functions/src/v1/storage-tests.ts b/integration_test/functions/src/v1/storage-tests.ts index a2a6a5bfc..ad91d4974 100644 --- a/integration_test/functions/src/v1/storage-tests.ts +++ b/integration_test/functions/src/v1/storage-tests.ts @@ -3,30 +3,6 @@ import * as functions from "firebase-functions"; import { REGION } from "../region"; import { sanitizeData } from "../utils"; -export const storageOnArchiveTests: any = functions - .runWith({ - timeoutSeconds: 540, - }) - .region(REGION) - .storage.bucket() - .object() - .onArchive(async (object, context) => { - const testId = object.name?.split(".")[0]; - if (!testId) { - console.error("TestId not found for storage object archive"); - return; - } - try { - await admin - .firestore() - .collection("storageOnArchiveTests") - .doc(testId) - .set(sanitizeData(context)); - } catch (error) { - console.error(`Error in Storage onArchive function for testId: ${testId}`, error); - } - }); - export const storageOnDeleteTests: any = functions .runWith({ timeoutSeconds: 540, @@ -37,18 +13,15 @@ export const storageOnDeleteTests: any = functions .onDelete(async (object, context) => { const testId = object.name?.split(".")[0]; if (!testId) { - console.error("TestId not found for storage object delete"); + functions.logger.error("TestId not found for storage object delete"); return; } - try { - await admin - .firestore() - .collection("storageOnDeleteTests") - .doc(testId) - .set(sanitizeData(context)); - } catch (error) { - console.error(`Error in Storage onDelete function for testId: ${testId}`, error); - } + + await admin + .firestore() + .collection("storageOnDeleteTests") + .doc(testId) + .set(sanitizeData(context)); }); export const storageOnFinalizeTests: any = functions @@ -61,18 +34,15 @@ export const storageOnFinalizeTests: any = functions .onFinalize(async (object, context) => { const testId = object.name?.split(".")[0]; if (!testId) { - console.error("TestId not found for storage object finalize"); + functions.logger.error("TestId not found for storage object finalize"); return; } - try { - await admin - .firestore() - .collection("storageOnFinalizeTests") - .doc(testId) - .set(sanitizeData(context)); - } catch (error) { - console.error(`Error in Storage onFinalize function for testId: ${testId}`, error); - } + + await admin + .firestore() + .collection("storageOnFinalizeTests") + .doc(testId) + .set(sanitizeData(context)); }); export const storageOnMetadataUpdateTests: any = functions @@ -85,16 +55,12 @@ export const storageOnMetadataUpdateTests: any = functions .onMetadataUpdate(async (object, context) => { const testId = object.name?.split(".")[0]; if (!testId) { - console.error("TestId not found for storage object metadata update"); + functions.logger.error("TestId not found for storage object metadata update"); return; } - try { - await admin - .firestore() - .collection("storageOnMetadataUpdateTests") - .doc(testId) - .set(sanitizeData(context)); - } catch (error) { - console.error(`Error in Storage onMetadataUpdate function for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("storageOnMetadataUpdateTests") + .doc(testId) + .set(sanitizeData(context)); }); diff --git a/integration_test/functions/src/v1/tasks-tests.ts b/integration_test/functions/src/v1/tasks-tests.ts index 5439fd8c2..d06dcd35e 100644 --- a/integration_test/functions/src/v1/tasks-tests.ts +++ b/integration_test/functions/src/v1/tasks-tests.ts @@ -11,13 +11,14 @@ export const tasksOnDispatchTests: any = functions .tasks.taskQueue() .onDispatch(async (data, context) => { const testId = data.testId; - try { - await admin - .firestore() - .collection("tasksOnDispatchTests") - .doc(testId) - .set(sanitizeData(context)); - } catch (error) { - console.error(`Error in Tasks onDispatch function for testId: ${testId}`, error); + if (!testId) { + functions.logger.error("TestId not found for tasks onDispatch"); + return; } + + await admin + .firestore() + .collection("tasksOnDispatchTests") + .doc(testId) + .set(sanitizeData(context)); }); diff --git a/integration_test/functions/src/v1/testLab-tests.ts b/integration_test/functions/src/v1/testLab-tests.ts index b44c89a3a..755136247 100644 --- a/integration_test/functions/src/v1/testLab-tests.ts +++ b/integration_test/functions/src/v1/testLab-tests.ts @@ -12,21 +12,18 @@ export const testLabOnCompleteTests: any = functions .onComplete(async (matrix, context) => { const testId = matrix?.clientInfo?.details?.testId; if (!testId) { - console.error("TestId not found for test matrix completion"); + functions.logger.error("TestId not found for test matrix completion"); return; } - try { - await admin - .firestore() - .collection("testLabOnCompleteTests") - .doc(testId) - .set( - sanitizeData({ - ...context, - matrix: JSON.stringify(matrix), - }) - ); - } catch (error) { - console.error(`Error in Test Matrix onComplete function for testId: ${testId}`, error); - } + + await admin + .firestore() + .collection("testLabOnCompleteTests") + .doc(testId) + .set( + sanitizeData({ + ...context, + matrix: JSON.stringify(matrix), + }) + ); }); diff --git a/integration_test/functions/src/v2/alerts-tests.ts b/integration_test/functions/src/v2/alerts-tests.ts index 377bef89d..ffc56ba61 100644 --- a/integration_test/functions/src/v2/alerts-tests.ts +++ b/integration_test/functions/src/v2/alerts-tests.ts @@ -1,4 +1,4 @@ -import * as admin from "firebase-admin"; +// import * as admin from "firebase-admin"; import { onAlertPublished } from "firebase-functions/v2/alerts"; import { onInAppFeedbackPublished, @@ -17,218 +17,144 @@ import { onVelocityAlertPublished, } from "firebase-functions/v2/alerts/crashlytics"; import { onThresholdAlertPublished } from "firebase-functions/v2/alerts/performance"; -import { REGION } from "../region"; -export const alertsOnAlertPublishedTests = onAlertPublished("crashlytics.issue", async (event) => { - const testId = event.data.payload.testId; +// TODO: All this does is test that the function is deployable. +// Since you cannot directly trigger alerts in a CI environment, we cannot test +// the internals without mocking. - try { - await admin - .firestore() - .collection("alertsOnAlertPublishedTests") - .doc(testId) - .set({ event: JSON.stringify(event) }); - } catch (error) { - console.error(`Error handling alert for testId: ${testId}`, error); +export const alertsOnAlertPublishedTests = onAlertPublished( + "crashlytics.newFatalIssue", + async (event) => { + // const testId = event.data.payload.testId; + // await admin + // .firestore() + // .collection("alertsOnAlertPublishedTests") + // .doc(testId) + // .set({ event: JSON.stringify(event) }); } -}); +); export const alertsOnInAppFeedbackPublishedTests = onInAppFeedbackPublished(async (event) => { - const testId = event.data.payload.testerName; - - if (!testId) { - console.error("TestId not found for onInAppFeedbackPublished"); - return; - } - - try { - await admin - .firestore() - .collection("alertsOnInAppFeedbackPublishedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + // const testId = event.data.payload.text; + // await admin + // .firestore() + // .collection("alertsOnInAppFeedbackPublishedTests") + // .doc(testId) + // .set({ + // event: JSON.stringify(event), + // }); }); export const alertsOnNewTesterIosDevicePublishedTests = onNewTesterIosDevicePublished( async (event) => { - const testId = event.data.payload.testerName; - - if (!testId) { - console.error("TestId not found for onNewTesterIosDevicePublished"); - return; - } - - try { - await admin - .firestore() - .collection("alertsOnNewTesterIosDevicePublishedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + // const testId = event.data.payload.testerName; + // await admin + // .firestore() + // .collection("alertsOnNewTesterIosDevicePublishedTests") + // .doc(testId) + // .set({ + // event: JSON.stringify(event), + // }); } ); export const alertsOnPlanAutomatedUpdatePublishedTests = onPlanAutomatedUpdatePublished( async (event) => { - const testId = event.data.payload.billingPlan; - - if (!testId) { - console.error("TestId not found for onPlanAutomatedUpdatePublished"); - return; - } - - try { - await admin - .firestore() - .collection("alertsOnPlanAutomatedUpdatePublishedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + // const testId = event.data.payload.billingPlan; + // await admin + // .firestore() + // .collection("alertsOnPlanAutomatedUpdatePublishedTests") + // .doc(testId) + // .set({ + // event: JSON.stringify(event), + // }); } ); export const alertsOnPlanUpdatePublishedTests = onPlanUpdatePublished(async (event) => { - const testId = event.data.payload.billingPlan; - - if (!testId) { - console.error("TestId not found for onPlanUpdatePublished"); - return; - } - - try { - await admin - .firestore() - .collection("alertsOnPlanUpdatePublishedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + // const testId = event.data.payload.billingPlan; + // await admin + // .firestore() + // .collection("alertsOnPlanUpdatePublishedTests") + // .doc(testId) + // .set({ + // event: JSON.stringify(event), + // }); }); export const alertsOnNewAnrIssuePublishedTests = onNewAnrIssuePublished(async (event) => { - const testId = event.data.payload.issue.title; - - try { - await admin - .firestore() - .collection("alertsOnNewAnrIssuePublishedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + // const testId = event.data.payload.issue.title; + // await admin + // .firestore() + // .collection("alertsOnNewAnrIssuePublishedTests") + // .doc(testId) + // .set({ + // event: JSON.stringify(event), + // }); }); export const alertsOnNewFatalIssuePublishedTests = onNewFatalIssuePublished(async (event) => { - const testId = event.data.payload.issue.title; - - try { - await admin - .firestore() - .collection("alertsOnNewFatalIssuePublishedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + // const testId = event.data.payload.issue.title; + // await admin + // .firestore() + // .collection("alertsOnNewFatalIssuePublishedTests") + // .doc(testId) + // .set({ + // event: JSON.stringify(event), + // }); }); export const alertsOnNewNonFatalIssuePublishedTests = onNewNonfatalIssuePublished(async (event) => { - const testId = event.data.payload.issue.title; - - try { - await admin - .firestore() - .collection("alertsOnNewFatalIssuePublishedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + // const testId = event.data.payload.issue.title; + // await admin + // .firestore() + // .collection("alertsOnNewFatalIssuePublishedTests") + // .doc(testId) + // .set({ + // event: JSON.stringify(event), + // }); }); export const alertsOnRegressionAlertPublishedTests = onRegressionAlertPublished(async (event) => { - const testId = event.data.payload.issue.title; - - try { - await admin - .firestore() - .collection("alertsOnRegressionAlertPublishedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + // const testId = event.data.payload.issue.title; + // await admin + // .firestore() + // .collection("alertsOnRegressionAlertPublishedTests") + // .doc(testId) + // .set({ + // event: JSON.stringify(event), + // }); }); export const alertsOnStabilityDigestPublishedTests = onStabilityDigestPublished(async (event) => { - const testId = event.data.payload.trendingIssues[0].issue.title; - - try { - await admin - .firestore() - .collection("alertsOnRegressionAlertPublishedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + // const testId = event.data.payload.trendingIssues[0].issue.title; + // await admin + // .firestore() + // .collection("alertsOnRegressionAlertPublishedTests") + // .doc(testId) + // .set({ + // event: JSON.stringify(event), + // }); }); export const alertsOnVelocityAlertPublishedTests = onVelocityAlertPublished(async (event) => { - const testId = event.data.payload.issue.title; - - try { - await admin - .firestore() - .collection("alertsOnVelocityAlertPublishedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + // const testId = event.data.payload.issue.title; + // await admin + // .firestore() + // .collection("alertsOnVelocityAlertPublishedTests") + // .doc(testId) + // .set({ + // event: JSON.stringify(event), + // }); }); export const alertsOnThresholdAlertPublishedTests = onThresholdAlertPublished(async (event) => { - const testId = event.data.payload.eventName; - - try { - await admin - .firestore() - .collection("alertsOnThresholdAlertPublishedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + // const testId = event.data.payload.eventName; + // await admin + // .firestore() + // .collection("alertsOnThresholdAlertPublishedTests") + // .doc(testId) + // .set({ + // event: JSON.stringify(event), + // }); }); diff --git a/integration_test/functions/src/v2/database-tests.ts b/integration_test/functions/src/v2/database-tests.ts index 72b5bc3a3..96c214f34 100644 --- a/integration_test/functions/src/v2/database-tests.ts +++ b/integration_test/functions/src/v2/database-tests.ts @@ -1,4 +1,5 @@ import * as admin from "firebase-admin"; +import * as functions from "firebase-functions"; import { onValueWritten, onValueCreated, @@ -15,21 +16,19 @@ export const databaseCreatedTests = onValueCreated( }, async (event) => { const testId = event.params.testId; - - try { - await admin - .firestore() - .collection("databaseCreatedTests") - .doc(testId) - .set( - sanitizeData({ - testId, - url: event.ref.toString(), - }) - ); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("databaseCreatedTests") + .doc(testId) + .set( + sanitizeData({ + testId, + type: event.type, + id: event.id, + time: event.time, + url: event.ref.toString(), + }) + ); } ); @@ -40,21 +39,19 @@ export const databaseDeletedTests = onValueDeleted( }, async (event) => { const testId = event.params.testId; - - try { - await admin - .firestore() - .collection("databaseDeletedTests") - .doc(testId) - .set( - sanitizeData({ - testId, - url: event.ref.toString(), - }) - ); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("databaseDeletedTests") + .doc(testId) + .set( + sanitizeData({ + testId, + type: event.type, + id: event.id, + time: event.time, + url: event.ref.toString(), + }) + ); } ); @@ -65,21 +62,21 @@ export const databaseUpdatedTests = onValueUpdated( }, async (event) => { const testId = event.params.testId; - - try { - await admin - .firestore() - .collection("databaseUpdatedTests") - .doc(testId) - .set( - sanitizeData({ - testId, - url: event.ref.toString(), - }) - ); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + const data = event.data.after.val(); + await admin + .firestore() + .collection("databaseUpdatedTests") + .doc(testId) + .set( + sanitizeData({ + testId, + url: event.ref.toString(), + type: event.type, + id: event.id, + time: event.time, + data: JSON.stringify(data ?? {}), + }) + ); } ); @@ -90,25 +87,22 @@ export const databaseWrittenTests = onValueWritten( }, async (event) => { const testId = event.params.testId; - if (!event.data.after.exists()) { - console.info(`Event for ${testId} is null; presuming data cleanup, so skipping.`); + functions.logger.info(`Event for ${testId} is null; presuming data cleanup, so skipping.`); return; } - - try { - await admin - .firestore() - .collection("databaseWrittenTests") - .doc(testId) - .set( - sanitizeData({ - testId, - url: event.ref.toString(), - }) - ); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("databaseWrittenTests") + .doc(testId) + .set( + sanitizeData({ + testId, + type: event.type, + id: event.id, + time: event.time, + url: event.ref.toString(), + }) + ); } ); diff --git a/integration_test/functions/src/v2/eventarc-tests.ts b/integration_test/functions/src/v2/eventarc-tests.ts index 22dd60612..aa3424819 100644 --- a/integration_test/functions/src/v2/eventarc-tests.ts +++ b/integration_test/functions/src/v2/eventarc-tests.ts @@ -1,25 +1,21 @@ import * as admin from "firebase-admin"; import { onCustomEventPublished } from "firebase-functions/v2/eventarc"; -import { REGION } from "../region"; export const eventarcOnCustomEventPublishedTests = onCustomEventPublished( - { - eventType: "custom_event_tests", - region: REGION, - }, + "achieved-leaderboard", async (event) => { - const testId = event.data.payload.testId; + const testId = event.data.testId; - try { - await admin - .firestore() - .collection("eventarcOnCustomEventPublishedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error creating test record for testId: ${testId}`, error); - } + await admin + .firestore() + .collection("eventarcOnCustomEventPublishedTests") + .doc(testId) + .set({ + id: event.id, + type: event.type, + time: event.time, + source: event.source, + data: JSON.stringify(event.data), + }); } ); diff --git a/integration_test/functions/src/v2/firestore-tests.ts b/integration_test/functions/src/v2/firestore-tests.ts index 59a7f436b..72741408d 100644 --- a/integration_test/functions/src/v2/firestore-tests.ts +++ b/integration_test/functions/src/v2/firestore-tests.ts @@ -1,5 +1,11 @@ import * as admin from "firebase-admin"; -import { onDocumentCreated, onDocumentDeleted } from "firebase-functions/v2/firestore"; +import * as functions from "firebase-functions"; +import { + onDocumentCreated, + onDocumentDeleted, + onDocumentUpdated, + onDocumentWritten, +} from "firebase-functions/v2/firestore"; import { REGION } from "../region"; import { sanitizeData } from "../utils"; @@ -10,16 +16,21 @@ export const firestoreOnDocumentCreatedTests = onDocumentCreated( timeoutSeconds: 540, }, async (event) => { + functions.logger.debug(event); const documentId = event.params.documentId; - try { - await admin - .firestore() - .collection("firestoreOnDocumentCreatedTests") - .doc(documentId) - .set(sanitizeData(event)); - } catch (error) { - console.error(`Error creating test record for testId: ${documentId}`, error); - } + + await admin + .firestore() + .collection("firestoreOnDocumentCreatedTests") + .doc(documentId) + .set( + sanitizeData({ + time: event.time, + id: event.id, + type: event.type, + source: event.source, + }) + ); } ); @@ -30,55 +41,70 @@ export const firestoreOnDocumentDeletedTests = onDocumentDeleted( timeoutSeconds: 540, }, async (event) => { + functions.logger.debug(event); const documentId = event.params.documentId; - try { - await admin - .firestore() - .collection("firestoreOnDocumentCreatedTests") - .doc(documentId) - .set(sanitizeData(event)); - } catch (error) { - console.error(`Error creating test record for testId: ${documentId}`, error); - } + + await admin + .firestore() + .collection("firestoreOnDocumentDeletedTests") + .doc(documentId) + .set( + sanitizeData({ + time: event.time, + id: event.id, + type: event.type, + source: event.source, + }) + ); } ); -export const firestoreOnDocumentUpdatedTests = onDocumentDeleted( +export const firestoreOnDocumentUpdatedTests = onDocumentUpdated( { document: "tests/{documentId}", region: REGION, timeoutSeconds: 540, }, async (event) => { + functions.logger.debug(event); const documentId = event.params.documentId; - try { - await admin - .firestore() - .collection("firestoreOnDocumentUpdatedTests") - .doc(documentId) - .set(sanitizeData(event)); - } catch (error) { - console.error(`Error creating test record for testId: ${documentId}`, error); - } + + await admin + .firestore() + .collection("firestoreOnDocumentUpdatedTests") + .doc(documentId) + .set( + sanitizeData({ + time: event.time, + id: event.id, + type: event.type, + source: event.source, + }) + ); } ); -export const firestoreOnDocumentWrittenTests = onDocumentDeleted( +export const firestoreOnDocumentWrittenTests = onDocumentWritten( { document: "tests/{documentId}", region: REGION, timeoutSeconds: 540, }, async (event) => { + functions.logger.debug(event); const documentId = event.params.documentId; - try { - await admin - .firestore() - .collection("firestoreOnDocumentWrittenTests") - .doc(documentId) - .set(sanitizeData(event)); - } catch (error) { - console.error(`Error creating test record for testId: ${documentId}`, error); - } + + await admin + .firestore() + .collection("firestoreOnDocumentWrittenTests") + .doc(documentId) + .set( + sanitizeData({ + time: event.time, + id: event.id, + type: event.type, + source: event.source, + }) + ); } ); diff --git a/integration_test/functions/src/v2/https-tests.ts b/integration_test/functions/src/v2/https-tests.ts index 5b572ab73..751e8b7a7 100644 --- a/integration_test/functions/src/v2/https-tests.ts +++ b/integration_test/functions/src/v2/https-tests.ts @@ -9,11 +9,7 @@ export const httpsOnCallV2Tests = onCall( }, async (req) => { const data = req?.data; - try { - await admin.firestore().collection("httpsOnCallV2Tests").doc(data?.testId).set(data); - } catch (error) { - console.error(`Error creating test record for testId: ${data?.testId}`, error); - } + await admin.firestore().collection("httpsOnCallV2Tests").doc(data?.testId).set(data); } ); @@ -24,10 +20,7 @@ export const httpsOnRequestV2Tests = onRequest( }, async (req) => { const data = req?.body.data; - try { - await admin.firestore().collection("httpsOnRequestV2Tests").doc(data?.testId).set(data); - } catch (error) { - console.error(`Error creating test record for testId: ${data?.testId}`, error); - } + + await admin.firestore().collection("httpsOnRequestV2Tests").doc(data?.testId).set(data); } ); diff --git a/integration_test/functions/src/v2/identity-tests.ts b/integration_test/functions/src/v2/identity-tests.ts index 0b3381a2f..07e92c596 100644 --- a/integration_test/functions/src/v2/identity-tests.ts +++ b/integration_test/functions/src/v2/identity-tests.ts @@ -3,32 +3,25 @@ import { beforeUserCreated, beforeUserSignedIn } from "firebase-functions/v2/ide export const identityBeforeUserCreatedTests = beforeUserCreated(async (event) => { const { uid } = event.data; - try { - await admin - .firestore() - .collection("identityBeforeUserCreatedTests") - .doc(uid) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error in identity beforeUserCreated function for uid: ${uid}`, error); - } + + await admin.firestore().collection("identityBeforeUserCreatedTests").doc(uid).set({ + eventId: event.eventId, + eventType: event.eventType, + timestamp: event.timestamp, + resource: event.resource, + }); + return event.data; }); export const identityBeforeUserSignedInTests = beforeUserSignedIn(async (event) => { const { uid } = event.data; - try { - await admin - .firestore() - .collection("identityBeforeUserSignedInTests") - .doc(uid) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error in identity beforeUserCreated function for uid: ${uid}`, error); - } + await admin.firestore().collection("identityBeforeUserSignedInTests").doc(uid).set({ + eventId: event.eventId, + eventType: event.eventType, + timestamp: event.timestamp, + resource: event.resource, + }); + return event.data; }); diff --git a/integration_test/functions/src/v2/index.ts b/integration_test/functions/src/v2/index.ts index 9fdd9807a..561505427 100644 --- a/integration_test/functions/src/v2/index.ts +++ b/integration_test/functions/src/v2/index.ts @@ -3,15 +3,18 @@ import { REGION } from "../region"; setGlobalOptions({ region: REGION }); export * from "./alerts-tests"; -// export * from "./database-tests"; -// export * from "./eventarc-tests"; -// export * from "./firestore-tests"; -// export * from './https-tests'; -// TODO: cannot deploy multiple auth blocking funcs at once. -// update framework to run v1 tests in isolation, tear down, then run v2 tests -// export * from "./identity-tests"; -// export * from './pubsub-tests'; -// export * from "./scheduler-tests"; -// export * from "./storage-tests"; -// export * from "./tasks-tests"; -// export * from "./testLab-tests"; +export * from "./database-tests"; +export * from "./eventarc-tests"; +export * from "./firestore-tests"; +// Temporarily disable http test - will not work unless running on projects +// w/ permission to create public functions. +// export * from "./https-tests"; +// TODO: cannot deploy multiple auth blocking funcs at once. Only have one of +// v2 identity or v1 auth exported at once. +export * from "./identity-tests"; +export * from "./pubsub-tests"; +export * from "./scheduler-tests"; +export * from "./storage-tests"; +export * from "./tasks-tests"; +export * from "./testLab-tests"; +export * from "./remoteConfig-tests"; diff --git a/integration_test/functions/src/v2/pubsub-tests.ts b/integration_test/functions/src/v2/pubsub-tests.ts index b7aae851b..aeb0c6186 100644 --- a/integration_test/functions/src/v2/pubsub-tests.ts +++ b/integration_test/functions/src/v2/pubsub-tests.ts @@ -1,6 +1,8 @@ import * as admin from "firebase-admin"; +import * as functions from "firebase-functions"; import { onMessagePublished } from "firebase-functions/v2/pubsub"; import { REGION } from "../region"; +import { sanitizeData } from "../utils"; export const pubsubOnMessagePublishedTests = onMessagePublished( { @@ -10,19 +12,23 @@ export const pubsubOnMessagePublishedTests = onMessagePublished( async (event) => { let testId = event.data.message.json?.testId; if (!testId) { - console.error("TestId not found for onMessagePublished function execution"); + functions.logger.error("TestId not found for onMessagePublished function execution"); return; } - try { - await admin - .firestore() - .collection("pubsubOnMessagePublishedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error in Pub/Sub onMessagePublished function for testId: ${testId}`, error); - } + + await admin + .firestore() + .collection("pubsubOnMessagePublishedTests") + .doc(testId) + .set( + sanitizeData({ + id: event.id, + source: event.source, + subject: event.subject, + time: event.time, + type: event.type, + message: JSON.stringify(event.data.message), + }) + ); } ); diff --git a/integration_test/functions/src/v2/remoteConfig-tests.ts b/integration_test/functions/src/v2/remoteConfig-tests.ts index 018a9d9eb..89ba5209c 100644 --- a/integration_test/functions/src/v2/remoteConfig-tests.ts +++ b/integration_test/functions/src/v2/remoteConfig-tests.ts @@ -8,16 +8,12 @@ export const remoteConfigOnConfigUpdatedTests = onConfigUpdated( }, async (event) => { const testId = event.data.description; - try { - await admin - .firestore() - .collection("remoteConfigOnConfigUpdatedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error in RemoteConfig onConfigUpdated function for testId: ${testId}`, error); - } + + await admin.firestore().collection("remoteConfigOnConfigUpdatedTests").doc(testId).set({ + testId, + type: event.type, + id: event.id, + time: event.time, + }); } ); diff --git a/integration_test/functions/src/v2/scheduler-tests.ts b/integration_test/functions/src/v2/scheduler-tests.ts index 09bad2612..c7f38d691 100644 --- a/integration_test/functions/src/v2/scheduler-tests.ts +++ b/integration_test/functions/src/v2/scheduler-tests.ts @@ -1,8 +1,9 @@ import * as admin from "firebase-admin"; +import * as functions from "firebase-functions"; import { onSchedule } from "firebase-functions/v2/scheduler"; import { REGION } from "../region"; -export const schedulerOnScheduleTests: any = onSchedule( +export const schedule: any = onSchedule( { schedule: "every 10 hours", region: REGION, @@ -10,18 +11,16 @@ export const schedulerOnScheduleTests: any = onSchedule( async (event) => { const testId = event.jobName; if (!testId) { - console.error("TestId not found for scheduled function execution"); + functions.logger.error("TestId not found for scheduled function execution"); return; } - try { - await admin - .firestore() - .collection("schedulerOnScheduleTests") - .doc(testId) - .set({ success: true }); - } catch (error) { - console.error(`Error in scheduler onSchedule function for testId: ${testId}`, error); - } + + await admin + .firestore() + .collection("schedulerOnScheduleV2Tests") + .doc(testId) + .set({ success: true }); + return; } ); diff --git a/integration_test/functions/src/v2/storage-tests.ts b/integration_test/functions/src/v2/storage-tests.ts index 821ddc338..fd0e8f755 100644 --- a/integration_test/functions/src/v2/storage-tests.ts +++ b/integration_test/functions/src/v2/storage-tests.ts @@ -1,34 +1,12 @@ import * as admin from "firebase-admin"; +import * as functions from "firebase-functions"; import { - onObjectArchived, onObjectDeleted, onObjectFinalized, onObjectMetadataUpdated, } from "firebase-functions/v2/storage"; import { REGION } from "../region"; -export const storageOnObjectArchiveTests = onObjectArchived( - { - region: REGION, - }, - async (event) => { - const testId = event.data.name?.split(".")[0]; - if (!testId) { - console.error("TestId not found for storage onObjectArchived"); - return; - } - try { - await admin - .firestore() - .collection("storageOnObjectArchivedTests") - .doc(testId) - .set({ event: JSON.stringify(event) }); - } catch (error) { - console.error(`Error in Storage onObjectArchived function for testId: ${testId}`, error); - } - } -); - export const storageOnDeleteTests = onObjectDeleted( { region: REGION, @@ -36,18 +14,16 @@ export const storageOnDeleteTests = onObjectDeleted( async (event) => { const testId = event.data.name?.split(".")[0]; if (!testId) { - console.error("TestId not found for storage onObjectDeleted"); + functions.logger.error("TestId not found for storage onObjectDeleted"); return; } - try { - await admin - .firestore() - .collection("storageOnObjectDeletedTests") - .doc(testId) - .set({ event: JSON.stringify(event) }); - } catch (error) { - console.error(`Error in Storage onObjectDeleted function for testId: ${testId}`, error); - } + + await admin.firestore().collection("storageOnObjectDeletedTests").doc(testId).set({ + id: event.id, + time: event.time, + type: event.type, + source: event.source, + }); } ); @@ -58,18 +34,16 @@ export const storageOnFinalizeTests = onObjectFinalized( async (event) => { const testId = event.data.name?.split(".")[0]; if (!testId) { - console.error("TestId not found for storage onObjectFinalized"); + functions.logger.error("TestId not found for storage onObjectFinalized"); return; } - try { - await admin - .firestore() - .collection("storageOnObjectFinalizedTests") - .doc(testId) - .set({ event: JSON.stringify(event) }); - } catch (error) { - console.error(`Error in Storage onObjectFinalized function for testId: ${testId}`, error); - } + + await admin.firestore().collection("storageOnObjectFinalizedTests").doc(testId).set({ + id: event.id, + time: event.time, + type: event.type, + source: event.source, + }); } ); @@ -80,20 +54,14 @@ export const storageOnMetadataUpdateTests = onObjectMetadataUpdated( async (event) => { const testId = event.data.name?.split(".")[0]; if (!testId) { - console.error("TestId not found for storage onObjectMetadataUpdated"); + functions.logger.error("TestId not found for storage onObjectMetadataUpdated"); return; } - try { - await admin - .firestore() - .collection("storageOnObjectMetadataUpdatedTests") - .doc(testId) - .set({ event: JSON.stringify(event) }); - } catch (error) { - console.error( - `Error in Storage onObjectMetadataUpdated function for testId: ${testId}`, - error - ); - } + await admin.firestore().collection("storageOnObjectMetadataUpdatedTests").doc(testId).set({ + id: event.id, + time: event.time, + type: event.type, + source: event.source, + }); } ); diff --git a/integration_test/functions/src/v2/tasks-tests.ts b/integration_test/functions/src/v2/tasks-tests.ts index c4af36232..4257ab7d1 100644 --- a/integration_test/functions/src/v2/tasks-tests.ts +++ b/integration_test/functions/src/v2/tasks-tests.ts @@ -1,4 +1,5 @@ import * as admin from "firebase-admin"; +import * as functions from "firebase-functions"; import { onTaskDispatched } from "firebase-functions/v2/tasks"; import { REGION } from "../region"; @@ -8,16 +9,17 @@ export const tasksOnTaskDispatchedTests = onTaskDispatched( }, async (event) => { const testId = event.data.testId; - try { - await admin - .firestore() - .collection("tasksOnTaskDispatchedTests") - .doc(testId) - .set({ - event: JSON.stringify(event), - }); - } catch (error) { - console.error(`Error in Tasks onTaskDispatched function for testId: ${testId}`, error); + + if (!testId) { + functions.logger.error("TestId not found for tasks onTaskDispatched"); + return; } + + await admin.firestore().collection("tasksOnTaskDispatchedTests").doc(testId).set({ + testId, + queueName: event.queueName, + id: event.id, + scheduledTime: event.scheduledTime, + }); } ); diff --git a/integration_test/functions/src/v2/testLab-tests.ts b/integration_test/functions/src/v2/testLab-tests.ts index 1235d8848..767186082 100644 --- a/integration_test/functions/src/v2/testLab-tests.ts +++ b/integration_test/functions/src/v2/testLab-tests.ts @@ -1,4 +1,5 @@ import * as admin from "firebase-admin"; +import * as functions from "firebase-functions"; import { onTestMatrixCompleted } from "firebase-functions/v2/testLab"; import { REGION } from "../region"; @@ -9,20 +10,16 @@ export const testLabOnTestMatrixCompletedTests = onTestMatrixCompleted( async (event) => { const testId = event.data.clientInfo?.details?.testId; if (!testId) { - console.error("TestId not found for test matrix completion"); + functions.logger.error("TestId not found for test matrix completion"); return; } - try { - await admin - .firestore() - .collection("testLabOnTestMatrixCompletedTests") - .doc(testId) - .set({ event: JSON.stringify(event) }); - } catch (error) { - console.error( - `Error in Test Matrix onTestMatrixCompleted function for testId: ${testId}`, - error - ); - } + + await admin.firestore().collection("testLabOnTestMatrixCompletedTests").doc(testId).set({ + testId, + type: event.type, + id: event.id, + time: event.time, + state: event.data.state, + }); } ); diff --git a/integration_test/jest.config.js b/integration_test/jest.config.js index 30052fdc7..7421b956c 100644 --- a/integration_test/jest.config.js +++ b/integration_test/jest.config.js @@ -3,7 +3,6 @@ export default { testEnvironment: "node", testMatch: ["**/tests/**/*.test.ts"], testTimeout: 30000, - globalTeardown: "./tests/globalTeardown.ts", transform: { "^.+\\.(t|j)s$": ["ts-jest", { tsconfig: "tsconfig.test.json" }], }, diff --git a/integration_test/package-lock.json b/integration_test/package-lock.json index b0f450999..1b1c67ced 100644 --- a/integration_test/package-lock.json +++ b/integration_test/package-lock.json @@ -6,10 +6,10 @@ "": { "name": "integration_test", "dependencies": { - "@firebase/analytics": "^0.10.0", + "@google-cloud/tasks": "^5.1.0", "firebase": "^8.2.3", "firebase-admin": "^11.11.0", - "firebase-tools": "^12.9.1", + "firebase-tools": "^13.3.0", "js-yaml": "^4.1.0" }, "devDependencies": { @@ -23,6 +23,8 @@ }, "node_modules/@ampproject/remapping": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -35,6 +37,8 @@ }, "node_modules/@apidevtools/json-schema-ref-parser": { "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", + "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", "license": "MIT", "dependencies": { "@jsdevtools/ono": "^7.1.3", @@ -45,6 +49,8 @@ }, "node_modules/@babel/code-frame": { "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "license": "MIT", "dependencies": { @@ -57,6 +63,8 @@ }, "node_modules/@babel/code-frame/node_modules/ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "license": "MIT", "dependencies": { @@ -68,6 +76,8 @@ }, "node_modules/@babel/code-frame/node_modules/chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "license": "MIT", "dependencies": { @@ -81,6 +91,8 @@ }, "node_modules/@babel/code-frame/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "license": "MIT", "engines": { @@ -89,6 +101,8 @@ }, "node_modules/@babel/code-frame/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "license": "MIT", "dependencies": { @@ -166,6 +180,8 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "license": "ISC", "dependencies": { @@ -174,11 +190,15 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "license": "ISC" }, "node_modules/@babel/helper-environment-visitor": { "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "license": "MIT", "engines": { @@ -187,6 +207,8 @@ }, "node_modules/@babel/helper-function-name": { "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "license": "MIT", "dependencies": { @@ -199,6 +221,8 @@ }, "node_modules/@babel/helper-hoist-variables": { "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "license": "MIT", "dependencies": { @@ -210,6 +234,8 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, "license": "MIT", "dependencies": { @@ -221,6 +247,8 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -239,6 +267,8 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", "dev": true, "license": "MIT", "engines": { @@ -247,6 +277,8 @@ }, "node_modules/@babel/helper-simple-access": { "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "license": "MIT", "dependencies": { @@ -258,6 +290,8 @@ }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "license": "MIT", "dependencies": { @@ -269,6 +303,8 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "dev": true, "license": "MIT", "engines": { @@ -277,6 +313,8 @@ }, "node_modules/@babel/helper-validator-identifier": { "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "license": "MIT", "engines": { @@ -306,6 +344,8 @@ }, "node_modules/@babel/highlight": { "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "license": "MIT", "dependencies": { @@ -319,6 +359,8 @@ }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "license": "MIT", "dependencies": { @@ -330,6 +372,8 @@ }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "license": "MIT", "dependencies": { @@ -343,6 +387,8 @@ }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "license": "MIT", "engines": { @@ -351,6 +397,8 @@ }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "license": "MIT", "dependencies": { @@ -373,6 +421,8 @@ }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, "license": "MIT", "dependencies": { @@ -384,6 +434,8 @@ }, "node_modules/@babel/plugin-syntax-bigint": { "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, "license": "MIT", "dependencies": { @@ -395,6 +447,8 @@ }, "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, "license": "MIT", "dependencies": { @@ -406,6 +460,8 @@ }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, "license": "MIT", "dependencies": { @@ -417,6 +473,8 @@ }, "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, "license": "MIT", "dependencies": { @@ -428,6 +486,8 @@ }, "node_modules/@babel/plugin-syntax-jsx": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", "dev": true, "license": "MIT", "dependencies": { @@ -442,6 +502,8 @@ }, "node_modules/@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, "license": "MIT", "dependencies": { @@ -453,6 +515,8 @@ }, "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, "license": "MIT", "dependencies": { @@ -464,6 +528,8 @@ }, "node_modules/@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, "license": "MIT", "dependencies": { @@ -475,6 +541,8 @@ }, "node_modules/@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, "license": "MIT", "dependencies": { @@ -486,6 +554,8 @@ }, "node_modules/@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, "license": "MIT", "dependencies": { @@ -497,6 +567,8 @@ }, "node_modules/@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, "license": "MIT", "dependencies": { @@ -508,6 +580,8 @@ }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, "license": "MIT", "dependencies": { @@ -522,6 +596,8 @@ }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", "dev": true, "license": "MIT", "dependencies": { @@ -582,11 +658,15 @@ }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true, "license": "MIT" }, "node_modules/@colors/colors": { "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", "license": "MIT", "engines": { "node": ">=0.1.90" @@ -594,6 +674,8 @@ }, "node_modules/@dabh/diagnostics": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", "license": "MIT", "dependencies": { "colorspace": "1.1.x", @@ -603,6 +685,8 @@ }, "node_modules/@fastify/busboy": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.2.1.tgz", + "integrity": "sha512-7PQA7EH43S0CxcOa9OeAnaeA0oQ+e/DHNPZwSQM9CQHW76jle5+OvLdibRp/Aafs9KXbLhxyjOTkRjWUbQEd3Q==", "license": "MIT", "dependencies": { "text-decoding": "^1.0.0" @@ -611,21 +695,6 @@ "node": ">=14" } }, - "node_modules/@firebase/analytics": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.0.tgz", - "integrity": "sha512-Locv8gAqx0e+GX/0SI3dzmBY5e9kjVDtD+3zCFLJ0tH2hJwuCAiL+5WkHuxKj92rqQj/rvkBUCfA1ewlX2hehg==", - "dependencies": { - "@firebase/component": "0.6.4", - "@firebase/installations": "0.6.4", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.3", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, "node_modules/@firebase/analytics-types": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.6.0.tgz", @@ -695,6 +764,8 @@ }, "node_modules/@firebase/app-types": { "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz", + "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==", "license": "Apache-2.0" }, "node_modules/@firebase/auth": { @@ -710,6 +781,8 @@ }, "node_modules/@firebase/auth-interop-types": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz", + "integrity": "sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg==", "license": "Apache-2.0" }, "node_modules/@firebase/auth-types": { @@ -723,6 +796,8 @@ }, "node_modules/@firebase/component": { "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.4.tgz", + "integrity": "sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA==", "license": "Apache-2.0", "dependencies": { "@firebase/util": "1.9.3", @@ -731,6 +806,8 @@ }, "node_modules/@firebase/database": { "version": "0.14.4", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.14.4.tgz", + "integrity": "sha512-+Ea/IKGwh42jwdjCyzTmeZeLM3oy1h0mFPsTy6OqCWzcu/KFqRAr5Tt1HRCOBlNOdbh84JPZC47WLU18n2VbxQ==", "license": "Apache-2.0", "dependencies": { "@firebase/auth-interop-types": "0.2.1", @@ -743,6 +820,8 @@ }, "node_modules/@firebase/database-compat": { "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.3.4.tgz", + "integrity": "sha512-kuAW+l+sLMUKBThnvxvUZ+Q1ZrF/vFJ58iUY9kAcbX48U03nVzIF6Tmkf0p3WVQwMqiXguSgtOPIB6ZCeF+5Gg==", "license": "Apache-2.0", "dependencies": { "@firebase/component": "0.6.4", @@ -755,6 +834,8 @@ }, "node_modules/@firebase/database-types": { "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.10.4.tgz", + "integrity": "sha512-dPySn0vJ/89ZeBac70T+2tWWPiJXWbmRygYv0smT5TfE3hDrQ09eKMF3Y+vMlTdrMWq7mUdYW5REWPSGH4kAZQ==", "license": "Apache-2.0", "dependencies": { "@firebase/app-types": "0.9.0", @@ -974,20 +1055,6 @@ } } }, - "node_modules/@firebase/installations": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.4.tgz", - "integrity": "sha512-u5y88rtsp7NYkCHC3ElbFBrPtieUybZluXyzl7+4BsIz4sqb4vSAuwHEUgCgCeaQhvsnxDEU6icly8U9zsJigA==", - "dependencies": { - "@firebase/component": "0.6.4", - "@firebase/util": "1.9.3", - "idb": "7.0.1", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, "node_modules/@firebase/installations-types": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.3.4.tgz", @@ -996,13 +1063,10 @@ "@firebase/app-types": "0.x" } }, - "node_modules/@firebase/installations/node_modules/idb": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz", - "integrity": "sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg==" - }, "node_modules/@firebase/logger": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz", + "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" @@ -1279,6 +1343,8 @@ }, "node_modules/@firebase/util": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" @@ -1333,6 +1399,8 @@ }, "node_modules/@google-cloud/paginator": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.7.tgz", + "integrity": "sha512-jJNutk0arIQhmpUUQJPJErsojqo834KcyB6X7a1mxuic8i1tKXxde8E69IZxNZawRIlZdIK2QY4WALvlK5MzYQ==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -1345,6 +1413,8 @@ }, "node_modules/@google-cloud/precise-date": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/precise-date/-/precise-date-3.0.1.tgz", + "integrity": "sha512-crK2rgNFfvLoSgcKJY7ZBOLW91IimVNmPfi1CL+kMTf78pTJYd29XqEVedAeBu4DwCJc0EDIp1MpctLgoPq+Uw==", "license": "Apache-2.0", "engines": { "node": ">=12.0.0" @@ -1352,6 +1422,8 @@ }, "node_modules/@google-cloud/projectify": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz", + "integrity": "sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA==", "license": "Apache-2.0", "engines": { "node": ">=12.0.0" @@ -1359,6 +1431,8 @@ }, "node_modules/@google-cloud/promisify": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.4.tgz", + "integrity": "sha512-j8yRSSqswWi1QqUGKVEKOG03Q7qOoZP6/h2zN2YO+F5h2+DHU0bSrHCK9Y7lo2DI9fBd8qGAw795sf+3Jva4yA==", "license": "Apache-2.0", "engines": { "node": ">=10" @@ -1366,6 +1440,8 @@ }, "node_modules/@google-cloud/pubsub": { "version": "3.7.5", + "resolved": "https://registry.npmjs.org/@google-cloud/pubsub/-/pubsub-3.7.5.tgz", + "integrity": "sha512-4Qrry4vIToth5mqduVslltWVsyb7DR8OhnkBA3F7XiE0jgQsiuUfwp/RB2F559aXnRbwcfmjvP4jSuEaGcjrCQ==", "license": "Apache-2.0", "dependencies": { "@google-cloud/paginator": "^4.0.0", @@ -1391,6 +1467,8 @@ }, "node_modules/@google-cloud/pubsub/node_modules/@google-cloud/paginator": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-4.0.1.tgz", + "integrity": "sha512-6G1ui6bWhNyHjmbYwavdN7mpVPRBtyDg/bfqBTAlwr413On2TnFNfDxc9UhTJctkgoCDgQXEKiRPLPR9USlkbQ==", "license": "Apache-2.0", "dependencies": { "arrify": "^2.0.0", @@ -1402,6 +1480,8 @@ }, "node_modules/@google-cloud/storage": { "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.12.0.tgz", + "integrity": "sha512-78nNAY7iiZ4O/BouWMWTD/oSF2YtYgYB3GZirn0To6eBOugjXVoK+GXgUXOl+HlqbAOyHxAVXOlsj3snfbQ1dw==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -1430,6 +1510,8 @@ }, "node_modules/@google-cloud/storage/node_modules/@google-cloud/promisify": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-3.0.1.tgz", + "integrity": "sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA==", "license": "Apache-2.0", "optional": true, "engines": { @@ -1438,6 +1520,8 @@ }, "node_modules/@google-cloud/storage/node_modules/mime": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", "license": "MIT", "optional": true, "bin": { @@ -1447,8 +1531,218 @@ "node": ">=10.0.0" } }, + "node_modules/@google-cloud/tasks": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@google-cloud/tasks/-/tasks-5.1.0.tgz", + "integrity": "sha512-6TU2BqK5G62iLSiNzIAK7EBXJzDtjY9kiOjvXm1bcZAnRbmlow+2QtunSWzRlcLYJW9oz4v4mTGkuvNWa/QC0A==", + "dependencies": { + "google-gax": "^4.0.4" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@google-cloud/tasks/node_modules/@grpc/grpc-js": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.1.tgz", + "integrity": "sha512-55ONqFytZExfOIjF1RjXPcVmT/jJqFzbbDqxK9jmRV4nxiYWtL9hENSW1Jfx0SdZfrvoqd44YJ/GJTqfRrawSQ==", + "dependencies": { + "@grpc/proto-loader": "^0.7.8", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@google-cloud/tasks/node_modules/gaxios": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.2.0.tgz", + "integrity": "sha512-H6+bHeoEAU5D6XNc6mPKeN5dLZqEDs9Gpk6I+SZBEzK5So58JVrHPmevNi35fRl1J9Y5TaeLW0kYx3pCJ1U2mQ==", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/tasks/node_modules/gcp-metadata": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", + "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", + "dependencies": { + "gaxios": "^6.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/tasks/node_modules/google-auth-library": { + "version": "9.6.3", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.6.3.tgz", + "integrity": "sha512-4CacM29MLC2eT9Cey5GDVK4Q8t+MMp8+OEdOaqD9MG6b0dOyLORaaeJMPQ7EESVgm/+z5EKYyFLxgzBJlJgyHQ==", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/tasks/node_modules/google-gax": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.3.1.tgz", + "integrity": "sha512-qpSfslpwqToIgQ+Tf3MjWIDjYK4UFIZ0uz6nLtttlW9N1NQA4PhGf9tlGo6KDYJ4rgL2w4CjXVd0z5yeNpN/Iw==", + "dependencies": { + "@grpc/grpc-js": "~1.10.0", + "@grpc/proto-loader": "^0.7.0", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "google-auth-library": "^9.3.0", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^2.0.0", + "protobufjs": "7.2.6", + "retry-request": "^7.0.0", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/tasks/node_modules/gtoken": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", + "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", + "dependencies": { + "gaxios": "^6.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/tasks/node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@google-cloud/tasks/node_modules/proto3-json-serializer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.1.tgz", + "integrity": "sha512-8awBvjO+FwkMd6gNoGFZyqkHZXCFd54CIYTb6De7dPaufGJ2XNW+QUNqbMr8MaAocMdb+KpsD4rxEOaTBDCffA==", + "dependencies": { + "protobufjs": "^7.2.5" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/tasks/node_modules/protobufjs": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", + "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@google-cloud/tasks/node_modules/retry-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", + "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", + "dependencies": { + "@types/request": "^2.48.8", + "extend": "^3.0.2", + "teeny-request": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/tasks/node_modules/teeny-request": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", + "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", + "dependencies": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.9", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/tasks/node_modules/teeny-request/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@google-cloud/tasks/node_modules/teeny-request/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@google-cloud/tasks/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@grpc/grpc-js": { "version": "1.8.21", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.21.tgz", + "integrity": "sha512-KeyQeZpxeEBSqFVTi3q2K7PiPXmgBfECc4updA1ejCLjYmoAlvvM3ZMp5ztTDUCUQmoY3CpDxvchjO1+rFkoHg==", "license": "Apache-2.0", "dependencies": { "@grpc/proto-loader": "^0.7.0", @@ -1460,6 +1754,8 @@ }, "node_modules/@grpc/proto-loader": { "version": "0.7.10", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz", + "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==", "license": "Apache-2.0", "dependencies": { "lodash.camelcase": "^4.3.0", @@ -1498,6 +1794,8 @@ }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "license": "ISC", "dependencies": { @@ -1522,6 +1820,8 @@ }, "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "license": "MIT", "engines": { @@ -1543,6 +1843,8 @@ }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, "license": "MIT", "engines": { @@ -1551,6 +1853,8 @@ }, "node_modules/@jest/console": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "license": "MIT", "dependencies": { @@ -1567,6 +1871,8 @@ }, "node_modules/@jest/core": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "license": "MIT", "dependencies": { @@ -1613,6 +1919,8 @@ }, "node_modules/@jest/environment": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "license": "MIT", "dependencies": { @@ -1627,6 +1935,8 @@ }, "node_modules/@jest/expect": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1639,6 +1949,8 @@ }, "node_modules/@jest/expect-utils": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "license": "MIT", "dependencies": { @@ -1650,6 +1962,8 @@ }, "node_modules/@jest/fake-timers": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1666,6 +1980,8 @@ }, "node_modules/@jest/globals": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1680,6 +1996,8 @@ }, "node_modules/@jest/reporters": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, "license": "MIT", "dependencies": { @@ -1722,6 +2040,8 @@ }, "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -1751,6 +2071,8 @@ }, "node_modules/@jest/schemas": { "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", "dependencies": { @@ -1762,6 +2084,8 @@ }, "node_modules/@jest/source-map": { "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "license": "MIT", "dependencies": { @@ -1775,6 +2099,8 @@ }, "node_modules/@jest/test-result": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "license": "MIT", "dependencies": { @@ -1789,6 +2115,8 @@ }, "node_modules/@jest/test-sequencer": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "license": "MIT", "dependencies": { @@ -1803,6 +2131,8 @@ }, "node_modules/@jest/transform": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "license": "MIT", "dependencies": { @@ -1828,6 +2158,8 @@ }, "node_modules/@jest/transform/node_modules/write-file-atomic": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "license": "ISC", "dependencies": { @@ -1840,6 +2172,8 @@ }, "node_modules/@jest/types": { "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "license": "MIT", "dependencies": { @@ -1856,6 +2190,8 @@ }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1877,6 +2213,8 @@ }, "node_modules/@jridgewell/set-array": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, "license": "MIT", "engines": { @@ -1885,6 +2223,8 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true, "license": "MIT" }, @@ -1899,6 +2239,8 @@ }, "node_modules/@jsdevtools/ono": { "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", "license": "MIT" }, "node_modules/@jsdoc/salty": { @@ -1958,6 +2300,8 @@ }, "node_modules/@opentelemetry/semantic-conventions": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.3.1.tgz", + "integrity": "sha512-wU5J8rUoo32oSef/rFpOT1HIjLjAv3qIDHkw1QIhODV3OpAVHi5oVzlouozg9obUmZKtbZ0qUe/m7FP0y0yBzA==", "license": "Apache-2.0", "engines": { "node": ">=8.12.0" @@ -1965,6 +2309,8 @@ }, "node_modules/@pnpm/config.env-replace": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", "license": "MIT", "engines": { "node": ">=12.22.0" @@ -1972,6 +2318,8 @@ }, "node_modules/@pnpm/network.ca-file": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", "license": "MIT", "dependencies": { "graceful-fs": "4.2.10" @@ -1982,10 +2330,14 @@ }, "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "license": "ISC" }, "node_modules/@pnpm/npm-conf": { "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", + "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", "license": "MIT", "dependencies": { "@pnpm/config.env-replace": "^1.1.0", @@ -1998,22 +2350,32 @@ }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/base64": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/codegen": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/fetch": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.1", @@ -2022,26 +2384,38 @@ }, "node_modules/@protobufjs/float": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/inquire": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/path": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/pool": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/utf8": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", "license": "BSD-3-Clause" }, "node_modules/@sinclair/typebox": { "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true, "license": "MIT" }, @@ -2055,6 +2429,8 @@ }, "node_modules/@sinonjs/fake-timers": { "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -2063,18 +2439,23 @@ }, "node_modules/@tootallnate/once": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "license": "MIT", - "optional": true, "engines": { "node": ">= 10" } }, "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", "license": "MIT" }, "node_modules/@types/babel__core": { "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "license": "MIT", "dependencies": { @@ -2095,6 +2476,8 @@ }, "node_modules/@types/babel__template": { "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "license": "MIT", "dependencies": { @@ -2112,14 +2495,23 @@ }, "node_modules/@types/body-parser": { "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", "license": "MIT", "dependencies": { "@types/connect": "*", "@types/node": "*" } }, + "node_modules/@types/caseless": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", + "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==" + }, "node_modules/@types/connect": { "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -2134,6 +2526,8 @@ }, "node_modules/@types/express": { "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "license": "MIT", "dependencies": { "@types/body-parser": "*", @@ -2164,6 +2558,8 @@ }, "node_modules/@types/glob": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", "license": "MIT", "dependencies": { "@types/minimatch": "^5.1.2", @@ -2172,6 +2568,8 @@ }, "node_modules/@types/graceful-fs": { "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2180,15 +2578,21 @@ }, "node_modules/@types/http-errors": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "license": "MIT" }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true, "license": "MIT" }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dev": true, "license": "MIT", "dependencies": { @@ -2197,6 +2601,8 @@ }, "node_modules/@types/istanbul-reports": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2225,6 +2631,8 @@ }, "node_modules/@types/jsonwebtoken": { "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz", + "integrity": "sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -2236,10 +2644,14 @@ }, "node_modules/@types/long": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", "license": "MIT" }, "node_modules/@types/markdown-it": { "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", "license": "MIT", "dependencies": { "@types/linkify-it": "*", @@ -2252,10 +2664,14 @@ }, "node_modules/@types/mime": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.4.tgz", + "integrity": "sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==", "license": "MIT" }, "node_modules/@types/minimatch": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", "license": "MIT" }, "node_modules/@types/node": { @@ -2281,10 +2697,38 @@ }, "node_modules/@types/range-parser": { "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "license": "MIT" }, + "node_modules/@types/request": { + "version": "2.48.12", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz", + "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==", + "dependencies": { + "@types/caseless": "*", + "@types/node": "*", + "@types/tough-cookie": "*", + "form-data": "^2.5.0" + } + }, + "node_modules/@types/request/node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, "node_modules/@types/rimraf": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==", "license": "MIT", "dependencies": { "@types/glob": "*", @@ -2293,6 +2737,8 @@ }, "node_modules/@types/send": { "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "license": "MIT", "dependencies": { "@types/mime": "^1", @@ -2301,6 +2747,8 @@ }, "node_modules/@types/send/node_modules/@types/mime": { "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "license": "MIT" }, "node_modules/@types/send/node_modules/@types/node": { @@ -2312,6 +2760,8 @@ }, "node_modules/@types/serve-static": { "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", "license": "MIT", "dependencies": { "@types/http-errors": "*", @@ -2321,15 +2771,24 @@ }, "node_modules/@types/stack-utils": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true, "license": "MIT" }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==" + }, "node_modules/@types/triple-beam": { "version": "1.3.4", "license": "MIT" }, "node_modules/@types/yargs": { "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", "dev": true, "license": "MIT", "dependencies": { @@ -2338,6 +2797,8 @@ }, "node_modules/@types/yargs-parser": { "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true, "license": "MIT" }, @@ -2348,6 +2809,8 @@ }, "node_modules/abort-controller": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "license": "MIT", "dependencies": { "event-target-shim": "^5.0.0" @@ -2358,6 +2821,8 @@ }, "node_modules/accepts": { "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "license": "MIT", "dependencies": { "mime-types": "~2.1.34", @@ -2379,6 +2844,8 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -2386,6 +2853,8 @@ }, "node_modules/agent-base": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", "license": "MIT", "dependencies": { "debug": "^4.3.4" @@ -2407,6 +2876,8 @@ }, "node_modules/aggregate-error": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "license": "MIT", "optional": true, "dependencies": { @@ -2419,7 +2890,8 @@ }, "node_modules/ajv": { "version": "6.12.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2433,10 +2905,13 @@ }, "node_modules/ajv/node_modules/json-schema-traverse": { "version": "0.4.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/ansi-align": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "license": "ISC", "dependencies": { "string-width": "^4.1.0" @@ -2444,6 +2919,8 @@ }, "node_modules/ansi-escapes": { "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "license": "MIT", "dependencies": { "type-fest": "^0.21.3" @@ -2457,6 +2934,8 @@ }, "node_modules/ansi-regex": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", "engines": { "node": ">=8" @@ -2464,6 +2943,8 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -2477,6 +2958,8 @@ }, "node_modules/ansi-styles/node_modules/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -2487,10 +2970,14 @@ }, "node_modules/ansicolors": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==", "license": "MIT" }, "node_modules/anymatch": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -2507,6 +2994,8 @@ }, "node_modules/archiver": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", "license": "MIT", "dependencies": { "archiver-utils": "^2.1.0", @@ -2523,6 +3012,8 @@ }, "node_modules/archiver-utils": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", "license": "MIT", "dependencies": { "glob": "^7.1.4", @@ -2542,10 +3033,14 @@ }, "node_modules/archiver-utils/node_modules/isarray": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "license": "MIT" }, "node_modules/archiver-utils/node_modules/readable-stream": { "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", @@ -2559,10 +3054,14 @@ }, "node_modules/archiver-utils/node_modules/safe-buffer": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, "node_modules/archiver-utils/node_modules/string_decoder": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" @@ -2582,14 +3081,20 @@ }, "node_modules/argparse": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "license": "Python-2.0" }, "node_modules/array-flatten": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, "node_modules/arrify": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", "license": "MIT", "engines": { "node": ">=8" @@ -2597,24 +3102,14 @@ }, "node_modules/as-array": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/as-array/-/as-array-2.0.0.tgz", + "integrity": "sha512-1Sd1LrodN0XYxYeZcN1J4xYZvmvTwD5tDWaPUGPIzH1mFsmzsPnVtd2exWhecMjtZk/wYWjNZJiD3b1SLCeJqg==", "license": "MIT" }, - "node_modules/asn1": { - "version": "0.2.6", - "license": "MIT", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, "node_modules/ast-types": { "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", "license": "MIT", "dependencies": { "tslib": "^2.0.1" @@ -2629,10 +3124,14 @@ }, "node_modules/async-lock": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.3.2.tgz", + "integrity": "sha512-phnXdS3RP7PPcmP6NWWzWMU0sLTeyvtZCxBPpZdkYE3seGLKSQZs9FrmVO/qwypq98FUtWWUEYxziLkdGk5nnA==", "license": "MIT" }, "node_modules/async-retry": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", "license": "MIT", "optional": true, "dependencies": { @@ -2641,21 +3140,14 @@ }, "node_modules/asynckit": { "version": "0.4.0", - "license": "MIT" - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.12.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, "node_modules/babel-jest": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "license": "MIT", "dependencies": { @@ -2676,6 +3168,8 @@ }, "node_modules/babel-plugin-istanbul": { "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -2691,6 +3185,8 @@ }, "node_modules/babel-plugin-jest-hoist": { "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "license": "MIT", "dependencies": { @@ -2705,6 +3201,8 @@ }, "node_modules/babel-preset-current-node-syntax": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2727,6 +3225,8 @@ }, "node_modules/babel-preset-jest": { "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "license": "MIT", "dependencies": { @@ -2742,10 +3242,14 @@ }, "node_modules/balanced-match": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "funding": [ { "type": "github", @@ -2764,6 +3268,8 @@ }, "node_modules/basic-auth": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", "license": "MIT", "dependencies": { "safe-buffer": "5.1.2" @@ -2774,10 +3280,14 @@ }, "node_modules/basic-auth-connect": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", + "integrity": "sha512-kiV+/DTgVro4aZifY/hwRwALBISViL5NP4aReaR2EVJEObpbUBHIkdJh/YpcoEiYt7nBodZ6U2ajZeZvSxUCCg==", "license": "MIT" }, "node_modules/basic-auth/node_modules/safe-buffer": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, "node_modules/basic-ftp": { @@ -2787,15 +3297,10 @@ "node": ">=10.0.0" } }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "license": "BSD-3-Clause", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, "node_modules/bignumber.js": { "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", "license": "MIT", "engines": { "node": "*" @@ -2803,6 +3308,8 @@ }, "node_modules/binary-extensions": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "license": "MIT", "engines": { "node": ">=8" @@ -2810,6 +3317,8 @@ }, "node_modules/bl": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "license": "MIT", "dependencies": { "buffer": "^5.5.0", @@ -2819,10 +3328,14 @@ }, "node_modules/bluebird": { "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "license": "MIT" }, "node_modules/body-parser": { "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -2845,6 +3358,8 @@ }, "node_modules/body-parser/node_modules/debug": { "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -2852,10 +3367,14 @@ }, "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, "node_modules/boxen": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", "license": "MIT", "dependencies": { "ansi-align": "^3.0.0", @@ -2876,6 +3395,8 @@ }, "node_modules/boxen/node_modules/type-fest": { "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" @@ -2886,6 +3407,8 @@ }, "node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -2893,6 +3416,8 @@ }, "node_modules/braces": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "license": "MIT", "dependencies": { "fill-range": "^7.0.1" @@ -2946,6 +3471,8 @@ }, "node_modules/bser": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2954,6 +3481,8 @@ }, "node_modules/buffer": { "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "funding": [ { "type": "github", @@ -2976,6 +3505,8 @@ }, "node_modules/buffer-crc32": { "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "license": "MIT", "engines": { "node": "*" @@ -2983,15 +3514,21 @@ }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", "license": "BSD-3-Clause" }, "node_modules/buffer-from": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, "license": "MIT" }, "node_modules/bytes": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -3053,6 +3590,8 @@ }, "node_modules/cacache/node_modules/minimatch": { "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "license": "ISC", "optional": true, "dependencies": { @@ -3076,10 +3615,14 @@ }, "node_modules/call-me-maybe": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", "license": "MIT" }, "node_modules/callsites": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "license": "MIT", "engines": { @@ -3088,6 +3631,8 @@ }, "node_modules/camelcase": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "license": "MIT", "engines": { "node": ">=10" @@ -3117,6 +3662,8 @@ }, "node_modules/cardinal": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", "license": "MIT", "dependencies": { "ansicolors": "~0.3.2", @@ -3126,12 +3673,10 @@ "cdl": "bin/cdl.js" } }, - "node_modules/caseless": { - "version": "0.12.0", - "license": "Apache-2.0" - }, "node_modules/catharsis": { "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", "license": "MIT", "dependencies": { "lodash": "^4.17.15" @@ -3142,6 +3687,8 @@ }, "node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -3156,6 +3703,8 @@ }, "node_modules/char-regex": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, "license": "MIT", "engines": { @@ -3164,6 +3713,8 @@ }, "node_modules/chardet": { "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "license": "MIT" }, "node_modules/chokidar": { @@ -3193,6 +3744,8 @@ }, "node_modules/chownr": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "license": "ISC", "engines": { "node": ">=10" @@ -3200,6 +3753,8 @@ }, "node_modules/ci-info": { "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, "funding": [ { @@ -3214,11 +3769,15 @@ }, "node_modules/cjs-module-lexer": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true, "license": "MIT" }, "node_modules/cjson": { "version": "0.3.3", + "resolved": "https://registry.npmjs.org/cjson/-/cjson-0.3.3.tgz", + "integrity": "sha512-yKNcXi/Mvi5kb1uK0sahubYiyfUO2EUgOp4NcY9+8NX5Xmc+4yeNogZuLFkpLBBj7/QI9MjRUIuXrV9XOw5kVg==", "license": "MIT", "dependencies": { "json-parse-helpfulerror": "^1.0.3" @@ -3229,6 +3788,8 @@ }, "node_modules/clean-stack": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "license": "MIT", "optional": true, "engines": { @@ -3237,6 +3798,8 @@ }, "node_modules/cli-boxes": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "license": "MIT", "engines": { "node": ">=6" @@ -3247,6 +3810,8 @@ }, "node_modules/cli-cursor": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" @@ -3267,6 +3832,8 @@ }, "node_modules/cli-table": { "version": "0.3.11", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", + "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", "dependencies": { "colors": "1.0.3" }, @@ -3276,6 +3843,8 @@ }, "node_modules/cli-table3": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", + "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", "license": "MIT", "dependencies": { "string-width": "^4.2.0" @@ -3289,6 +3858,8 @@ }, "node_modules/cli-table3/node_modules/@colors/colors": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "license": "MIT", "optional": true, "engines": { @@ -3297,6 +3868,8 @@ }, "node_modules/cli-width": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "license": "ISC", "engines": { "node": ">= 10" @@ -3304,6 +3877,8 @@ }, "node_modules/cliui": { "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -3316,6 +3891,8 @@ }, "node_modules/clone": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "license": "MIT", "engines": { "node": ">=0.8" @@ -3323,6 +3900,8 @@ }, "node_modules/co": { "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, "license": "MIT", "engines": { @@ -3332,11 +3911,15 @@ }, "node_modules/collect-v8-coverage": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true, "license": "MIT" }, "node_modules/color": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", "license": "MIT", "dependencies": { "color-convert": "^1.9.3", @@ -3345,6 +3928,8 @@ }, "node_modules/color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "license": "MIT", "dependencies": { "color-name": "1.1.3" @@ -3352,14 +3937,20 @@ }, "node_modules/color-convert/node_modules/color-name": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "license": "MIT" }, "node_modules/color-name": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, "node_modules/color-string": { "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "license": "MIT", "dependencies": { "color-name": "^1.0.0", @@ -3376,10 +3967,14 @@ }, "node_modules/colorette": { "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "license": "MIT" }, "node_modules/colors": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", "license": "MIT", "engines": { "node": ">=0.1.90" @@ -3387,6 +3982,8 @@ }, "node_modules/colorspace": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", "license": "MIT", "dependencies": { "color": "^3.1.3", @@ -3395,6 +3992,8 @@ }, "node_modules/combined-stream": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -3405,6 +4004,8 @@ }, "node_modules/commander": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "license": "MIT", "engines": { "node": ">= 6" @@ -3412,6 +4013,8 @@ }, "node_modules/compress-commons": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", "license": "MIT", "dependencies": { "buffer-crc32": "^0.2.13", @@ -3425,6 +4028,8 @@ }, "node_modules/compressible": { "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "license": "MIT", "dependencies": { "mime-db": ">= 1.43.0 < 2" @@ -3435,6 +4040,8 @@ }, "node_modules/compression": { "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", "license": "MIT", "dependencies": { "accepts": "~1.3.5", @@ -3451,6 +4058,8 @@ }, "node_modules/compression/node_modules/bytes": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -3458,6 +4067,8 @@ }, "node_modules/compression/node_modules/debug": { "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -3465,18 +4076,26 @@ }, "node_modules/compression/node_modules/ms": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, "node_modules/compression/node_modules/safe-buffer": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, "node_modules/config-chain": { "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "license": "MIT", "dependencies": { "ini": "^1.3.4", @@ -3485,6 +4104,8 @@ }, "node_modules/configstore": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", "license": "BSD-2-Clause", "dependencies": { "dot-prop": "^5.2.0", @@ -3500,6 +4121,8 @@ }, "node_modules/connect": { "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -3513,6 +4136,8 @@ }, "node_modules/connect/node_modules/debug": { "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -3520,6 +4145,8 @@ }, "node_modules/connect/node_modules/finalhandler": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -3536,10 +4163,14 @@ }, "node_modules/connect/node_modules/ms": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, "node_modules/connect/node_modules/on-finished": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", "license": "MIT", "dependencies": { "ee-first": "1.1.1" @@ -3550,6 +4181,8 @@ }, "node_modules/connect/node_modules/statuses": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -3562,6 +4195,8 @@ }, "node_modules/content-disposition": { "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" @@ -3572,6 +4207,8 @@ }, "node_modules/content-type": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -3579,11 +4216,15 @@ }, "node_modules/convert-source-map": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, "node_modules/cookie": { "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -3591,6 +4232,8 @@ }, "node_modules/cookie-signature": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, "node_modules/core-js": { @@ -3606,10 +4249,14 @@ }, "node_modules/core-util-is": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "license": "MIT" }, "node_modules/cors": { "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "license": "MIT", "dependencies": { "object-assign": "^4", @@ -3621,6 +4268,8 @@ }, "node_modules/crc-32": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", "license": "Apache-2.0", "bin": { "crc32": "bin/crc32.njs" @@ -3631,6 +4280,8 @@ }, "node_modules/crc32-stream": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", "license": "MIT", "dependencies": { "crc-32": "^1.2.0", @@ -3642,6 +4293,8 @@ }, "node_modules/create-jest": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", "dev": true, "license": "MIT", "dependencies": { @@ -3662,6 +4315,8 @@ }, "node_modules/cross-env": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.1.tgz", + "integrity": "sha512-1yHhtcfAd1r4nwQgknowuUNfIT9E8dOMMspC36g45dN+iD1blloi7xp8X/xAIDnjHWyt1uQ8PHk2fkNaym7soQ==", "license": "MIT", "dependencies": { "cross-spawn": "^6.0.5" @@ -3676,6 +4331,8 @@ }, "node_modules/cross-env/node_modules/cross-spawn": { "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "license": "MIT", "dependencies": { "nice-try": "^1.0.4", @@ -3690,6 +4347,8 @@ }, "node_modules/cross-env/node_modules/path-key": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "license": "MIT", "engines": { "node": ">=4" @@ -3697,6 +4356,8 @@ }, "node_modules/cross-env/node_modules/semver": { "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "license": "ISC", "bin": { "semver": "bin/semver" @@ -3704,6 +4365,8 @@ }, "node_modules/cross-env/node_modules/shebang-command": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "license": "MIT", "dependencies": { "shebang-regex": "^1.0.0" @@ -3714,6 +4377,8 @@ }, "node_modules/cross-env/node_modules/shebang-regex": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -3721,6 +4386,8 @@ }, "node_modules/cross-env/node_modules/which": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -3731,6 +4398,8 @@ }, "node_modules/cross-spawn": { "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -3743,6 +4412,8 @@ }, "node_modules/crypto-random-string": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "license": "MIT", "engines": { "node": ">=8" @@ -3752,16 +4423,6 @@ "version": "5.5.2", "license": "MIT" }, - "node_modules/dashdash": { - "version": "1.14.1", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/data-uri-to-buffer": { "version": "6.0.1", "license": "MIT", @@ -3771,6 +4432,8 @@ }, "node_modules/debug": { "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "license": "MIT", "dependencies": { "ms": "2.1.2" @@ -3786,10 +4449,14 @@ }, "node_modules/debug/node_modules/ms": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "license": "MIT" }, "node_modules/dedent": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -3803,6 +4470,8 @@ }, "node_modules/deep-extend": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "license": "MIT", "engines": { "node": ">=4.0.0" @@ -3810,14 +4479,20 @@ }, "node_modules/deep-freeze": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz", + "integrity": "sha512-Z+z8HiAvsGwmjqlphnHW5oz6yWlOwu6EQfFTjmeTWlDeda3FS2yv3jhq35TX/ewmsnqB+RX2IdsIOyjJCQN5tg==", "license": "public domain" }, "node_modules/deep-is": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "license": "MIT" }, "node_modules/deepmerge": { "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, "license": "MIT", "engines": { @@ -3826,6 +4501,8 @@ }, "node_modules/defaults": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "license": "MIT", "dependencies": { "clone": "^1.0.2" @@ -3848,6 +4525,8 @@ }, "node_modules/degenerator": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", "license": "MIT", "dependencies": { "ast-types": "^0.13.4", @@ -3860,6 +4539,8 @@ }, "node_modules/degenerator/node_modules/escodegen": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", "license": "BSD-2-Clause", "dependencies": { "esprima": "^4.0.1", @@ -3879,6 +4560,8 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", "engines": { "node": ">=0.4.0" @@ -3891,6 +4574,8 @@ }, "node_modules/depd": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -3898,6 +4583,8 @@ }, "node_modules/destroy": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "license": "MIT", "engines": { "node": ">= 0.8", @@ -3906,6 +4593,8 @@ }, "node_modules/detect-newline": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, "license": "MIT", "engines": { @@ -3914,6 +4603,8 @@ }, "node_modules/diff-sequences": { "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "license": "MIT", "engines": { @@ -3930,6 +4621,8 @@ }, "node_modules/dot-prop": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "license": "MIT", "dependencies": { "is-obj": "^2.0.0" @@ -3940,6 +4633,8 @@ }, "node_modules/duplexify": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", "license": "MIT", "dependencies": { "end-of-stream": "^1.4.1", @@ -3948,16 +4643,10 @@ "stream-shift": "^1.0.0" } }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "license": "MIT", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" @@ -3965,6 +4654,8 @@ }, "node_modules/ee-first": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, "node_modules/electron-to-chromium": { @@ -3974,6 +4665,8 @@ }, "node_modules/emittery": { "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "license": "MIT", "engines": { @@ -3985,14 +4678,20 @@ }, "node_modules/emoji-regex": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, "node_modules/enabled": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", "license": "MIT" }, "node_modules/encodeurl": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -4000,6 +4699,8 @@ }, "node_modules/encoding": { "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "license": "MIT", "optional": true, "dependencies": { @@ -4008,6 +4709,8 @@ }, "node_modules/encoding/node_modules/iconv-lite": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", "optional": true, "dependencies": { @@ -4019,6 +4722,8 @@ }, "node_modules/end-of-stream": { "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "license": "MIT", "dependencies": { "once": "^1.4.0" @@ -4026,11 +4731,15 @@ }, "node_modules/ent": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", "license": "MIT", "optional": true }, "node_modules/entities": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", "license": "BSD-2-Clause", "funding": { "url": "https://github.com/fb55/entities?sponsor=1" @@ -4038,6 +4747,8 @@ }, "node_modules/env-paths": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "license": "MIT", "optional": true, "engines": { @@ -4046,11 +4757,15 @@ }, "node_modules/err-code": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "license": "MIT", "optional": true }, "node_modules/error-ex": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "license": "MIT", "dependencies": { @@ -4066,6 +4781,8 @@ }, "node_modules/escape-goat": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", "license": "MIT", "engines": { "node": ">=8" @@ -4073,10 +4790,14 @@ }, "node_modules/escape-html": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "license": "MIT", "engines": { "node": ">=0.8.0" @@ -4084,6 +4805,8 @@ }, "node_modules/escodegen": { "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", "license": "BSD-2-Clause", "dependencies": { "esprima": "^4.0.1", @@ -4104,6 +4827,8 @@ }, "node_modules/escodegen/node_modules/estraverse": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -4111,6 +4836,8 @@ }, "node_modules/eslint-visitor-keys": { "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4121,6 +4848,8 @@ }, "node_modules/espree": { "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.9.0", @@ -4136,6 +4865,8 @@ }, "node_modules/esprima": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", @@ -4147,6 +4878,8 @@ }, "node_modules/estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -4154,6 +4887,8 @@ }, "node_modules/esutils": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" @@ -4161,6 +4896,8 @@ }, "node_modules/etag": { "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -4168,6 +4905,8 @@ }, "node_modules/event-target-shim": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", "engines": { "node": ">=6" @@ -4175,10 +4914,14 @@ }, "node_modules/events-listener": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/events-listener/-/events-listener-1.1.0.tgz", + "integrity": "sha512-Kd3EgYfODHueq6GzVfs/VUolh2EgJsS8hkO3KpnDrxVjU3eq63eXM2ujXkhPP+OkeUOhL8CxdfZbQXzryb5C4g==", "license": "MIT" }, "node_modules/execa": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "license": "MIT", "dependencies": { @@ -4201,6 +4944,8 @@ }, "node_modules/exegesis": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/exegesis/-/exegesis-4.1.1.tgz", + "integrity": "sha512-PvSqaMOw2absLBgsthtJyVOeCHN4lxQ1dM7ibXb6TfZZJaoXtGELoEAGJRFvdN16+u9kg8oy1okZXRk8VpimWA==", "license": "MIT", "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.3", @@ -4228,6 +4973,8 @@ }, "node_modules/exegesis-express": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/exegesis-express/-/exegesis-express-4.0.0.tgz", + "integrity": "sha512-V2hqwTtYRj0bj43K4MCtm0caD97YWkqOUHFMRCBW5L1x9IjyqOEc7Xa4oQjjiFbeFOSQzzwPV+BzXsQjSz08fw==", "license": "MIT", "dependencies": { "exegesis": "^4.1.0" @@ -4239,6 +4986,8 @@ }, "node_modules/exegesis/node_modules/ajv": { "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -4253,6 +5002,8 @@ }, "node_modules/exegesis/node_modules/ajv-formats": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "license": "MIT", "dependencies": { "ajv": "^8.0.0" @@ -4268,6 +5019,8 @@ }, "node_modules/exegesis/node_modules/qs": { "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.4" @@ -4294,6 +5047,8 @@ }, "node_modules/exit": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, "engines": { "node": ">= 0.8.0" @@ -4301,6 +5056,8 @@ }, "node_modules/expect": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "license": "MIT", "dependencies": { @@ -4316,11 +5073,15 @@ }, "node_modules/exponential-backoff": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", "license": "Apache-2.0", "optional": true }, "node_modules/express": { "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", @@ -4361,6 +5122,8 @@ }, "node_modules/express/node_modules/body-parser": { "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -4383,6 +5146,8 @@ }, "node_modules/express/node_modules/debug": { "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -4390,10 +5155,14 @@ }, "node_modules/express/node_modules/ms": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, "node_modules/express/node_modules/raw-body": { "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -4407,10 +5176,14 @@ }, "node_modules/extend": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "license": "MIT" }, "node_modules/external-editor": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "license": "MIT", "dependencies": { "chardet": "^0.7.0", @@ -4423,6 +5196,8 @@ }, "node_modules/external-editor/node_modules/tmp": { "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "license": "MIT", "dependencies": { "os-tmpdir": "~1.0.2" @@ -4431,31 +5206,34 @@ "node": ">=0.6.0" } }, - "node_modules/extsprintf": { - "version": "1.3.0", - "engines": [ - "node >=0.6.0" - ], - "license": "MIT" - }, "node_modules/fast-deep-equal": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "license": "MIT" }, "node_modules/fast-text-encoding": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", + "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==", "license": "Apache-2.0" }, "node_modules/fast-url-parser": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", "license": "MIT", "dependencies": { "punycode": "^1.3.2" @@ -4463,6 +5241,8 @@ }, "node_modules/fast-url-parser/node_modules/punycode": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", "license": "MIT" }, "node_modules/fast-xml-parser": { @@ -4488,6 +5268,8 @@ }, "node_modules/faye-websocket": { "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", "license": "Apache-2.0", "dependencies": { "websocket-driver": ">=0.5.1" @@ -4498,6 +5280,8 @@ }, "node_modules/fb-watchman": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4506,10 +5290,14 @@ }, "node_modules/fecha": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", "license": "MIT" }, "node_modules/figures": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.5" @@ -4523,6 +5311,8 @@ }, "node_modules/filesize": { "version": "6.4.0", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.4.0.tgz", + "integrity": "sha512-mjFIpOHC4jbfcTfoh4rkWpI31mF7viw9ikj/JyLoKzqlwG/YsefKfvYlYhdYdg/9mtK2z1AzgN/0LvVQ3zdlSQ==", "license": "BSD-3-Clause", "engines": { "node": ">= 0.4.0" @@ -4530,6 +5320,8 @@ }, "node_modules/fill-range": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -4540,6 +5332,8 @@ }, "node_modules/finalhandler": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -4556,6 +5350,8 @@ }, "node_modules/finalhandler/node_modules/debug": { "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -4563,10 +5359,14 @@ }, "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, "node_modules/find-up": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", "dependencies": { @@ -4625,6 +5425,8 @@ }, "node_modules/firebase-admin/node_modules/uuid": { "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -4635,8 +5437,9 @@ } }, "node_modules/firebase-tools": { - "version": "12.9.1", - "license": "MIT", + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/firebase-tools/-/firebase-tools-13.3.0.tgz", + "integrity": "sha512-WooMk02Wucre63XGHNOopwRp/FFCL/zjq1Jz0itZ6fDeytdTxZabhlcvnX+HMCyccPhuwbs3extIEh/T6SFWtA==", "dependencies": { "@google-cloud/pubsub": "^3.0.1", "abort-controller": "^3.0.0", @@ -4680,7 +5483,6 @@ "portfinder": "^1.0.32", "progress": "^2.0.3", "proxy-agent": "^6.3.0", - "request": "^2.87.0", "retry": "^0.13.1", "rimraf": "^3.0.0", "semver": "^7.5.2", @@ -4703,7 +5505,7 @@ "firebase": "lib/bin/firebase.js" }, "engines": { - "node": ">=16.13.0 || >=18.0.0" + "node": ">=18.0.0 || >=20.0.0" } }, "node_modules/firebase-tools/node_modules/argparse": { @@ -4716,6 +5518,8 @@ }, "node_modules/firebase-tools/node_modules/gaxios": { "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", "license": "Apache-2.0", "dependencies": { "abort-controller": "^3.0.0", @@ -4730,6 +5534,8 @@ }, "node_modules/firebase-tools/node_modules/gcp-metadata": { "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", "license": "Apache-2.0", "dependencies": { "gaxios": "^4.0.0", @@ -4741,6 +5547,8 @@ }, "node_modules/firebase-tools/node_modules/google-auth-library": { "version": "7.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", + "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", "license": "Apache-2.0", "dependencies": { "arrify": "^2.0.0", @@ -4759,6 +5567,8 @@ }, "node_modules/firebase-tools/node_modules/google-p12-pem": { "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", "license": "MIT", "dependencies": { "node-forge": "^1.3.1" @@ -4772,6 +5582,8 @@ }, "node_modules/firebase-tools/node_modules/gtoken": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", "license": "MIT", "dependencies": { "gaxios": "^4.0.0", @@ -4931,17 +5743,14 @@ }, "node_modules/fn.name": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", "license": "MIT" }, - "node_modules/forever-agent": { - "version": "0.6.1", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, "node_modules/form-data": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -4954,6 +5763,8 @@ }, "node_modules/forwarded": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -4961,6 +5772,8 @@ }, "node_modules/fresh": { "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -4968,10 +5781,14 @@ }, "node_modules/fs-constants": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "license": "MIT" }, "node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", @@ -4984,6 +5801,8 @@ }, "node_modules/fs-minipass": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "license": "ISC", "dependencies": { "minipass": "^3.0.0" @@ -4994,10 +5813,14 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "license": "MIT", "optional": true, "os": [ @@ -5009,6 +5832,8 @@ }, "node_modules/function-bind": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5016,6 +5841,8 @@ }, "node_modules/functional-red-black-tree": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", "license": "MIT", "optional": true }, @@ -5039,6 +5866,8 @@ }, "node_modules/gaxios": { "version": "5.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz", + "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==", "license": "Apache-2.0", "dependencies": { "extend": "^3.0.2", @@ -5052,6 +5881,8 @@ }, "node_modules/gcp-metadata": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz", + "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==", "license": "Apache-2.0", "dependencies": { "gaxios": "^5.0.0", @@ -5063,6 +5894,8 @@ }, "node_modules/gensync": { "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "license": "MIT", "engines": { @@ -5071,6 +5904,8 @@ }, "node_modules/get-caller-file": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -5091,6 +5926,8 @@ }, "node_modules/get-package-type": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, "license": "MIT", "engines": { @@ -5099,6 +5936,8 @@ }, "node_modules/get-stream": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, "license": "MIT", "engines": { @@ -5147,15 +5986,10 @@ "node": ">= 4.0.0" } }, - "node_modules/getpass": { - "version": "0.1.7", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/glob": { "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -5174,6 +6008,8 @@ }, "node_modules/glob-parent": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -5184,10 +6020,14 @@ }, "node_modules/glob-slash": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glob-slash/-/glob-slash-1.0.0.tgz", + "integrity": "sha512-ZwFh34WZhZX28ntCMAP1mwyAJkn8+Omagvt/GvA+JQM/qgT0+MR2NPF3vhvgdshfdvDyGZXs8fPXW84K32Wjuw==", "license": "MIT" }, "node_modules/glob-slasher": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glob-slasher/-/glob-slasher-1.0.1.tgz", + "integrity": "sha512-5MUzqFiycIKLMD1B0dYOE4hGgLLUZUNGGYO4BExdwT32wUwW3DBOE7lMQars7vB1q43Fb3Tyt+HmgLKsJhDYdg==", "license": "MIT", "dependencies": { "glob-slash": "^1.0.0", @@ -5197,6 +6037,8 @@ }, "node_modules/global-dirs": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", "license": "MIT", "dependencies": { "ini": "2.0.0" @@ -5210,6 +6052,8 @@ }, "node_modules/global-dirs/node_modules/ini": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", "license": "ISC", "engines": { "node": ">=10" @@ -5217,6 +6061,8 @@ }, "node_modules/globals": { "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, "license": "MIT", "engines": { @@ -5225,6 +6071,8 @@ }, "node_modules/google-auth-library": { "version": "8.9.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.9.0.tgz", + "integrity": "sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg==", "license": "Apache-2.0", "dependencies": { "arrify": "^2.0.0", @@ -5243,6 +6091,8 @@ }, "node_modules/google-gax": { "version": "3.6.1", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-3.6.1.tgz", + "integrity": "sha512-g/lcUjGcB6DSw2HxgEmCDOrI/CByOwqRvsuUvNalHUK2iPPPlmAIpbMbl62u0YufGMr8zgE3JL7th6dCb1Ry+w==", "license": "Apache-2.0", "dependencies": { "@grpc/grpc-js": "~1.8.0", @@ -5271,6 +6121,8 @@ }, "node_modules/google-p12-pem": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-4.0.1.tgz", + "integrity": "sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ==", "license": "MIT", "dependencies": { "node-forge": "^1.3.1" @@ -5284,6 +6136,8 @@ }, "node_modules/gopd": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.3" @@ -5294,10 +6148,14 @@ }, "node_modules/graceful-fs": { "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, "node_modules/gtoken": { "version": "6.1.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-6.1.2.tgz", + "integrity": "sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ==", "license": "MIT", "dependencies": { "gaxios": "^5.0.1", @@ -5308,26 +6166,10 @@ "node": ">=12.0.0" } }, - "node_modules/har-schema": { - "version": "2.0.0", - "license": "ISC", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "license": "MIT", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "license": "MIT", "engines": { "node": ">=8" @@ -5345,6 +6187,8 @@ }, "node_modules/has-proto": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -5355,6 +6199,8 @@ }, "node_modules/has-symbols": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -5370,6 +6216,8 @@ }, "node_modules/has-yarn": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", "license": "MIT", "engines": { "node": ">=8" @@ -5387,6 +6235,8 @@ }, "node_modules/heap-js": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/heap-js/-/heap-js-2.3.0.tgz", + "integrity": "sha512-E5303mzwQ+4j/n2J0rDvEPBN7GKjhis10oHiYOgjxsmxYgqG++hz9NyLLOXttzH8as/DyiBHYpUrJTZWYaMo8Q==", "license": "BSD-3-Clause", "engines": { "node": ">=10.0.0" @@ -5394,6 +6244,8 @@ }, "node_modules/html-escaper": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true, "license": "MIT" }, @@ -5404,6 +6256,8 @@ }, "node_modules/http-errors": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "license": "MIT", "dependencies": { "depd": "2.0.0", @@ -5418,12 +6272,15 @@ }, "node_modules/http-parser-js": { "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", "license": "MIT" }, "node_modules/http-proxy-agent": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "license": "MIT", - "optional": true, "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -5435,8 +6292,9 @@ }, "node_modules/http-proxy-agent/node_modules/agent-base": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "license": "MIT", - "optional": true, "dependencies": { "debug": "4" }, @@ -5444,21 +6302,10 @@ "node": ">= 6.0.0" } }, - "node_modules/http-signature": { - "version": "1.2.0", - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/https-proxy-agent": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "license": "MIT", "dependencies": { "agent-base": "6", @@ -5470,6 +6317,8 @@ }, "node_modules/https-proxy-agent/node_modules/agent-base": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "license": "MIT", "dependencies": { "debug": "4" @@ -5480,6 +6329,8 @@ }, "node_modules/human-signals": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -5496,6 +6347,8 @@ }, "node_modules/iconv-lite": { "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" @@ -5512,6 +6365,8 @@ }, "node_modules/ieee754": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "funding": [ { "type": "github", @@ -5530,6 +6385,8 @@ }, "node_modules/import-lazy": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", "license": "MIT", "engines": { "node": ">=4" @@ -5537,6 +6394,8 @@ }, "node_modules/import-local": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, "license": "MIT", "dependencies": { @@ -5555,6 +6414,8 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "license": "MIT", "engines": { "node": ">=0.8.19" @@ -5562,6 +6423,8 @@ }, "node_modules/indent-string": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "license": "MIT", "optional": true, "engines": { @@ -5575,6 +6438,8 @@ }, "node_modules/inflight": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -5583,14 +6448,20 @@ }, "node_modules/inherits": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, "node_modules/ini": { "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "license": "ISC" }, "node_modules/inquirer": { "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", "license": "MIT", "dependencies": { "ansi-escapes": "^4.2.1", @@ -5615,6 +6486,8 @@ }, "node_modules/inquirer/node_modules/wrap-ansi": { "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -5640,6 +6513,8 @@ }, "node_modules/ip-regex": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", "license": "MIT", "engines": { "node": ">=8" @@ -5647,6 +6522,8 @@ }, "node_modules/ipaddr.js": { "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "license": "MIT", "engines": { "node": ">= 0.10" @@ -5654,11 +6531,15 @@ }, "node_modules/is-arrayish": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, "license": "MIT" }, "node_modules/is-binary-path": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" @@ -5669,6 +6550,8 @@ }, "node_modules/is-ci": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", "license": "MIT", "dependencies": { "ci-info": "^2.0.0" @@ -5679,10 +6562,14 @@ }, "node_modules/is-ci/node_modules/ci-info": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "license": "MIT" }, "node_modules/is-core-module": { "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "license": "MIT", "dependencies": { @@ -5694,6 +6581,8 @@ }, "node_modules/is-extglob": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5701,6 +6590,8 @@ }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", "engines": { "node": ">=8" @@ -5708,6 +6599,8 @@ }, "node_modules/is-generator-fn": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, "license": "MIT", "engines": { @@ -5716,6 +6609,8 @@ }, "node_modules/is-glob": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -5726,6 +6621,8 @@ }, "node_modules/is-installed-globally": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", "license": "MIT", "dependencies": { "global-dirs": "^3.0.0", @@ -5740,6 +6637,8 @@ }, "node_modules/is-interactive": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "license": "MIT", "engines": { "node": ">=8" @@ -5747,11 +6646,15 @@ }, "node_modules/is-lambda": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "license": "MIT", "optional": true }, "node_modules/is-npm": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", "license": "MIT", "engines": { "node": ">=10" @@ -5762,6 +6665,8 @@ }, "node_modules/is-number": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "license": "MIT", "engines": { "node": ">=0.12.0" @@ -5769,6 +6674,8 @@ }, "node_modules/is-obj": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "license": "MIT", "engines": { "node": ">=8" @@ -5776,6 +6683,8 @@ }, "node_modules/is-path-inside": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "license": "MIT", "engines": { "node": ">=8" @@ -5783,6 +6692,8 @@ }, "node_modules/is-stream": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "license": "MIT", "engines": { "node": ">=8" @@ -5793,14 +6704,20 @@ }, "node_modules/is-stream-ended": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", + "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==", "license": "MIT" }, "node_modules/is-typedarray": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "license": "MIT" }, "node_modules/is-unicode-supported": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "license": "MIT", "engines": { "node": ">=10" @@ -5811,10 +6728,14 @@ }, "node_modules/is-url": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", "license": "MIT" }, "node_modules/is-wsl": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", "license": "MIT", "engines": { "node": ">=4" @@ -5822,10 +6743,14 @@ }, "node_modules/is-yarn-global": { "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "license": "MIT" }, "node_modules/is2": { "version": "2.0.9", + "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.9.tgz", + "integrity": "sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g==", "license": "MIT", "dependencies": { "deep-is": "^0.1.3", @@ -5838,26 +6763,30 @@ }, "node_modules/isarray": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, "node_modules/isomorphic-fetch": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", "license": "MIT", "dependencies": { "node-fetch": "^2.6.1", "whatwg-fetch": "^3.4.1" } }, - "node_modules/isstream": { - "version": "0.1.2", - "license": "MIT" - }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -5866,6 +6795,8 @@ }, "node_modules/istanbul-lib-instrument": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5881,6 +6812,8 @@ }, "node_modules/istanbul-lib-report": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5894,6 +6827,8 @@ }, "node_modules/istanbul-lib-report/node_modules/make-dir": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "license": "MIT", "dependencies": { @@ -5922,6 +6857,8 @@ }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5935,6 +6872,8 @@ }, "node_modules/istanbul-reports": { "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5947,6 +6886,8 @@ }, "node_modules/jest": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", "dependencies": { @@ -5972,6 +6913,8 @@ }, "node_modules/jest-changed-files": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "license": "MIT", "dependencies": { @@ -5985,6 +6928,8 @@ }, "node_modules/jest-circus": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "license": "MIT", "dependencies": { @@ -6015,6 +6960,8 @@ }, "node_modules/jest-cli": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, "license": "MIT", "dependencies": { @@ -6047,6 +6994,8 @@ }, "node_modules/jest-config": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6091,6 +7040,8 @@ }, "node_modules/jest-diff": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "license": "MIT", "dependencies": { @@ -6105,6 +7056,8 @@ }, "node_modules/jest-docblock": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "license": "MIT", "dependencies": { @@ -6116,6 +7069,8 @@ }, "node_modules/jest-each": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6131,6 +7086,8 @@ }, "node_modules/jest-environment-node": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "license": "MIT", "dependencies": { @@ -6147,6 +7104,8 @@ }, "node_modules/jest-get-type": { "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "license": "MIT", "engines": { @@ -6155,6 +7114,8 @@ }, "node_modules/jest-haste-map": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "license": "MIT", "dependencies": { @@ -6179,6 +7140,8 @@ }, "node_modules/jest-leak-detector": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, "license": "MIT", "dependencies": { @@ -6191,6 +7154,8 @@ }, "node_modules/jest-matcher-utils": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "license": "MIT", "dependencies": { @@ -6205,6 +7170,8 @@ }, "node_modules/jest-message-util": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "license": "MIT", "dependencies": { @@ -6224,6 +7191,8 @@ }, "node_modules/jest-mock": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "license": "MIT", "dependencies": { @@ -6237,6 +7206,8 @@ }, "node_modules/jest-pnp-resolver": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "license": "MIT", "engines": { @@ -6253,6 +7224,8 @@ }, "node_modules/jest-regex-util": { "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "license": "MIT", "engines": { @@ -6261,6 +7234,8 @@ }, "node_modules/jest-resolve": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "license": "MIT", "dependencies": { @@ -6280,6 +7255,8 @@ }, "node_modules/jest-resolve-dependencies": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "license": "MIT", "dependencies": { @@ -6292,6 +7269,8 @@ }, "node_modules/jest-runner": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6323,6 +7302,8 @@ }, "node_modules/jest-runtime": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6355,6 +7336,8 @@ }, "node_modules/jest-snapshot": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "license": "MIT", "dependencies": { @@ -6399,6 +7382,8 @@ }, "node_modules/jest-util": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "license": "MIT", "dependencies": { @@ -6415,6 +7400,8 @@ }, "node_modules/jest-validate": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "license": "MIT", "dependencies": { @@ -6431,6 +7418,8 @@ }, "node_modules/jest-watcher": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "license": "MIT", "dependencies": { @@ -6449,6 +7438,8 @@ }, "node_modules/jest-worker": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "license": "MIT", "dependencies": { @@ -6463,6 +7454,8 @@ }, "node_modules/jest-worker/node_modules/supports-color": { "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -6477,10 +7470,14 @@ }, "node_modules/jju": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", "license": "MIT" }, "node_modules/join-path": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/join-path/-/join-path-1.1.1.tgz", + "integrity": "sha512-jnt9OC34sLXMLJ6YfPQ2ZEKrR9mB5ZbSnQb4LPaOx1c5rTzxpR33L18jjp0r75mGGTJmsil3qwN1B5IBeTnSSA==", "license": "MIT", "dependencies": { "as-array": "^2.0.0", @@ -6490,6 +7487,8 @@ }, "node_modules/jose": { "version": "4.15.4", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz", + "integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" @@ -6497,6 +7496,8 @@ }, "node_modules/js-tokens": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, "license": "MIT" }, @@ -6513,17 +7514,17 @@ }, "node_modules/js2xmlparser": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", "license": "Apache-2.0", "dependencies": { "xmlcreate": "^2.0.4" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "license": "MIT" - }, "node_modules/jsdoc": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", "license": "Apache-2.0", "dependencies": { "@babel/parser": "^7.20.15", @@ -6561,6 +7562,8 @@ }, "node_modules/jsdoc/node_modules/escape-string-regexp": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "license": "MIT", "engines": { "node": ">=8" @@ -6568,6 +7571,8 @@ }, "node_modules/jsesc": { "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, "license": "MIT", "bin": { @@ -6579,6 +7584,8 @@ }, "node_modules/json-bigint": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", "license": "MIT", "dependencies": { "bignumber.js": "^9.0.0" @@ -6586,11 +7593,15 @@ }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, "license": "MIT" }, "node_modules/json-parse-helpfulerror": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", + "integrity": "sha512-XgP0FGR77+QhUxjXkwOMkC94k3WtqEBfcnjWqhRd82qTat4SWKRE+9kUnynz/shm3I4ea2+qISvTIeGTNU7kJg==", "license": "MIT", "dependencies": { "jju": "^1.1.0" @@ -6598,22 +7609,20 @@ }, "node_modules/json-ptr": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/json-ptr/-/json-ptr-3.1.1.tgz", + "integrity": "sha512-SiSJQ805W1sDUCD1+/t1/1BIrveq2Fe9HJqENxZmMCILmrPI7WhS/pePpIOx85v6/H2z1Vy7AI08GV2TzfXocg==", "license": "MIT" }, - "node_modules/json-schema": { - "version": "0.4.0", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, "node_modules/json-schema-traverse": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "license": "ISC" - }, "node_modules/json5": { "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "license": "MIT", "bin": { @@ -6625,6 +7634,8 @@ }, "node_modules/jsonfile": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "license": "MIT", "dependencies": { "universalify": "^2.0.0" @@ -6635,6 +7646,8 @@ }, "node_modules/jsonwebtoken": { "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "license": "MIT", "dependencies": { "jws": "^3.2.2", @@ -6655,6 +7668,8 @@ }, "node_modules/jsonwebtoken/node_modules/jwa": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", "license": "MIT", "dependencies": { "buffer-equal-constant-time": "1.0.1", @@ -6664,6 +7679,8 @@ }, "node_modules/jsonwebtoken/node_modules/jws": { "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", "license": "MIT", "dependencies": { "jwa": "^1.4.1", @@ -6683,21 +7700,10 @@ "node": ">=10" } }, - "node_modules/jsprim": { - "version": "1.4.2", - "license": "MIT", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/jwa": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", "license": "MIT", "dependencies": { "buffer-equal-constant-time": "1.0.1", @@ -6707,6 +7713,8 @@ }, "node_modules/jwks-rsa": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.1.0.tgz", + "integrity": "sha512-v7nqlfezb9YfHHzYII3ef2a2j1XnGeSE/bK3WfumaYCqONAIstJbrEGapz4kadScZzEt7zYCN7bucj8C0Mv/Rg==", "license": "MIT", "dependencies": { "@types/express": "^4.17.17", @@ -6722,6 +7730,8 @@ }, "node_modules/jws": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", "license": "MIT", "dependencies": { "jwa": "^2.0.0", @@ -6730,6 +7740,8 @@ }, "node_modules/klaw": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", "license": "MIT", "dependencies": { "graceful-fs": "^4.1.9" @@ -6737,6 +7749,8 @@ }, "node_modules/kleur": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, "license": "MIT", "engines": { @@ -6745,10 +7759,14 @@ }, "node_modules/kuler": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", "license": "MIT" }, "node_modules/lazystream": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", "license": "MIT", "dependencies": { "readable-stream": "^2.0.5" @@ -6759,10 +7777,14 @@ }, "node_modules/lazystream/node_modules/isarray": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "license": "MIT" }, "node_modules/lazystream/node_modules/readable-stream": { "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", @@ -6776,10 +7798,14 @@ }, "node_modules/lazystream/node_modules/safe-buffer": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, "node_modules/lazystream/node_modules/string_decoder": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" @@ -6787,6 +7813,8 @@ }, "node_modules/leven": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "license": "MIT", "engines": { "node": ">=6" @@ -6794,6 +7822,8 @@ }, "node_modules/levn": { "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "license": "MIT", "dependencies": { "prelude-ls": "~1.1.2", @@ -6805,25 +7835,35 @@ }, "node_modules/libsodium": { "version": "0.7.13", + "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.13.tgz", + "integrity": "sha512-mK8ju0fnrKXXfleL53vtp9xiPq5hKM0zbDQtcxQIsSmxNgSxqCj6R7Hl9PkrNe2j29T4yoDaF7DJLK9/i5iWUw==", "license": "ISC" }, "node_modules/libsodium-wrappers": { "version": "0.7.13", + "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.13.tgz", + "integrity": "sha512-kasvDsEi/r1fMzKouIDv7B8I6vNmknXwGiYodErGuESoFTohGSKZplFtVxZqHaoQ217AynyIFgnOVRitpHs0Qw==", "license": "ISC", "dependencies": { "libsodium": "^0.7.13" } }, "node_modules/limiter": { - "version": "1.1.5" + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" }, "node_modules/lines-and-columns": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true, "license": "MIT" }, "node_modules/linkify-it": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", "license": "MIT", "dependencies": { "uc.micro": "^1.0.1" @@ -6831,6 +7871,8 @@ }, "node_modules/locate-path": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", "dependencies": { @@ -6842,50 +7884,74 @@ }, "node_modules/lodash": { "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, "node_modules/lodash._objecttypes": { "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "integrity": "sha512-XpqGh1e7hhkOzftBfWE7zt+Yn9mVHFkDhicVttvKLsoCMLVVL+xTQjfjB4X4vtznauxv0QZ5ZAeqjvat0dh62Q==", "license": "MIT" }, "node_modules/lodash.camelcase": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "license": "MIT" }, "node_modules/lodash.clonedeep": { "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", "license": "MIT" }, "node_modules/lodash.defaults": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", "license": "MIT" }, "node_modules/lodash.difference": { "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", "license": "MIT" }, "node_modules/lodash.flatten": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", "license": "MIT" }, "node_modules/lodash.includes": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", "license": "MIT" }, "node_modules/lodash.isboolean": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", "license": "MIT" }, "node_modules/lodash.isinteger": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", "license": "MIT" }, "node_modules/lodash.isnumber": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", "license": "MIT" }, "node_modules/lodash.isobject": { "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "integrity": "sha512-sTebg2a1PoicYEZXD5PBdQcTlIJ6hUslrlWr7iV0O7n+i4596s2NQ9I5CaZ5FbXSfya/9WQsrYLANUJv9paYVA==", "license": "MIT", "dependencies": { "lodash._objecttypes": "~2.4.1" @@ -6893,10 +7959,14 @@ }, "node_modules/lodash.isplainobject": { "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", "license": "MIT" }, "node_modules/lodash.isstring": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "license": "MIT" }, "node_modules/lodash.memoize": { @@ -6907,18 +7977,26 @@ }, "node_modules/lodash.once": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "license": "MIT" }, "node_modules/lodash.snakecase": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", "license": "MIT" }, "node_modules/lodash.union": { "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", "license": "MIT" }, "node_modules/log-symbols": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "license": "MIT", "dependencies": { "chalk": "^4.1.0", @@ -6933,6 +8011,8 @@ }, "node_modules/logform": { "version": "2.6.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", + "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", "license": "MIT", "dependencies": { "@colors/colors": "1.6.0", @@ -6948,10 +8028,14 @@ }, "node_modules/long": { "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", "license": "Apache-2.0" }, "node_modules/lru-cache": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -6962,6 +8046,8 @@ }, "node_modules/lru-memoizer": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.2.0.tgz", + "integrity": "sha512-QfOZ6jNkxCcM/BkIPnFsqDhtrazLRsghi9mBwFAzol5GCvj4EkFT899Za3+QwikCg5sRX8JstioBDwOxEyzaNw==", "license": "MIT", "dependencies": { "lodash.clonedeep": "^4.5.0", @@ -6970,6 +8056,8 @@ }, "node_modules/lru-memoizer/node_modules/lru-cache": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", + "integrity": "sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw==", "license": "ISC", "dependencies": { "pseudomap": "^1.0.1", @@ -6978,10 +8066,14 @@ }, "node_modules/lru-memoizer/node_modules/yallist": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", "license": "ISC" }, "node_modules/make-dir": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "license": "MIT", "dependencies": { "semver": "^6.0.0" @@ -7059,6 +8151,8 @@ }, "node_modules/makeerror": { "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -7067,6 +8161,8 @@ }, "node_modules/markdown-it": { "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", "license": "MIT", "dependencies": { "argparse": "^2.0.1", @@ -7081,6 +8177,8 @@ }, "node_modules/markdown-it-anchor": { "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", "license": "Unlicense", "peerDependencies": { "@types/markdown-it": "*", @@ -7089,6 +8187,8 @@ }, "node_modules/marked": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "license": "MIT", "bin": { "marked": "bin/marked.js" @@ -7099,6 +8199,8 @@ }, "node_modules/marked-terminal": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.2.0.tgz", + "integrity": "sha512-Piv6yNwAQXGFjZSaiNljyNFw7jKDdGrw70FSbtxEyldLsyeuV5ZHm/1wW++kWbrOF1VPnUgYOhB2oLL0ZpnekA==", "license": "MIT", "dependencies": { "ansi-escapes": "^6.2.0", @@ -7117,6 +8219,8 @@ }, "node_modules/marked-terminal/node_modules/ansi-escapes": { "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", "license": "MIT", "dependencies": { "type-fest": "^3.0.0" @@ -7130,6 +8234,8 @@ }, "node_modules/marked-terminal/node_modules/chalk": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" @@ -7140,6 +8246,8 @@ }, "node_modules/marked-terminal/node_modules/type-fest": { "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=14.16" @@ -7150,10 +8258,14 @@ }, "node_modules/mdurl": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", "license": "MIT" }, "node_modules/media-typer": { "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -7161,15 +8273,21 @@ }, "node_modules/merge-descriptors": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", "license": "MIT" }, "node_modules/merge-stream": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true, "license": "MIT" }, "node_modules/methods": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -7177,6 +8295,8 @@ }, "node_modules/micromatch": { "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "license": "MIT", "dependencies": { @@ -7189,6 +8309,8 @@ }, "node_modules/mime": { "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "license": "MIT", "bin": { "mime": "cli.js" @@ -7199,6 +8321,8 @@ }, "node_modules/mime-db": { "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -7206,6 +8330,8 @@ }, "node_modules/mime-types": { "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -7216,6 +8342,8 @@ }, "node_modules/mimic-fn": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "license": "MIT", "engines": { "node": ">=6" @@ -7223,6 +8351,8 @@ }, "node_modules/minimatch": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -7233,6 +8363,8 @@ }, "node_modules/minimatch/node_modules/brace-expansion": { "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -7241,6 +8373,8 @@ }, "node_modules/minimist": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7248,6 +8382,8 @@ }, "node_modules/minipass": { "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -7285,6 +8421,8 @@ }, "node_modules/minipass-flush": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "license": "ISC", "optional": true, "dependencies": { @@ -7296,6 +8434,8 @@ }, "node_modules/minipass-pipeline": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "license": "ISC", "optional": true, "dependencies": { @@ -7307,6 +8447,8 @@ }, "node_modules/minipass-sized": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "license": "ISC", "optional": true, "dependencies": { @@ -7318,6 +8460,8 @@ }, "node_modules/minizlib": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "license": "MIT", "dependencies": { "minipass": "^3.0.0", @@ -7329,6 +8473,8 @@ }, "node_modules/mkdirp": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" @@ -7339,6 +8485,8 @@ }, "node_modules/morgan": { "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", "license": "MIT", "dependencies": { "basic-auth": "~2.0.1", @@ -7353,6 +8501,8 @@ }, "node_modules/morgan/node_modules/debug": { "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -7360,10 +8510,14 @@ }, "node_modules/morgan/node_modules/ms": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, "node_modules/morgan/node_modules/on-finished": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", "license": "MIT", "dependencies": { "ee-first": "1.1.1" @@ -7374,24 +8528,34 @@ }, "node_modules/ms": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/mute-stream": { "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "license": "ISC" }, "node_modules/nan": { "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", "license": "MIT", "optional": true }, "node_modules/natural-compare": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -7399,6 +8563,8 @@ }, "node_modules/netmask": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", "license": "MIT", "engines": { "node": ">= 0.4.0" @@ -7406,10 +8572,14 @@ }, "node_modules/nice-try": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "license": "MIT" }, "node_modules/node-emoji": { "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", "license": "MIT", "dependencies": { "lodash": "^4.17.21" @@ -7417,6 +8587,8 @@ }, "node_modules/node-fetch": { "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" @@ -7435,6 +8607,8 @@ }, "node_modules/node-forge": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" @@ -7480,6 +8654,8 @@ }, "node_modules/node-int64": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "dev": true, "license": "MIT" }, @@ -7504,6 +8680,8 @@ }, "node_modules/normalize-path": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7511,6 +8689,8 @@ }, "node_modules/npm-run-path": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "license": "MIT", "dependencies": { @@ -7534,15 +8714,10 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, "node_modules/object-assign": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7550,6 +8725,8 @@ }, "node_modules/object-hash": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", "license": "MIT", "engines": { "node": ">= 6" @@ -7564,6 +8741,8 @@ }, "node_modules/on-finished": { "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "license": "MIT", "dependencies": { "ee-first": "1.1.1" @@ -7574,6 +8753,8 @@ }, "node_modules/on-headers": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -7581,6 +8762,8 @@ }, "node_modules/once": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "license": "ISC", "dependencies": { "wrappy": "1" @@ -7588,6 +8771,8 @@ }, "node_modules/one-time": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", "license": "MIT", "dependencies": { "fn.name": "1.x.x" @@ -7595,6 +8780,8 @@ }, "node_modules/onetime": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" @@ -7608,6 +8795,8 @@ }, "node_modules/open": { "version": "6.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", + "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", "license": "MIT", "dependencies": { "is-wsl": "^1.1.0" @@ -7618,6 +8807,8 @@ }, "node_modules/openapi3-ts": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-3.2.0.tgz", + "integrity": "sha512-/ykNWRV5Qs0Nwq7Pc0nJ78fgILvOT/60OxEmB3v7yQ8a8Bwcm43D4diaYazG/KBn6czA+52XYy931WFLMCUeSg==", "license": "MIT", "dependencies": { "yaml": "^2.2.1" @@ -7625,6 +8816,8 @@ }, "node_modules/optionator": { "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "license": "MIT", "dependencies": { "deep-is": "~0.1.3", @@ -7640,6 +8833,8 @@ }, "node_modules/ora": { "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "license": "MIT", "dependencies": { "bl": "^4.1.0", @@ -7661,6 +8856,8 @@ }, "node_modules/os-tmpdir": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7668,6 +8865,8 @@ }, "node_modules/p-defer": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-3.0.0.tgz", + "integrity": "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==", "license": "MIT", "engines": { "node": ">=8" @@ -7675,6 +8874,8 @@ }, "node_modules/p-limit": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" @@ -7688,6 +8889,8 @@ }, "node_modules/p-locate": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "license": "MIT", "dependencies": { @@ -7699,6 +8902,8 @@ }, "node_modules/p-locate/node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", "dependencies": { @@ -7713,6 +8918,8 @@ }, "node_modules/p-map": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "license": "MIT", "optional": true, "dependencies": { @@ -7727,6 +8934,8 @@ }, "node_modules/p-try": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, "license": "MIT", "engines": { @@ -7735,6 +8944,8 @@ }, "node_modules/pac-proxy-agent": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", + "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", "license": "MIT", "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", @@ -7790,6 +9001,8 @@ }, "node_modules/parse-json": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", "dependencies": { @@ -7807,6 +9020,8 @@ }, "node_modules/parseurl": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -7814,6 +9029,8 @@ }, "node_modules/path-exists": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { @@ -7822,6 +9039,8 @@ }, "node_modules/path-is-absolute": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7829,6 +9048,8 @@ }, "node_modules/path-key": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "license": "MIT", "engines": { "node": ">=8" @@ -7836,24 +9057,28 @@ }, "node_modules/path-parse": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true, "license": "MIT" }, "node_modules/path-to-regexp": { "version": "0.1.7", - "license": "MIT" - }, - "node_modules/performance-now": { - "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", "license": "MIT" }, "node_modules/picocolors": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true, "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -7864,6 +9089,8 @@ }, "node_modules/pirates": { "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true, "license": "MIT", "engines": { @@ -7872,6 +9099,8 @@ }, "node_modules/pkg-dir": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7883,6 +9112,8 @@ }, "node_modules/portfinder": { "version": "1.0.32", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", + "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", "license": "MIT", "dependencies": { "async": "^2.6.4", @@ -7895,6 +9126,8 @@ }, "node_modules/portfinder/node_modules/async": { "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "license": "MIT", "dependencies": { "lodash": "^4.17.14" @@ -7902,6 +9135,8 @@ }, "node_modules/portfinder/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "license": "MIT", "dependencies": { "ms": "^2.1.1" @@ -7909,6 +9144,8 @@ }, "node_modules/portfinder/node_modules/mkdirp": { "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "license": "MIT", "dependencies": { "minimist": "^1.2.6" @@ -7919,12 +9156,16 @@ }, "node_modules/prelude-ls": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", "engines": { "node": ">= 0.8.0" } }, "node_modules/pretty-format": { "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7938,6 +9179,8 @@ }, "node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", "engines": { @@ -7949,10 +9192,14 @@ }, "node_modules/process-nextick-args": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, "node_modules/progress": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "license": "MIT", "engines": { "node": ">=0.4.0" @@ -7960,6 +9207,8 @@ }, "node_modules/promise-breaker": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/promise-breaker/-/promise-breaker-6.0.0.tgz", + "integrity": "sha512-BthzO9yTPswGf7etOBiHCVuugs2N01/Q/94dIPls48z2zCmrnDptUUZzfIb+41xq0MnYZ/BzmOd6ikDR4ibNZA==", "license": "MIT" }, "node_modules/promise-inflight": { @@ -7974,6 +9223,8 @@ }, "node_modules/promise-retry": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "license": "MIT", "optional": true, "dependencies": { @@ -7986,6 +9237,8 @@ }, "node_modules/promise-retry/node_modules/retry": { "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "license": "MIT", "optional": true, "engines": { @@ -7994,6 +9247,8 @@ }, "node_modules/prompts": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -8006,10 +9261,14 @@ }, "node_modules/proto-list": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", "license": "ISC" }, "node_modules/proto3-json-serializer": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-1.1.1.tgz", + "integrity": "sha512-AwAuY4g9nxx0u52DnSMkqqgyLHaW/XaPLtaAo3y/ZCfeaQB/g4YDH4kb8Wc/mWzWvu0YjOznVnfn373MVZZrgw==", "license": "Apache-2.0", "dependencies": { "protobufjs": "^7.0.0" @@ -8020,6 +9279,8 @@ }, "node_modules/protobufjs": { "version": "7.2.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", + "integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { @@ -8042,6 +9303,8 @@ }, "node_modules/protobufjs-cli": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.1.tgz", + "integrity": "sha512-VPWMgIcRNyQwWUv8OLPyGQ/0lQY/QTQAVN5fh+XzfDwsVw1FZ2L3DM/bcBf8WPiRz2tNpaov9lPZfNcmNo6LXA==", "license": "BSD-3-Clause", "dependencies": { "chalk": "^4.0.0", @@ -8068,6 +9331,8 @@ }, "node_modules/protobufjs-cli/node_modules/glob": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -8085,6 +9350,8 @@ }, "node_modules/protobufjs-cli/node_modules/minimatch": { "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -8108,6 +9375,8 @@ }, "node_modules/proxy-addr": { "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "license": "MIT", "dependencies": { "forwarded": "0.2.0", @@ -8158,6 +9427,8 @@ }, "node_modules/proxy-agent/node_modules/lru-cache": { "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "license": "ISC", "engines": { "node": ">=12" @@ -8165,18 +9436,20 @@ }, "node_modules/proxy-from-env": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, "node_modules/pseudomap": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", "license": "ISC" }, - "node_modules/psl": { - "version": "1.9.0", - "license": "MIT" - }, "node_modules/pump": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -8185,6 +9458,8 @@ }, "node_modules/punycode": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "license": "MIT", "engines": { "node": ">=6" @@ -8192,6 +9467,8 @@ }, "node_modules/pupa": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", "license": "MIT", "dependencies": { "escape-goat": "^2.0.0" @@ -8202,6 +9479,8 @@ }, "node_modules/pure-rand": { "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", "dev": true, "funding": [ { @@ -8217,6 +9496,8 @@ }, "node_modules/qs": { "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.4" @@ -8230,6 +9511,8 @@ }, "node_modules/range-parser": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -8237,6 +9520,8 @@ }, "node_modules/raw-body": { "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -8250,6 +9535,8 @@ }, "node_modules/rc": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { "deep-extend": "^0.6.0", @@ -8263,6 +9550,8 @@ }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8281,11 +9570,15 @@ }, "node_modules/react-is": { "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true, "license": "MIT" }, "node_modules/readable-stream": { "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -8298,6 +9591,8 @@ }, "node_modules/readdir-glob": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", "license": "Apache-2.0", "dependencies": { "minimatch": "^5.1.0" @@ -8305,6 +9600,8 @@ }, "node_modules/readdir-glob/node_modules/minimatch": { "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -8315,6 +9612,8 @@ }, "node_modules/readdirp": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "license": "MIT", "dependencies": { "picomatch": "^2.2.1" @@ -8325,6 +9624,8 @@ }, "node_modules/redeyed": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", "license": "MIT", "dependencies": { "esprima": "~4.0.0" @@ -8332,6 +9633,8 @@ }, "node_modules/registry-auth-token": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", "license": "MIT", "dependencies": { "@pnpm/npm-conf": "^2.1.0" @@ -8342,6 +9645,8 @@ }, "node_modules/registry-url": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", "license": "MIT", "dependencies": { "rc": "^1.2.8" @@ -8350,63 +9655,10 @@ "node": ">=8" } }, - "node_modules/request": { - "version": "2.88.2", - "license": "Apache-2.0", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/request/node_modules/qs": { - "version": "6.5.3", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "license": "MIT", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/require-directory": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8414,6 +9666,8 @@ }, "node_modules/require-from-string": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8421,6 +9675,8 @@ }, "node_modules/requizzle": { "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", "license": "MIT", "dependencies": { "lodash": "^4.17.21" @@ -8428,6 +9684,8 @@ }, "node_modules/resolve": { "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "license": "MIT", "dependencies": { @@ -8444,6 +9702,8 @@ }, "node_modules/resolve-cwd": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, "license": "MIT", "dependencies": { @@ -8455,6 +9715,8 @@ }, "node_modules/resolve-from": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "license": "MIT", "engines": { @@ -8463,6 +9725,8 @@ }, "node_modules/resolve.exports": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true, "license": "MIT", "engines": { @@ -8471,6 +9735,8 @@ }, "node_modules/restore-cursor": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "license": "MIT", "dependencies": { "onetime": "^5.1.0", @@ -8482,6 +9748,8 @@ }, "node_modules/retry": { "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "license": "MIT", "engines": { "node": ">= 4" @@ -8489,6 +9757,8 @@ }, "node_modules/retry-request": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-5.0.2.tgz", + "integrity": "sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ==", "license": "MIT", "dependencies": { "debug": "^4.1.1", @@ -8500,6 +9770,8 @@ }, "node_modules/rimraf": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -8513,6 +9785,8 @@ }, "node_modules/router": { "version": "1.3.8", + "resolved": "https://registry.npmjs.org/router/-/router-1.3.8.tgz", + "integrity": "sha512-461UFH44NtSfIlS83PUg2N7OZo86BC/kB3dY77gJdsODsBhhw7+2uE0tzTINxrY9CahCUVk1VhpWCA5i1yoIEg==", "license": "MIT", "dependencies": { "array-flatten": "3.0.0", @@ -8529,10 +9803,14 @@ }, "node_modules/router/node_modules/array-flatten": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-3.0.0.tgz", + "integrity": "sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==", "license": "MIT" }, "node_modules/router/node_modules/debug": { "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -8540,10 +9818,14 @@ }, "node_modules/router/node_modules/ms": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, "node_modules/run-async": { "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "license": "MIT", "engines": { "node": ">=0.12.0" @@ -8551,6 +9833,8 @@ }, "node_modules/rxjs": { "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" @@ -8558,6 +9842,8 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -8576,6 +9862,8 @@ }, "node_modules/safe-stable-stringify": { "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", "license": "MIT", "engines": { "node": ">=10" @@ -8583,10 +9871,14 @@ }, "node_modules/safer-buffer": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, "node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -8594,6 +9886,8 @@ }, "node_modules/semver-diff": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", "license": "MIT", "dependencies": { "semver": "^6.3.0" @@ -8604,6 +9898,8 @@ }, "node_modules/send": { "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -8626,6 +9922,8 @@ }, "node_modules/send/node_modules/debug": { "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -8633,10 +9931,14 @@ }, "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, "node_modules/send/node_modules/mime": { "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "license": "MIT", "bin": { "mime": "cli.js" @@ -8647,6 +9949,8 @@ }, "node_modules/serve-static": { "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "license": "MIT", "dependencies": { "encodeurl": "~1.0.2", @@ -8678,10 +9982,14 @@ }, "node_modules/setprototypeof": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, "node_modules/shebang-command": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -8692,6 +10000,8 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "license": "MIT", "engines": { "node": ">=8" @@ -8711,10 +10021,14 @@ }, "node_modules/signal-exit": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC" }, "node_modules/simple-swizzle": { "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", "license": "MIT", "dependencies": { "is-arrayish": "^0.3.1" @@ -8722,15 +10036,21 @@ }, "node_modules/simple-swizzle/node_modules/is-arrayish": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", "license": "MIT" }, "node_modules/sisteransi": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true, "license": "MIT" }, "node_modules/slash": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", "engines": { @@ -8739,6 +10059,8 @@ }, "node_modules/smart-buffer": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "license": "MIT", "engines": { "node": ">= 6.0.0", @@ -8759,6 +10081,8 @@ }, "node_modules/socks-proxy-agent": { "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -8771,6 +10095,8 @@ }, "node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "devOptional": true, "license": "BSD-3-Clause", "engines": { @@ -8779,6 +10105,8 @@ }, "node_modules/source-map-support": { "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, "license": "MIT", "dependencies": { @@ -8791,29 +10119,6 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, - "node_modules/sshpk": { - "version": "1.18.0", - "license": "MIT", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ssri": { "version": "9.0.1", "license": "ISC", @@ -8827,6 +10132,8 @@ }, "node_modules/stack-trace": { "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", "license": "MIT", "engines": { "node": "*" @@ -8834,6 +10141,8 @@ }, "node_modules/stack-utils": { "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8845,6 +10154,8 @@ }, "node_modules/stack-utils/node_modules/escape-string-regexp": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, "license": "MIT", "engines": { @@ -8853,6 +10164,8 @@ }, "node_modules/statuses": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -8860,18 +10173,23 @@ }, "node_modules/stream-chain": { "version": "2.2.5", + "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", + "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", "license": "BSD-3-Clause" }, "node_modules/stream-events": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", "license": "MIT", - "optional": true, "dependencies": { "stubs": "^3.0.0" } }, "node_modules/stream-json": { "version": "1.8.0", + "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.8.0.tgz", + "integrity": "sha512-HZfXngYHUAr1exT4fxlbc1IOce1RYxp2ldeaf97LYCOPSoOqY/1Psp7iGvpb+6JIOgkra9zDYnPX01hGAHzEPw==", "license": "BSD-3-Clause", "dependencies": { "stream-chain": "^2.2.5" @@ -8883,6 +10201,8 @@ }, "node_modules/string_decoder": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" @@ -8890,6 +10210,8 @@ }, "node_modules/string-length": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8902,6 +10224,8 @@ }, "node_modules/string-width": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -8914,6 +10238,8 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -8924,6 +10250,8 @@ }, "node_modules/strip-bom": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, "license": "MIT", "engines": { @@ -8932,6 +10260,8 @@ }, "node_modules/strip-final-newline": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, "license": "MIT", "engines": { @@ -8940,6 +10270,8 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "license": "MIT", "engines": { "node": ">=8" @@ -8950,16 +10282,21 @@ }, "node_modules/strnum": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", "license": "MIT", "optional": true }, "node_modules/stubs": { "version": "3.0.0", - "license": "MIT", - "optional": true + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", + "license": "MIT" }, "node_modules/superstatic": { "version": "9.0.3", + "resolved": "https://registry.npmjs.org/superstatic/-/superstatic-9.0.3.tgz", + "integrity": "sha512-e/tmW0bsnQ/33ivK6y3CapJT0Ovy4pk/ohNPGhIAGU2oasoNLRQ1cv6enua09NU9w6Y0H/fBu07cjzuiWvLXxw==", "license": "MIT", "dependencies": { "basic-auth-connect": "^1.0.0", @@ -8993,6 +10330,8 @@ }, "node_modules/superstatic/node_modules/commander": { "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "license": "MIT", "engines": { "node": ">=14" @@ -9000,6 +10339,8 @@ }, "node_modules/superstatic/node_modules/minimatch": { "version": "6.2.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-6.2.0.tgz", + "integrity": "sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg==", "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -9013,6 +10354,8 @@ }, "node_modules/superstatic/node_modules/path-to-regexp": { "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", "license": "MIT", "dependencies": { "isarray": "0.0.1" @@ -9020,6 +10363,8 @@ }, "node_modules/supports-color": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -9030,6 +10375,8 @@ }, "node_modules/supports-hyperlinks": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", "license": "MIT", "dependencies": { "has-flag": "^4.0.0", @@ -9041,6 +10388,8 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "license": "MIT", "engines": { @@ -9052,6 +10401,8 @@ }, "node_modules/tar": { "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", "license": "ISC", "dependencies": { "chownr": "^2.0.0", @@ -9067,6 +10418,8 @@ }, "node_modules/tar-stream": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "license": "MIT", "dependencies": { "bl": "^4.0.3", @@ -9081,6 +10434,8 @@ }, "node_modules/tar/node_modules/minipass": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "license": "ISC", "engines": { "node": ">=8" @@ -9088,6 +10443,8 @@ }, "node_modules/tcp-port-used": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", + "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", "license": "MIT", "dependencies": { "debug": "4.3.1", @@ -9096,6 +10453,8 @@ }, "node_modules/tcp-port-used/node_modules/debug": { "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "license": "MIT", "dependencies": { "ms": "2.1.2" @@ -9111,10 +10470,14 @@ }, "node_modules/tcp-port-used/node_modules/ms": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "license": "MIT" }, "node_modules/teeny-request": { "version": "8.0.3", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-8.0.3.tgz", + "integrity": "sha512-jJZpA5He2y52yUhA7pyAGZlgQpcB+xLjcN0eUFxr9c8hP/H7uOXbBNVo/O0C/xVfJLJs680jvkFgVJEEvk9+ww==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -9130,6 +10493,8 @@ }, "node_modules/teeny-request/node_modules/uuid": { "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -9142,6 +10507,8 @@ }, "node_modules/test-exclude": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "license": "ISC", "dependencies": { @@ -9155,18 +10522,26 @@ }, "node_modules/text-decoding": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz", + "integrity": "sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==", "license": "MIT" }, "node_modules/text-hex": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", "license": "MIT" }, "node_modules/through": { "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "license": "MIT" }, "node_modules/tmp": { "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", "license": "MIT", "dependencies": { "rimraf": "^3.0.0" @@ -9177,11 +10552,15 @@ }, "node_modules/tmpl": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true, "license": "BSD-3-Clause" }, "node_modules/to-fast-properties": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, "license": "MIT", "engines": { @@ -9190,6 +10569,8 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -9200,24 +10581,17 @@ }, "node_modules/toidentifier": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "license": "MIT", "engines": { "node": ">=0.6" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "license": "BSD-3-Clause", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/toxic": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toxic/-/toxic-1.0.1.tgz", + "integrity": "sha512-WI3rIGdcaKULYg7KVoB0zcjikqvcYYvcuT6D89bFPz2rVR0Rl0PK6x8/X62rtdLtBKIE985NzVf/auTtGegIIg==", "license": "MIT", "dependencies": { "lodash": "^4.17.10" @@ -9225,10 +10599,14 @@ }, "node_modules/tr46": { "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, "node_modules/triple-beam": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", "license": "MIT", "engines": { "node": ">= 14.0.0" @@ -9294,24 +10672,14 @@ }, "node_modules/tslib": { "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "license": "0BSD" }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "license": "Unlicense" - }, "node_modules/type-check": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "license": "MIT", "dependencies": { "prelude-ls": "~1.1.2" @@ -9322,6 +10690,8 @@ }, "node_modules/type-detect": { "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, "license": "MIT", "engines": { @@ -9330,6 +10700,8 @@ }, "node_modules/type-fest": { "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" @@ -9340,6 +10712,8 @@ }, "node_modules/type-is": { "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "license": "MIT", "dependencies": { "media-typer": "0.3.0", @@ -9351,6 +10725,8 @@ }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "license": "MIT", "dependencies": { "is-typedarray": "^1.0.0" @@ -9372,10 +10748,14 @@ }, "node_modules/uc.micro": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", "license": "MIT" }, "node_modules/uglify-js": { "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", "license": "BSD-2-Clause", "bin": { "uglifyjs": "bin/uglifyjs" @@ -9386,10 +10766,14 @@ }, "node_modules/underscore": { "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", "license": "MIT" }, "node_modules/undici-types": { "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "license": "MIT" }, "node_modules/unique-filename": { @@ -9416,6 +10800,8 @@ }, "node_modules/unique-string": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", "license": "MIT", "dependencies": { "crypto-random-string": "^2.0.0" @@ -9426,6 +10812,8 @@ }, "node_modules/universal-analytics": { "version": "0.5.3", + "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.5.3.tgz", + "integrity": "sha512-HXSMyIcf2XTvwZ6ZZQLfxfViRm/yTGoRgDeTbojtq6rezeyKB0sTBcKH2fhddnteAHRcHiKgr/ACpbgjGOC6RQ==", "license": "MIT", "dependencies": { "debug": "^4.3.1", @@ -9437,6 +10825,8 @@ }, "node_modules/universalify": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "license": "MIT", "engines": { "node": ">= 10.0.0" @@ -9444,6 +10834,8 @@ }, "node_modules/unpipe": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -9451,6 +10843,8 @@ }, "node_modules/update-browserslist-db": { "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, "funding": [ { @@ -9480,6 +10874,8 @@ }, "node_modules/update-notifier-cjs": { "version": "5.1.6", + "resolved": "https://registry.npmjs.org/update-notifier-cjs/-/update-notifier-cjs-5.1.6.tgz", + "integrity": "sha512-wgxdSBWv3x/YpMzsWz5G4p4ec7JWD0HCl8W6bmNB6E5Gwo+1ym5oN4hiXpLf0mPySVEJEIsYlkshnplkg2OP9A==", "license": "BSD-2-Clause", "dependencies": { "boxen": "^5.0.0", @@ -9518,6 +10914,8 @@ }, "node_modules/uri-js": { "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -9525,14 +10923,20 @@ }, "node_modules/url-join": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz", + "integrity": "sha512-H6dnQ/yPAAVzMQRvEvyz01hhfQL5qRWSEt7BX8t9DqnPw9BjMb64fjIRq76Uvf1hkHp+mTZvEVJ5guXOT0Xqaw==", "license": "MIT" }, "node_modules/util-deprecate": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, "node_modules/utils-merge": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "license": "MIT", "engines": { "node": ">= 0.4.0" @@ -9540,6 +10944,8 @@ }, "node_modules/uuid": { "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "license": "MIT", "bin": { "uuid": "dist/bin/uuid" @@ -9547,6 +10953,8 @@ }, "node_modules/v8-to-istanbul": { "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dev": true, "license": "ISC", "dependencies": { @@ -9559,40 +10967,23 @@ } }, "node_modules/valid-url": { - "version": "1.0.9" + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", + "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==" }, "node_modules/vary": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/verror": { - "version": "1.10.0", - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/verror/node_modules/extsprintf": { - "version": "1.4.1", - "engines": [ - "node >=0.6.0" - ], - "license": "MIT" - }, "node_modules/walker": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -9601,6 +10992,8 @@ }, "node_modules/wcwidth": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "license": "MIT", "dependencies": { "defaults": "^1.0.3" @@ -9608,10 +11001,14 @@ }, "node_modules/webidl-conversions": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "license": "BSD-2-Clause" }, "node_modules/websocket-driver": { "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", "license": "Apache-2.0", "dependencies": { "http-parser-js": ">=0.5.1", @@ -9624,6 +11021,8 @@ }, "node_modules/websocket-extensions": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "license": "Apache-2.0", "engines": { "node": ">=0.8.0" @@ -9635,6 +11034,8 @@ }, "node_modules/whatwg-url": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "license": "MIT", "dependencies": { "tr46": "~0.0.3", @@ -9643,6 +11044,8 @@ }, "node_modules/which": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -9664,6 +11067,8 @@ }, "node_modules/widest-line": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", "license": "MIT", "dependencies": { "string-width": "^4.0.0" @@ -9674,6 +11079,8 @@ }, "node_modules/winston": { "version": "3.11.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz", + "integrity": "sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==", "license": "MIT", "dependencies": { "@colors/colors": "^1.6.0", @@ -9706,6 +11113,8 @@ }, "node_modules/word-wrap": { "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9713,6 +11122,8 @@ }, "node_modules/wrap-ansi": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -9728,10 +11139,14 @@ }, "node_modules/wrappy": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, "node_modules/write-file-atomic": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", @@ -9742,6 +11157,8 @@ }, "node_modules/ws": { "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", "license": "MIT", "engines": { "node": ">=8.3.0" @@ -9761,6 +11178,8 @@ }, "node_modules/xdg-basedir": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "license": "MIT", "engines": { "node": ">=8" @@ -9768,6 +11187,8 @@ }, "node_modules/xmlcreate": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", "license": "Apache-2.0" }, "node_modules/xmlhttprequest": { @@ -9780,6 +11201,8 @@ }, "node_modules/y18n": { "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "license": "ISC", "engines": { "node": ">=10" @@ -9787,10 +11210,14 @@ }, "node_modules/yallist": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "license": "ISC" }, "node_modules/yaml": { "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "license": "ISC", "engines": { "node": ">= 14" @@ -9798,6 +11225,8 @@ }, "node_modules/yargs": { "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "license": "MIT", "dependencies": { "cliui": "^8.0.1", @@ -9814,6 +11243,8 @@ }, "node_modules/yargs-parser": { "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "license": "ISC", "engines": { "node": ">=12" @@ -9821,6 +11252,8 @@ }, "node_modules/yocto-queue": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "license": "MIT", "engines": { "node": ">=10" @@ -9831,6 +11264,8 @@ }, "node_modules/zip-stream": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", + "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", "license": "MIT", "dependencies": { "archiver-utils": "^3.0.4", @@ -9843,6 +11278,8 @@ }, "node_modules/zip-stream/node_modules/archiver-utils": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", + "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", "license": "MIT", "dependencies": { "glob": "^7.2.3", diff --git a/integration_test/package.json b/integration_test/package.json index fbe878cde..bb584a13a 100644 --- a/integration_test/package.json +++ b/integration_test/package.json @@ -3,23 +3,25 @@ "module": "index.ts", "type": "module", "dependencies": { - "@firebase/analytics": "^0.10.0", - "firebase": "^8.2.3", + "@google-cloud/eventarc": "^3.1.0", + "@google-cloud/tasks": "^5.1.0", + "firebase": "^10.8.0", "firebase-admin": "^11.11.0", - "firebase-tools": "^12.9.1", - "js-yaml": "^4.1.0" + "firebase-tools": "^13.3.0", + "js-yaml": "^4.1.0", + "node-fetch": "2" }, "scripts": { "copyfiles": "cp ./serviceAccount.json ./dist/serviceAccount.json", "build": "tsc && npm run copyfiles", - "test": "jest", + "test": "jest --detectOpenHandles", "start": "npm run build && node dist/run.js" }, "devDependencies": { "@types/firebase": "^3.2.1", "@types/jest": "^29.5.11", "@types/js-yaml": "^4.0.9", - "@types/node-fetch": "^2.6.9", + "@types/node-fetch": "2", "jest": "^29.7.0", "ts-jest": "^29.1.1" } diff --git a/integration_test/package.json.template b/integration_test/package.json.template index 42cdf121c..67e55974c 100644 --- a/integration_test/package.json.template +++ b/integration_test/package.json.template @@ -5,15 +5,13 @@ "build": "./node_modules/.bin/tsc" }, "dependencies": { - "@google-cloud/pubsub": "^2.10.0", "firebase-admin": "__FIREBASE_ADMIN__", - "firebase-functions": "__SDK_TARBALL__", - "node-fetch": "^2.6.7" + "firebase-functions": "__SDK_TARBALL__" }, "main": "lib/index.js", "devDependencies": { "@types/node-fetch": "^2.6.1", - "typescript": "^4.3.5" + "typescript": "^5.3.3" }, "engines": { "node": "__NODE_VERSION__" diff --git a/integration_test/run.ts b/integration_test/run.ts index 712d1c9a1..236d1850a 100644 --- a/integration_test/run.ts +++ b/integration_test/run.ts @@ -33,10 +33,24 @@ const { PROJECT_ID, DATABASE_URL, STORAGE_BUCKET, + FIREBASE_APP_ID, + FIREBASE_MEASUREMENT_ID, + FIREBASE_AUTH_DOMAIN, + FIREBASE_API_KEY, + GOOGLE_ANALYTICS_API_SECRET, } = process.env; const TEST_RUN_ID = `t${Date.now()}`; -if (!PROJECT_ID || !DATABASE_URL || !STORAGE_BUCKET) { +if ( + !PROJECT_ID || + !DATABASE_URL || + !STORAGE_BUCKET || + !FIREBASE_APP_ID || + !FIREBASE_MEASUREMENT_ID || + !FIREBASE_AUTH_DOMAIN || + !FIREBASE_API_KEY || + !GOOGLE_ANALYTICS_API_SECRET +) { console.error("Required environment variables are not set. Exiting..."); process.exit(1); } @@ -64,7 +78,14 @@ const env = { let modifiedYaml: any; function generateUniqueHash(originalName: string): string { - return `${TEST_RUN_ID}-${originalName}`; + // Function name can only contain letters, numbers and hyphens and be less than 100 chars. + const modifiedName = `${TEST_RUN_ID}-${originalName}`; + if (modifiedName.length > 100) { + throw new Error( + `Function name is too long. Original=${originalName}, Modified=${modifiedName}` + ); + } + return modifiedName; } /** @@ -259,5 +280,8 @@ async function runIntegrationTests(): Promise { } runIntegrationTests() - .then(() => console.log("Integration tests completed")) + .then(() => { + console.log("Integration tests completed"); + process.exit(0); + }) .catch((error) => console.error("An error occurred during integration tests", error)); diff --git a/integration_test/tests/firebaseSetup.ts b/integration_test/tests/firebaseSetup.ts index 7d0ce39dc..d6c898f2a 100644 --- a/integration_test/tests/firebaseSetup.ts +++ b/integration_test/tests/firebaseSetup.ts @@ -1,5 +1,4 @@ import * as admin from "firebase-admin"; -import "@firebase/analytics"; import { cert } from "firebase-admin/app"; /** diff --git a/integration_test/tests/globalTeardown.ts b/integration_test/tests/globalTeardown.ts deleted file mode 100644 index 88615a43c..000000000 --- a/integration_test/tests/globalTeardown.ts +++ /dev/null @@ -1,69 +0,0 @@ -import * as admin from "firebase-admin"; -import { initializeFirebase } from "./firebaseSetup"; - -async function deleteCollection( - db: admin.firestore.Firestore, - collectionPath: string, - batchSize: number -) { - const collectionRef = db.collection(collectionPath); - const query = collectionRef.orderBy("__name__").limit(batchSize); - - return new Promise((resolve, reject) => { - deleteQueryBatch(db, query, batchSize, resolve, reject).then(resolve).catch(reject); - }); -} - -async function deleteQueryBatch( - db: admin.firestore.Firestore, - query: admin.firestore.Query, - batchSize: number, - resolve: (value?: unknown) => void, - reject: (reason: any) => void -): Promise { - try { - const snapshot = await query.get(); - - if (snapshot.size === 0) { - resolve(); - return; - } - - const batch = db.batch(); - snapshot.docs.forEach((doc) => { - batch.delete(doc.ref); - }); - - await batch.commit(); - - process.nextTick(() => deleteQueryBatch(db, query, batchSize, resolve, reject)); - } catch (error) { - reject(error); - } -} - -export default async () => { - await initializeFirebase(); - - try { - // TODO: Only delete resources created by this test run. - // const db = admin.firestore(); - // await Promise.all([ - // deleteCollection(db, "userProfiles", 100), - // deleteCollection(db, "createUserTests", 100), - // deleteCollection(db, "deleteUserTests", 100), - // deleteCollection(db, "databaseOnWriteTests", 100), - // deleteCollection(db, "firestoreOnCreateTests", 100), - // deleteCollection(db, "firestoreOnUpdateTests", 100), - // deleteCollection(db, "firestoreOnDeleteTests", 100), - // deleteCollection(db, "httpsOnCallTests", 100), - // deleteCollection(db, "pubsubOnPublishTests", 100), - // deleteCollection(db, "pubsubScheduleTests", 100), - // deleteCollection(db, "tests", 100), - // ]); - } catch (error) { - console.error("Error in global teardown:", error); - } - - await admin.app().delete(); -}; diff --git a/integration_test/tests/utils.ts b/integration_test/tests/utils.ts index 367d17239..6750852cd 100644 --- a/integration_test/tests/utils.ts +++ b/integration_test/tests/utils.ts @@ -1 +1,157 @@ +import * as admin from "firebase-admin"; +import { CloudTasksClient, protos } from "@google-cloud/tasks"; +import fetch from "node-fetch"; + +interface AndroidDevice { + androidModelId: string; + androidVersionId: string; + locale: string; + orientation: string; +} + +const TESTING_API_SERVICE_NAME = "testing.googleapis.com"; + +export async function startTestRun(projectId: string, testId: string, accessToken: string) { + const device = await fetchDefaultDevice(accessToken); + return await createTestMatrix(accessToken, projectId, testId, device); +} + +async function fetchDefaultDevice(accessToken: string) { + const resp = await fetch( + `https://${TESTING_API_SERVICE_NAME}/v1/testEnvironmentCatalog/ANDROID`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/json", + }, + } + ); + if (!resp.ok) { + throw new Error(resp.statusText); + } + const data = await resp.json(); + const models = data?.androidDeviceCatalog?.models || []; + const defaultModels = models.filter( + (m: any) => + m.tags !== undefined && + m.tags.indexOf("default") > -1 && + m.supportedVersionIds !== undefined && + m.supportedVersionIds.length > 0 + ); + + if (defaultModels.length === 0) { + throw new Error("No default device found"); + } + + const model = defaultModels[0]; + const versions = model.supportedVersionIds; + + return { + androidModelId: model.id, + androidVersionId: versions[versions.length - 1], + locale: "en", + orientation: "portrait", + } as AndroidDevice; +} + +async function createTestMatrix( + accessToken: string, + projectId: string, + testId: string, + device: AndroidDevice +): Promise { + const body = { + projectId, + testSpecification: { + androidRoboTest: { + appApk: { + gcsPath: "gs://path/to/non-existing-app.apk", + }, + }, + }, + environmentMatrix: { + androidDeviceList: { + androidDevices: [device], + }, + }, + resultStorage: { + googleCloudStorage: { + gcsPath: "gs://" + admin.storage().bucket().name, + }, + }, + clientInfo: { + name: "CloudFunctionsSDKIntegrationTest", + clientInfoDetails: { + key: "testId", + value: testId, + }, + }, + }; + const resp = await fetch( + `https://${TESTING_API_SERVICE_NAME}/v1/projects/${projectId}/testMatrices`, + { + method: "POST", + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(body), + } + ); + if (!resp.ok) { + throw new Error(resp.statusText); + } + return; +} + export const timeout = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + +export async function createTask( + project: string, + queue: string, + location: string, + url: string, + payload: Record +) { + const client = new CloudTasksClient(); + const queuePath = client.queuePath(project, location, queue); + // try { + // await client.getQueue({ name: queuePath }); + // } catch (err: any) { + // if (err.code === 5) { + // // '5' is the error code for 'not found' in Google Cloud APIs + // const queue = { + // name: queuePath, + // }; + // const parent = client.locationPath(project, location); + // await client.createQueue({ parent, queue }); + // } else { + // throw err; + // } + // } + + const parent = client.queuePath(project, location, queue); + const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; + if (!serviceAccountPath) { + throw new Error("Environment configured incorrectly."); + } + const serviceAccount = await import(serviceAccountPath); + const task: protos.google.cloud.tasks.v2.ITask = { + httpRequest: { + httpMethod: "POST", + url, + oidcToken: { + serviceAccountEmail: serviceAccount.client_email, + }, + headers: { + "Content-Type": "application/json", + }, + body: Buffer.from(JSON.stringify(payload)).toString("base64"), + }, + }; + + const [response] = await client.createTask({ parent, task }); + if (!response) { + throw new Error("Unable to create task"); + } +} diff --git a/integration_test/tests/v1/analytics.test.ts b/integration_test/tests/v1/analytics.test.ts deleted file mode 100644 index 3c244abca..000000000 --- a/integration_test/tests/v1/analytics.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import admin from "firebase-admin"; -import firebase from "firebase/app"; -import { timeout } from "../utils"; -import { initializeFirebase } from "../firebaseSetup"; - -describe("Firebase Analytics event onLog trigger", () => { - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } - - await initializeFirebase(); - const analytics = firebase.analytics(); - await analytics.logEvent("in_app_purchase", { testId }); - await timeout(20000); - const logSnapshot = await admin.firestore().collection("analyticsEventTests").doc(testId).get(); - loggedContext = logSnapshot.data(); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should not include path", () => { - expect(loggedContext?.path).toBeUndefined(); - }); - - it("should have the right eventType", () => { - expect(loggedContext?.eventType).toEqual("google.firebase.analytics.event.onlog"); - }); - - it("should have eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - - it("should not have action", () => { - expect(loggedContext?.action).toBeUndefined(); - }); -}); diff --git a/integration_test/tests/v1/auth.test.ts b/integration_test/tests/v1/auth.test.ts index 8e7ec1884..277df3d51 100644 --- a/integration_test/tests/v1/auth.test.ts +++ b/integration_test/tests/v1/auth.test.ts @@ -2,23 +2,49 @@ import admin from "firebase-admin"; import { timeout } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; import { UserRecord } from "firebase-admin/lib/auth/user-record"; +import { initializeApp } from "firebase/app"; +import { getAuth, createUserWithEmailAndPassword, UserCredential } from "firebase/auth"; + +describe("Firebase Auth (v1)", () => { + let userIds: string[] = []; + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + const config = { + apiKey: process.env.FIREBASE_API_KEY, + authDomain: process.env.FIREBASE_AUTH_DOMAIN, + databaseURL: process.env.DATABASE_URL, + projectId, + storageBucket: process.env.STORAGE_BUCKET, + appId: process.env.FIREBASE_APP_ID, + measurementId: process.env.FIREBASE_MEASUREMENT_ID, + }; + const app = initializeApp(config); + + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + for (const userId in userIds) { + await admin.firestore().collection("userProfiles").doc(userId).delete(); + await admin.firestore().collection("authUserOnCreateTests").doc(userId).delete(); + await admin.firestore().collection("authUserOnDeleteTests").doc(userId).delete(); + await admin.firestore().collection("authBeforeCreateTests").doc(userId).delete(); + await admin.firestore().collection("authBeforeSignInTests").doc(userId).delete(); + } + }); -describe("Firebase Auth", () => { describe("user onCreate trigger", () => { - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; let userRecord: UserRecord; let loggedContext: admin.firestore.DocumentData | undefined; beforeAll(async () => { - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } - - await initializeFirebase(); - userRecord = await admin.auth().createUser({ - email: `${testId}@fake.com`, + email: `${testId}@fake-create.com`, password: "secret", displayName: `${testId}`, }); @@ -33,6 +59,8 @@ describe("Firebase Auth", () => { loggedContext = logSnapshot.data(); + userIds.push(userRecord.uid); + if (!loggedContext) { throw new Error("loggedContext is undefined"); } @@ -95,24 +123,17 @@ describe("Firebase Auth", () => { }); describe("user onDelete trigger", () => { - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; let userRecord: UserRecord; let logSnapshot; let loggedContext: admin.firestore.DocumentData | undefined; beforeAll(async () => { - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } - - await initializeFirebase(); - userRecord = await admin.auth().createUser({ - email: `${testId}@fake.com`, + email: `${testId}@fake-delete.com`, password: "secret", displayName: `${testId}`, }); + await admin.auth().deleteUser(userRecord.uid); await timeout(20000); @@ -124,6 +145,8 @@ describe("Firebase Auth", () => { .get(); loggedContext = logSnapshot.data(); + userIds.push(userRecord.uid); + if (!loggedContext) { throw new Error("loggedContext is undefined"); } @@ -159,48 +182,45 @@ describe("Firebase Auth", () => { }); describe("user beforeCreate trigger", () => { - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; - let userRecord; - let loggedContext; + let userRecord: UserCredential; + let loggedContext: admin.firestore.DocumentData | undefined; beforeAll(async () => { - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } + userRecord = await createUserWithEmailAndPassword( + getAuth(app), + `${testId}@fake-before-create.com`, + "secret" + ); - await initializeFirebase(); - userRecord = await admin.auth().createUser({ - email: `${testId}@fake.com`, - password: "secret", - displayName: `${testId}`, - }); - - await timeout(20000); + await timeout(15000); const logSnapshot = await admin .firestore() - .collection("userBeforeCreateTests") - .doc(userRecord.uid) + .collection("authBeforeCreateTests") + .doc(userRecord.user.uid) .get(); loggedContext = logSnapshot.data(); + + userIds.push(userRecord.user.uid); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } }); afterAll(async () => { - await admin.auth().deleteUser(userRecord.uid); + await admin.auth().deleteUser(userRecord.user.uid); }); it("should have a project as resource", () => { expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); }); - it("should not have a path", () => { - expect(loggedContext?.path).toBeUndefined(); - }); - - it("should have the correct eventType", async () => { - expect(loggedContext?.eventType).toEqual("google.firebase.auth.user.beforeCreate"); + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual( + "providers/cloud.auth/eventTypes/user.beforeCreate:password" + ); }); it("should have an eventId", () => { @@ -210,13 +230,56 @@ describe("Firebase Auth", () => { it("should have a timestamp", () => { expect(loggedContext?.timestamp).toBeDefined(); }); + }); - it("should not have auth", () => { - expect(loggedContext?.auth).toBeUndefined(); + describe("user beforeSignIn trigger", () => { + let userRecord: UserCredential; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + userRecord = await createUserWithEmailAndPassword( + getAuth(app), + `${testId}@fake-before-signin.com`, + "secret" + ); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("authBeforeSignInTests") + .doc(userRecord.user.uid) + .get(); + + loggedContext = logSnapshot.data(); + + userIds.push(userRecord.user.uid); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } }); - it("should not have an action", () => { - expect(loggedContext?.action).toBeUndefined(); + afterAll(async () => { + await admin.auth().deleteUser(userRecord.user.uid); + }); + + it("should have a project as resource", () => { + expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual( + "providers/cloud.auth/eventTypes/user.beforeSignIn:password" + ); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); }); }); }); diff --git a/integration_test/tests/v1/database.test.ts b/integration_test/tests/v1/database.test.ts index 564f4face..0f767dc0d 100644 --- a/integration_test/tests/v1/database.test.ts +++ b/integration_test/tests/v1/database.test.ts @@ -3,85 +3,320 @@ import { timeout } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; import { Reference } from "@firebase/database-types"; -describe("Firebase Database ref onWrite trigger", () => { +describe("Firebase Database (v1)", () => { const projectId = process.env.PROJECT_ID; const testId = process.env.TEST_RUN_ID; - let ref: Reference; - let loggedContext: admin.firestore.DocumentData | undefined; - beforeAll(async () => { - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + beforeAll(async () => { await initializeFirebase(); + }); - ref = admin.database().ref(`dbTests/${testId}/start`); + afterAll(async () => { + await admin.firestore().collection("databaseRefOnCreateTests").doc(testId).delete(); + await admin.firestore().collection("databaseRefOnDeleteTests").doc(testId).delete(); + await admin.firestore().collection("databaseRefOnUpdateTests").doc(testId).delete(); + await admin.firestore().collection("databaseRefOnWriteTests").doc(testId).delete(); + }); + + async function setupRef(refPath: string) { + const ref = admin.database().ref(refPath); await ref.set({ ".sv": "timestamp" }); - await timeout(20000); - const logSnapshot = await admin + return ref; + } + + async function teardownRef(ref: Reference) { + if (ref) { + try { + await ref.remove(); + } catch (err) { + console.log("Teardown error", err); + } + } + } + + function getLoggedContext(collectionName: string, testId: string) { + return admin .firestore() - .collection("databaseRefOnWriteTests") + .collection(collectionName) .doc(testId) - .get(); - loggedContext = logSnapshot.data(); + .get() + .then((logSnapshot) => logSnapshot.data()); + } - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } - }); + describe("ref onCreate trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; - afterAll(async () => { - await ref.parent?.remove(); - }); + beforeAll(async () => { + ref = await setupRef(`dbTests/${testId}/start`); + await timeout(20000); + loggedContext = await getLoggedContext("databaseRefOnCreateTests", testId); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); + afterAll(async () => { + await teardownRef(ref); + }); - it("should give refs access to admin data", async () => { - await ref.parent?.child("adminOnly").update({ allowed: 1 }); + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); - // Retrieve the updated data to verify the update operation - const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); - const adminData = adminDataSnapshot?.val(); + it("should give refs access to admin data", async () => { + await ref.parent?.child("adminOnly").update({ allowed: 1 }); - expect(adminData).toEqual({ allowed: 1 }); - }); + const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); + const adminData = adminDataSnapshot?.val(); - it("should have a correct ref url", () => { - expect(loggedContext?.url).toMatch( - new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests`) - ); - expect(loggedContext?.url).toMatch(/\/start$/); - }); + expect(adminData).toEqual({ allowed: 1 }); + }); - it("should have refs resources", () => - expect(loggedContext?.resource.name).toMatch( - new RegExp(`^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$`) - )); + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch( + new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) + ); + }); - it("should not include path", () => { - expect(loggedContext?.path).toBeUndefined(); - }); + it("should have refs resources", () => { + expect(loggedContext?.resource.name).toMatch( + new RegExp( + `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start` + ) + ); + }); - it("should have the right eventType", () => { - expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.write"); - }); + it("should not include path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.create"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); - it("should have eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + + it("should have admin authType", () => { + expect(loggedContext?.authType).toEqual("ADMIN"); + }); }); - it("should have timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); + describe("ref onDelete trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + ref = await setupRef(`dbTests/${testId}/start`); + await ref.remove(); + await timeout(20000); + loggedContext = await getLoggedContext("databaseRefOnDeleteTests", testId); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch( + new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) + ); + }); + + it("should have refs resources", () => { + expect(loggedContext?.resource.name).toMatch( + new RegExp( + `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` + ) + ); + }); + + it("should not include path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.delete"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + + it("should have admin authType", () => { + expect(loggedContext?.authType).toEqual("ADMIN"); + }); }); - it("should not have action", () => { - expect(loggedContext?.action).toBeUndefined(); + describe("ref onUpdate trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + ref = await setupRef(`dbTests/${testId}/start`); + await ref.update({ updated: true }); + await timeout(20000); + loggedContext = await getLoggedContext("databaseRefOnUpdateTests", testId); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + await teardownRef(ref); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + await ref.parent?.child("adminOnly").update({ allowed: 1 }); + + const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); + const adminData = adminDataSnapshot?.val(); + + expect(adminData).toEqual({ allowed: 1 }); + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch( + new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) + ); + }); + + it("should have refs resources", () => { + expect(loggedContext?.resource.name).toMatch( + new RegExp( + `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` + ) + ); + }); + + it("should not include path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.update"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + + it("should have admin authType", () => { + expect(loggedContext?.authType).toEqual("ADMIN"); + }); + + it("should log onUpdate event with updated data", async () => { + const parsedData = JSON.parse(loggedContext?.data ?? {}); + expect(parsedData).toEqual({ updated: true }); + }); }); - it("should have admin authType", () => { - expect(loggedContext?.authType).toEqual("ADMIN"); + describe("ref onWrite trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + ref = await setupRef(`dbTests/${testId}/start`); + + await timeout(20000); + + loggedContext = await getLoggedContext("databaseRefOnWriteTests", testId); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + await teardownRef(ref); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + await ref.parent?.child("adminOnly").update({ allowed: 1 }); + + const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); + const adminData = adminDataSnapshot?.val(); + + expect(adminData).toEqual({ allowed: 1 }); + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch( + new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) + ); + }); + + it("should have refs resources", () => { + expect(loggedContext?.resource.name).toMatch( + new RegExp( + `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` + ) + ); + }); + + it("should not include path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.write"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + + it("should have admin authType", () => { + expect(loggedContext?.authType).toEqual("ADMIN"); + }); }); }); diff --git a/integration_test/tests/v1/firestore.test.ts b/integration_test/tests/v1/firestore.test.ts index 858e0730a..a986523b2 100644 --- a/integration_test/tests/v1/firestore.test.ts +++ b/integration_test/tests/v1/firestore.test.ts @@ -2,66 +2,262 @@ import admin from "firebase-admin"; import { timeout } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; -describe("Firestore document onCreate trigger", () => { +describe("Cloud Firestore (v1)", () => { const projectId = process.env.PROJECT_ID; const testId = process.env.TEST_RUN_ID; - let loggedContext: admin.firestore.DocumentData | undefined; - let dataSnapshot: admin.firestore.DocumentSnapshot; - let docRef: admin.firestore.DocumentReference; - beforeAll(async () => { - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + beforeAll(async () => { await initializeFirebase(); + }); - docRef = admin.firestore().collection("tests").doc(testId); - await docRef.set({ test: testId }); - dataSnapshot = await docRef.get(); + afterAll(async () => { + await admin.firestore().collection("firestoreDocumentOnCreateTests").doc(testId).delete(); + await admin.firestore().collection("firestoreDocumentOnDeleteTests").doc(testId).delete(); + await admin.firestore().collection("firestoreDocumentOnUpdateTests").doc(testId).delete(); + await admin.firestore().collection("firestoreDocumentOnWriteTests").doc(testId).delete(); + }); - await timeout(20000); + describe("Document onCreate trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; - const logSnapshot = await admin - .firestore() - .collection("firestoreDocumentOnCreateTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({ test: testId }); + dataSnapshot = await docRef.get(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } - }); + await timeout(20000); - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); + const logSnapshot = await admin + .firestore() + .collection("firestoreDocumentOnCreateTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); - it("should give refs access to admin data", async () => { - const result = await docRef.set({ allowed: 1 }, { merge: true }); - expect(result).toBeTruthy(); - }); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); - it("should have well-formed resource", () => { - expect(loggedContext?.resource.name).toMatch( - `projects/${projectId}/databases/(default)/documents/tests/${testId}` - ); - }); + afterAll(async () => { + await admin.firestore().collection("tests").doc(testId).delete(); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + const result = await docRef.set({ allowed: 1 }, { merge: true }); + expect(result).toBeTruthy(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.resource.name).toMatch( + `projects/${projectId}/databases/(default)/documents/tests/${testId}` + ); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firestore.document.create"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); - it("should have the correct eventType", () => { - expect(loggedContext?.eventType).toEqual("google.firestore.document.create"); + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should have the correct data", () => { + expect(dataSnapshot.data()).toEqual({ test: testId }); + }); }); - it("should have an eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); + describe("Document onDelete trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({ test: testId }); + dataSnapshot = await docRef.get(); + + await docRef.delete(); + + await timeout(20000); + + // Refresh snapshot + dataSnapshot = await docRef.get(); + + const logSnapshot = await admin + .firestore() + .collection("firestoreDocumentOnDeleteTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + await admin.firestore().collection("tests").doc(testId).delete(); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.resource.name).toMatch( + `projects/${projectId}/databases/(default)/documents/tests/${testId}` + ); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firestore.document.delete"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have the data", () => { + expect(dataSnapshot.data()).toBeUndefined(); + }); }); - it("should have a timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); + describe("Document onUpdate trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({}); + dataSnapshot = await docRef.get(); + + await docRef.update({ test: testId }); + + await timeout(20000); + + // Refresh snapshot + dataSnapshot = await docRef.get(); + + const logSnapshot = await admin + .firestore() + .collection("firestoreDocumentOnUpdateTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + await admin.firestore().collection("tests").doc(testId).delete(); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.resource.name).toMatch( + `projects/${projectId}/databases/(default)/documents/tests/${testId}` + ); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firestore.document.update"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have the data", () => { + expect(dataSnapshot.data()).toStrictEqual({ test: testId }); + }); }); - it("should have the correct data", () => { - expect(dataSnapshot.data()).toEqual({ test: testId }); + describe("Document onWrite trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({ test: testId }); + dataSnapshot = await docRef.get(); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("firestoreDocumentOnWriteTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + await admin.firestore().collection("tests").doc(testId).delete(); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + const result = await docRef.set({ allowed: 1 }, { merge: true }); + expect(result).toBeTruthy(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.resource.name).toMatch( + `projects/${projectId}/databases/(default)/documents/tests/${testId}` + ); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firestore.document.write"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should have the correct data", () => { + expect(dataSnapshot.data()).toEqual({ test: testId }); + }); }); }); diff --git a/integration_test/tests/v1/https.test.ts b/integration_test/tests/v1/https.test.ts deleted file mode 100644 index 4ab3c6046..000000000 --- a/integration_test/tests/v1/https.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -import admin from "firebase-admin"; -import { initializeFirebase } from "../firebaseSetup"; -import { timeout } from "../utils"; -import fetch from "node-fetch"; - -// TODO: Temporarily disable - doesn't work unless running on projects w/ permission to create public functions. -// describe("HTTP onCall trigger", () => { -// const projectId = process.env.PROJECT_ID; -// const testId = process.env.TEST_RUN_ID; -// const region = process.env.REGION; -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// if (!testId || !projectId || !region) { -// throw new Error("Environment configured incorrectly."); -// } -// await initializeFirebase(); - -// const accessToken = await admin.credential.applicationDefault().getAccessToken(); -// const data = { foo: "bar", testId }; -// const response = await fetch( -// `https://${region}-${projectId}.cloudfunctions.net/${testId}-v2-callableTests`, -// { -// method: "POST", -// headers: { -// "Content-Type": "application/json", -// Authorization: `Bearer ${accessToken.access_token}`, -// }, -// body: JSON.stringify({ data }), -// } -// ); -// if (!response.ok) { -// throw new Error(response.statusText); -// } - -// await timeout(20000); - -// const logSnapshot = await admin.firestore().collection("httpsOnCallTests").doc(testId).get(); -// loggedContext = logSnapshot.data(); - -// if (!loggedContext) { -// throw new Error("loggedContext is undefined"); -// } -// }); - -// it("should have the correct data", () => { -// expect(loggedContext?.foo).toEqual("bar"); -// }); -// }); - -describe("HTTP onCall trigger (DISABLED)", () => { - it("should be disabled", () => { - expect(true).toBeTruthy(); - }); -}); diff --git a/integration_test/tests/v1/pubsub.test.ts b/integration_test/tests/v1/pubsub.test.ts index 5d677debb..af1a5f29b 100644 --- a/integration_test/tests/v1/pubsub.test.ts +++ b/integration_test/tests/v1/pubsub.test.ts @@ -1,115 +1,116 @@ import admin from "firebase-admin"; import { timeout } from "../utils"; import { PubSub } from "@google-cloud/pubsub"; -// import fetch from "node-fetch"; import { initializeFirebase } from "../firebaseSetup"; -describe("Pub/Sub onPublish trigger", () => { +describe("Pub/Sub (v1)", () => { const projectId = process.env.PROJECT_ID; const testId = process.env.TEST_RUN_ID; + const region = process.env.REGION; const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; - let loggedContext: admin.firestore.DocumentData | undefined; + const topicName = `firebase-schedule-${testId}-v1-pubsubScheduleTests-${region}`; - beforeAll(async () => { - if (!testId || !projectId || !serviceAccountPath) { - throw new Error("Environment configured incorrectly."); - } + if (!testId || !projectId || !region || !serviceAccountPath) { + throw new Error("Environment configured incorrectly."); + } + beforeAll(async () => { await initializeFirebase(); - - const serviceAccount = await import(serviceAccountPath); - const topic = new PubSub({ - credentials: serviceAccount.default, - projectId, - }).topic("pubsubTests"); - - await topic.publish(Buffer.from(JSON.stringify({ testId }))); - - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("pubsubOnPublishTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } }); - it("should have a topic as resource", () => { - expect(loggedContext?.resource.name).toEqual( - `projects/${process.env.PROJECT_ID}/topics/pubsubTests` - ); + afterAll(async () => { + await admin.firestore().collection("pubsubOnPublishTests").doc(testId).delete(); + await admin.firestore().collection("pubsubScheduleTests").doc(topicName).delete(); }); - it("should not have a path", () => { - expect(loggedContext?.path).toBeUndefined(); + describe("onPublish trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const serviceAccount = await import(serviceAccountPath); + const topic = new PubSub({ + credentials: serviceAccount.default, + projectId, + }).topic("pubsubTests"); + + await topic.publish(Buffer.from(JSON.stringify({ testId }))); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("pubsubOnPublishTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have a topic as resource", () => { + expect(loggedContext?.resource.name).toEqual( + `projects/${process.env.PROJECT_ID}/topics/pubsubTests` + ); + }); + + it("should not have a path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual("google.pubsub.topic.publish"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + + it("should have admin auth", () => { + expect(loggedContext?.auth).toBeUndefined(); + }); + + it("should have pubsub data", () => { + const decodedMessage = JSON.parse(loggedContext?.message); + const decoded = new Buffer(decodedMessage.data, "base64").toString(); + const parsed = JSON.parse(decoded); + expect(parsed.testId).toEqual(testId); + }); }); - it("should have the correct eventType", () => { - expect(loggedContext?.eventType).toEqual("google.pubsub.topic.publish"); - }); + describe("schedule trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; - it("should have an eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); + beforeAll(async () => { + const pubsub = new PubSub(); - it("should have timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); + const message = Buffer.from(JSON.stringify({ testId })); - it("should not have action", () => { - expect(loggedContext?.action).toBeUndefined(); - }); + await pubsub.topic(topicName).publish(message); - it("should have admin auth", () => { - expect(loggedContext?.auth).toBeUndefined(); - }); + await timeout(20000); - it("should have pubsub data", () => { - const decodedMessage = JSON.parse(loggedContext?.message); - const decoded = new Buffer(decodedMessage.data, "base64").toString(); - const parsed = JSON.parse(decoded); - expect(parsed.testId).toEqual(testId); + const logSnapshot = await admin + .firestore() + .collection("pubsubScheduleTests") + .doc(topicName) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have been called", () => { + expect(loggedContext).toBeDefined(); + }); }); }); - -// TODO: Uncomment this test when solution for test id access in scheduler. -// describe("Pub/Sub schedule trigger", () => { -// const testRunId = process.env.TEST_RUN_ID; -// let loggedContext; -// let logSnapshot; - -// beforeAll(async () => { -// try { -// await initializeFirebase(); -// const accessToken = await admin.credential.applicationDefault().getAccessToken(); -// const response = await fetch( -// `https://cloudscheduler.googleapis.com/v1/projects/${process.env.PROJECT_ID}/locations/${process.env.REGION}/jobs/firebase-schedule-${testRunId}-v1-schedule-${process.env.REGION}:run`, -// { -// method: "POST", -// headers: { -// "Content-Type": "application/json", -// Authorization: `Bearer ${accessToken.access_token}`, -// }, -// } -// ); -// if (!response.ok) { -// throw new Error(`Failed request with status ${response.status}!`); -// } - -// await timeout(15000); -// logSnapshot = await admin.firestore().collection("pubsubScheduleTests").doc(testRunId).get(); -// loggedContext = logSnapshot.data(); -// } catch (error) { -// console.error("Error in beforeAll:", error); -// throw error; -// } -// }); - -// it("should have been called", () => { -// expect(loggedContext).toBeDefined(); -// }); -// }); diff --git a/integration_test/tests/v1/remoteConfig.test.ts b/integration_test/tests/v1/remoteConfig.test.ts index 26e4e65bb..c05bb5da1 100644 --- a/integration_test/tests/v1/remoteConfig.test.ts +++ b/integration_test/tests/v1/remoteConfig.test.ts @@ -3,63 +3,72 @@ import { timeout } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; import fetch from "node-fetch"; -describe("Firebase Remote Config onUpdate trigger", () => { +describe("Firebase Remote Config (v1)", () => { const projectId = process.env.PROJECT_ID; const testId = process.env.TEST_RUN_ID; - let loggedContext: admin.firestore.DocumentData | undefined; - beforeAll(async () => { - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + beforeAll(async () => { await initializeFirebase(); + }); - const accessToken = await admin.credential.applicationDefault().getAccessToken(); - const resp = await fetch( - `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/remoteConfig`, - { - method: "PUT", - headers: { - Authorization: `Bearer ${accessToken.access_token}`, - "Content-Type": "application/json; UTF-8", - "Accept-Encoding": "gzip", - "If-Match": "*", - }, - body: JSON.stringify({ version: { description: testId } }), - } - ); - if (!resp.ok) { - throw new Error(resp.statusText); - } - await timeout(20000); - const logSnapshot = await admin - .firestore() - .collection("remoteConfigOnUpdateTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + afterAll(async () => { + await admin.firestore().collection("remoteConfigOnUpdateTests").doc(testId).delete(); }); - it("should have refs resources", () => - expect(loggedContext?.resource.name).toMatch(`projects/${process.env.PROJECT_ID}`)); + describe("onUpdate trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; - it("should have the right eventType", () => { - expect(loggedContext?.eventType).toEqual("google.firebase.remoteconfig.update"); - }); + beforeAll(async () => { + const accessToken = await admin.credential.applicationDefault().getAccessToken(); + const resp = await fetch( + `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/remoteConfig`, + { + method: "PUT", + headers: { + Authorization: `Bearer ${accessToken.access_token}`, + "Content-Type": "application/json; UTF-8", + "Accept-Encoding": "gzip", + "If-Match": "*", + }, + body: JSON.stringify({ version: { description: testId } }), + } + ); + if (!resp.ok) { + throw new Error(resp.statusText); + } + await timeout(20000); + const logSnapshot = await admin + .firestore() + .collection("remoteConfigOnUpdateTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); - it("should have eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); + it("should have refs resources", () => + expect(loggedContext?.resource.name).toMatch(`projects/${process.env.PROJECT_ID}`)); - it("should have timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.remoteconfig.update"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); - it("should not have auth", () => { - expect(loggedContext?.auth).toBeUndefined(); + it("should not have auth", () => { + expect(loggedContext?.auth).toBeUndefined(); + }); }); }); diff --git a/integration_test/tests/v1/storage.test.ts b/integration_test/tests/v1/storage.test.ts index 7ba440e38..4d8e251c6 100644 --- a/integration_test/tests/v1/storage.test.ts +++ b/integration_test/tests/v1/storage.test.ts @@ -13,59 +13,174 @@ async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { }); } -describe("Firebase Storage object onFinalize trigger", () => { +describe("Firebase Storage", () => { const testId = process.env.TEST_RUN_ID; - let loggedContext: admin.firestore.DocumentData | undefined; + if (!testId) { + throw new Error("Environment configured incorrectly."); + } beforeAll(async () => { - if (!testId) { - throw new Error("Environment configured incorrectly."); - } - await initializeFirebase(); - - const testContent = testId; - const buffer = Buffer.from(testContent, "utf-8"); - - await uploadBufferToFirebase(buffer, testId + ".txt"); - - await timeout(20000); - const logSnapshot = await admin - .firestore() - .collection("storageOnFinalizeTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } }); afterAll(async () => { - const file = admin - .storage() - .bucket() - .file(testId + ".txt"); - - const [exists] = await file.exists(); - if (exists) { - await file.delete(); - } + await admin.firestore().collection("storageOnFinalizeTests").doc(testId).delete(); + await admin.firestore().collection("storageOnDeleteTests").doc(testId).delete(); + await admin.firestore().collection("storageOnMetadataUpdateTests").doc(testId).delete(); }); - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); + describe("object onFinalize trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const testContent = testId; + const buffer = Buffer.from(testContent, "utf-8"); + + await uploadBufferToFirebase(buffer, testId + ".txt"); + + await timeout(20000); + const logSnapshot = await admin + .firestore() + .collection("storageOnFinalizeTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); - it("should have the right eventType", () => { - expect(loggedContext?.eventType).toEqual("google.storage.object.finalize"); + const [exists] = await file.exists(); + if (exists) { + await file.delete(); + } + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.storage.object.finalize"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); }); - it("should have eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); + describe("object onDelete trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const testContent = testId; + const buffer = Buffer.from(testContent, "utf-8"); + + await uploadBufferToFirebase(buffer, testId + ".txt"); + + await timeout(5000); // Short delay before delete + + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + await file.delete(); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("storageOnDeleteTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.storage.object.delete"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); }); - it("should have timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); + describe("object onMetadataUpdate trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const testContent = testId; + const buffer = Buffer.from(testContent, "utf-8"); + + await uploadBufferToFirebase(buffer, testId + ".txt"); + + // Trigger metadata update + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + await file.setMetadata({ contentType: "application/json" }); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("storageOnMetadataUpdateTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + + const [exists] = await file.exists(); + if (exists) { + await file.delete(); + } + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.storage.object.metadataUpdate"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); }); }); diff --git a/integration_test/tests/v1/tasks.test.ts b/integration_test/tests/v1/tasks.test.ts new file mode 100644 index 000000000..2b985ba59 --- /dev/null +++ b/integration_test/tests/v1/tasks.test.ts @@ -0,0 +1,46 @@ +import * as admin from "firebase-admin"; +import { initializeFirebase } from "../firebaseSetup"; +import { createTask, timeout } from "../utils"; + +describe("Cloud Tasks (v1)", () => { + const region = process.env.REGION; + const testId = process.env.TEST_RUN_ID; + const projectId = process.env.PROJECT_ID; + const queueName = `${testId}-v1-tasksOnDispatchTests`; + + if (!testId || !projectId || !region) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("tasksOnDispatchTests").doc(testId).delete(); + }); + + describe("onDispatch trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const url = `https://${region}-${projectId}.cloudfunctions.net/${testId}-v1-tasksOnDispatchTests`; + await createTask(projectId, queueName, region, url, { data: { testId } }); + + await timeout(20000); + const logSnapshot = await admin + .firestore() + .collection("tasksOnDispatchTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have correct event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v1/testLab.test.ts b/integration_test/tests/v1/testLab.test.ts index ee931163b..b6a7e5d07 100644 --- a/integration_test/tests/v1/testLab.test.ts +++ b/integration_test/tests/v1/testLab.test.ts @@ -1,152 +1,52 @@ import admin from "firebase-admin"; -import { timeout } from "../utils"; +import { startTestRun, timeout } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; -import fetch from "node-fetch"; -interface AndroidDevice { - androidModelId: string; - androidVersionId: string; - locale: string; - orientation: string; -} - -const TESTING_API_SERVICE_NAME = "testing.googleapis.com"; - -export async function startTestRun(projectId: string, testId: string, accessToken: string) { - const device = await fetchDefaultDevice(accessToken); - return await createTestMatrix(accessToken, projectId, testId, device); -} - -async function fetchDefaultDevice(accessToken: string) { - const resp = await fetch( - `https://${TESTING_API_SERVICE_NAME}/v1/testEnvironmentCatalog/ANDROID`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/json", - }, - } - ); - if (!resp.ok) { - throw new Error(resp.statusText); - } - const data = await resp.json(); - const models = data?.androidDeviceCatalog?.models || []; - const defaultModels = models.filter( - (m: any) => - m.tags !== undefined && - m.tags.indexOf("default") > -1 && - m.supportedVersionIds !== undefined && - m.supportedVersionIds.length > 0 - ); - - if (defaultModels.length === 0) { - throw new Error("No default device found"); - } - - const model = defaultModels[0]; - const versions = model.supportedVersionIds; - - return { - androidModelId: model.id, - androidVersionId: versions[versions.length - 1], - locale: "en", - orientation: "portrait", - } as AndroidDevice; -} - -async function createTestMatrix( - accessToken: string, - projectId: string, - testId: string, - device: AndroidDevice -): Promise { - const body = { - projectId, - testSpecification: { - androidRoboTest: { - appApk: { - gcsPath: "gs://path/to/non-existing-app.apk", - }, - }, - }, - environmentMatrix: { - androidDeviceList: { - androidDevices: [device], - }, - }, - resultStorage: { - googleCloudStorage: { - gcsPath: "gs://" + admin.storage().bucket().name, - }, - }, - clientInfo: { - name: "CloudFunctionsSDKIntegrationTest", - clientInfoDetails: { - key: "testId", - value: testId, - }, - }, - }; - const resp = await fetch( - `https://${TESTING_API_SERVICE_NAME}/v1/projects/${projectId}/testMatrices`, - { - method: "POST", - headers: { - Authorization: `Bearer ${accessToken}`, - "Content-Type": "application/json", - }, - body: JSON.stringify(body), - } - ); - if (!resp.ok) { - throw new Error(resp.statusText); - } - return; -} - -describe("TestLab test matrix onComplete trigger", () => { +describe("TestLab (v1)", () => { const projectId = process.env.PROJECT_ID; const testId = process.env.TEST_RUN_ID; - let loggedContext: admin.firestore.DocumentData | undefined; - beforeAll(async () => { - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + beforeAll(async () => { await initializeFirebase(); - - const accessToken = await admin.credential.applicationDefault().getAccessToken(); - await startTestRun(projectId, testId, accessToken.access_token); - await timeout(20000); - const logSnapshot = await admin - .firestore() - .collection("testLabOnCompleteTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } - }); - - it("should have eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); }); - it("should have right eventType", () => { - expect(loggedContext?.eventType).toEqual("google.testing.testMatrix.complete"); + afterAll(async () => { + await admin.firestore().collection("testLabOnCompleteTests").doc(testId).delete(); }); - it("should be in state 'INVALID'", () => { - const matrix = JSON.parse(loggedContext?.matrix); - expect(matrix?.state).toEqual("INVALID"); + describe("test matrix onComplete trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const accessToken = await admin.credential.applicationDefault().getAccessToken(); + await startTestRun(projectId, testId, accessToken.access_token); + await timeout(20000); + const logSnapshot = await admin + .firestore() + .collection("testLabOnCompleteTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.testing.testMatrix.complete"); + }); + + it("should be in state 'INVALID'", () => { + const matrix = JSON.parse(loggedContext?.matrix); + expect(matrix?.state).toEqual("INVALID"); + }); }); }); - -// describe("Firebase TestLab onComplete trigger", () => { -// test("should have refs resources", async () => { -// console.log("test"); -// }); -// }); diff --git a/integration_test/tests/v2/database.test.ts b/integration_test/tests/v2/database.test.ts new file mode 100644 index 000000000..79b9cd521 --- /dev/null +++ b/integration_test/tests/v2/database.test.ts @@ -0,0 +1,215 @@ +import admin from "firebase-admin"; +import { timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; +import { Reference } from "@firebase/database-types"; + +describe("Firebase Database (v2)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("databaseCreatedTests").doc(testId).delete(); + await admin.firestore().collection("databaseDeletedTests").doc(testId).delete(); + await admin.firestore().collection("databaseUpdatesTests").doc(testId).delete(); + await admin.firestore().collection("databaseWrittenTests").doc(testId).delete(); + }); + + async function setupRef(refPath: string) { + const ref = admin.database().ref(refPath); + await ref.set({ ".sv": "timestamp" }); + return ref; + } + + async function teardownRef(ref: Reference) { + if (ref) { + try { + await ref.remove(); + } catch (err) { + console.log("Teardown error", err); + } + } + } + + function getLoggedContext(collectionName: string, testId: string) { + return admin + .firestore() + .collection(collectionName) + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()); + } + + describe("created trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + ref = await setupRef(`databaseCreatedTests/${testId}/start`); + await timeout(20000); + loggedContext = await getLoggedContext("databaseCreatedTests", testId); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + await teardownRef(ref); + }); + + it("should give refs access to admin data", async () => { + await ref.parent?.child("adminOnly").update({ allowed: 1 }); + + const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); + const adminData = adminDataSnapshot?.val(); + + expect(adminData).toEqual({ allowed: 1 }); + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch(`databaseCreatedTests/${testId}/start`); + }); + + it("should have the right event type", () => { + expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.created"); + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + }); + + describe("deleted trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + ref = await setupRef(`databaseDeletedTests/${testId}/start`); + await teardownRef(ref); + await timeout(20000); + loggedContext = await getLoggedContext("databaseDeletedTests", testId); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch(`databaseDeletedTests/${testId}/start`); + }); + + it("should have the right event type", () => { + expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.deleted"); + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + }); + + describe("updated trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + ref = await setupRef(`databaseUpdatedTests/${testId}/start`); + await ref.update({ updated: true }); + await timeout(20000); + loggedContext = await getLoggedContext("databaseUpdatedTests", testId); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + await teardownRef(ref); + }); + + it("should give refs access to admin data", async () => { + await ref.parent?.child("adminOnly").update({ allowed: 1 }); + + const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); + const adminData = adminDataSnapshot?.val(); + + expect(adminData).toEqual({ allowed: 1 }); + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch(`databaseUpdatedTests/${testId}/start`); + }); + + it("should have the right event type", () => { + expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.updated"); + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + + it("should have updated data", async () => { + const parsedData = JSON.parse(loggedContext?.data ?? {}); + expect(parsedData).toEqual({ updated: true }); + }); + }); + + describe("written trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + ref = await setupRef(`databaseWrittenTests/${testId}/start`); + await timeout(20000); + loggedContext = await getLoggedContext("databaseWrittenTests", testId); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + await teardownRef(ref); + }); + + it("should give refs access to admin data", async () => { + await ref.parent?.child("adminOnly").update({ allowed: 1 }); + + const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); + const adminData = adminDataSnapshot?.val(); + + expect(adminData).toEqual({ allowed: 1 }); + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch(`databaseWrittenTests/${testId}/start`); + }); + + it("should have the right event type", () => { + expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.written"); + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v2/eventarc.test.ts b/integration_test/tests/v2/eventarc.test.ts new file mode 100644 index 000000000..de1ab3b08 --- /dev/null +++ b/integration_test/tests/v2/eventarc.test.ts @@ -0,0 +1,73 @@ +import admin from "firebase-admin"; +import { initializeFirebase } from "../firebaseSetup"; +import { CloudEvent, getEventarc } from "firebase-admin/eventarc"; +import { timeout } from "../utils"; + +describe("Eventarc (v2)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + const region = process.env.REGION; + + if (!testId || !projectId || !region) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("eventarcOnCustomEventPublishedTests").doc(testId).delete(); + }); + + describe("onCustomEventPublished trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const cloudEvent: CloudEvent = { + type: "achieved-leaderboard", + source: testId, + subject: "Welcome to the top 10", + data: { + message: "You have achieved the nth position in our leaderboard! To see...", + testId, + }, + }; + await getEventarc().channel(`locations/${region}/channels/firebase`).publish(cloudEvent); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("eventarcOnCustomEventPublishedTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have well-formed source", () => { + expect(loggedContext?.source).toMatch(testId); + }); + + it("should have the correct type", () => { + expect(loggedContext?.type).toEqual("achieved-leaderboard"); + }); + + it("should have an id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + + it("should not have the data", () => { + const eventData = JSON.parse(loggedContext?.data || "{}"); + expect(eventData.testId).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v2/firestore.test.ts b/integration_test/tests/v2/firestore.test.ts new file mode 100644 index 000000000..7d2efac5e --- /dev/null +++ b/integration_test/tests/v2/firestore.test.ts @@ -0,0 +1,247 @@ +import admin from "firebase-admin"; +import { timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; + +describe("Cloud Firestore (v2)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("firestoreOnDocumentCreatedTests").doc(testId).delete(); + await admin.firestore().collection("firestoreOnDocumentDeletedTests").doc(testId).delete(); + await admin.firestore().collection("firestoreOnDocumentUpdatedTests").doc(testId).delete(); + await admin.firestore().collection("firestoreOnDocumentWrittenTests").doc(testId).delete(); + }); + + describe("Document created trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({ test: testId }); + dataSnapshot = await docRef.get(); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("firestoreOnDocumentCreatedTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + const result = await docRef.set({ allowed: 1 }, { merge: true }); + expect(result).toBeTruthy(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.source).toMatch( + `//firestore.googleapis.com/projects/${projectId}/databases/(default)` + ); + }); + + it("should have the correct type", () => { + expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.created"); + }); + + it("should have an id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + + it("should have the correct data", () => { + expect(dataSnapshot.data()).toEqual({ test: testId }); + }); + }); + + describe("Document deleted trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({ test: testId }); + dataSnapshot = await docRef.get(); + + await docRef.delete(); + + await timeout(20000); + + // Refresh snapshot + dataSnapshot = await docRef.get(); + + const logSnapshot = await admin + .firestore() + .collection("firestoreOnDocumentDeletedTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have well-formed source", () => { + expect(loggedContext?.source).toMatch( + `//firestore.googleapis.com/projects/${projectId}/databases/(default)` + ); + }); + + it("should have the correct type", () => { + expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.deleted"); + }); + + it("should have an id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + + it("should not have the data", () => { + expect(dataSnapshot.data()).toBeUndefined(); + }); + }); + + describe("Document updated trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({}); + dataSnapshot = await docRef.get(); + + await docRef.update({ test: testId }); + + await timeout(20000); + + // Refresh snapshot + dataSnapshot = await docRef.get(); + + const logSnapshot = await admin + .firestore() + .collection("firestoreOnDocumentUpdatedTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.source).toMatch( + `//firestore.googleapis.com/projects/${projectId}/databases/(default)` + ); + }); + + it("should have the correct type", () => { + expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.updated"); + }); + + it("should have an id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + + it("should have the correct data", () => { + expect(dataSnapshot.data()).toStrictEqual({ test: testId }); + }); + }); + + describe("Document written trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({ test: testId }); + dataSnapshot = await docRef.get(); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("firestoreOnDocumentWrittenTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + const result = await docRef.set({ allowed: 1 }, { merge: true }); + expect(result).toBeTruthy(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.source).toMatch( + `//firestore.googleapis.com/projects/${projectId}/databases/(default)` + ); + }); + + it("should have the correct type", () => { + expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.written"); + }); + + it("should have an id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + + it("should have the correct data", () => { + expect(dataSnapshot.data()).toEqual({ test: testId }); + }); + }); +}); diff --git a/integration_test/tests/v2/https.test.ts b/integration_test/tests/v2/https.test.ts deleted file mode 100644 index ab4b8b6ec..000000000 --- a/integration_test/tests/v2/https.test.ts +++ /dev/null @@ -1,54 +0,0 @@ -import admin from "firebase-admin"; -import fetch from "node-fetch"; -import { timeout } from "../utils"; -import { initializeFirebase } from "../firebaseSetup"; - -// describe("HTTPS onCall trigger", () => { -// const projectId = process.env.PROJECT_ID; -// const region = process.env.REGION; -// const testId = process.env.TEST_RUN_ID; -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// if (!testId || !projectId || !region) { -// throw new Error("Environment configured incorrectly."); -// } -// await initializeFirebase(); - -// const accessToken = await admin.credential.applicationDefault().getAccessToken(); -// const data = { foo: "bar", testId }; -// const response = await fetch( -// `https://${region}-${projectId}.cloudfunctions.net/${testId}-v2-callableTests`, -// { -// method: "POST", -// headers: { -// "Content-Type": "application/json", -// Authorization: `Bearer ${accessToken.access_token}`, -// }, -// body: JSON.stringify({ data }), -// } -// ); -// if (!response.ok) { -// throw new Error(response.statusText); -// } - -// await timeout(15000); - -// const logSnapshot = await admin.firestore().collection("httpsOnCallV2Tests").doc(testId).get(); -// loggedContext = logSnapshot.data(); - -// if (!loggedContext) { -// throw new Error("loggedContext is undefined"); -// } -// }); - -// it("should have the correct data", () => { -// expect(loggedContext?.foo).toMatch("bar"); -// }); -// }); - -describe("HTTP onCall trigger (DISABLED)", () => { - it("should be disabled", () => { - expect(true).toBeTruthy(); - }); -}); diff --git a/integration_test/tests/v2/identity.test.ts b/integration_test/tests/v2/identity.test.ts new file mode 100644 index 000000000..760a57430 --- /dev/null +++ b/integration_test/tests/v2/identity.test.ts @@ -0,0 +1,140 @@ +import admin from "firebase-admin"; +import { timeout } from "../utils"; +import { initializeApp } from "firebase/app"; +import { initializeFirebase } from "../firebaseSetup"; +import { getAuth, createUserWithEmailAndPassword, UserCredential } from "firebase/auth"; + +describe("Firebase Identity (v2)", () => { + const userIds: string[] = []; + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + const config = { + apiKey: process.env.FIREBASE_API_KEY, + authDomain: process.env.FIREBASE_AUTH_DOMAIN, + databaseURL: process.env.DATABASE_URL, + projectId, + storageBucket: process.env.STORAGE_BUCKET, + appId: process.env.FIREBASE_APP_ID, + measurementId: process.env.FIREBASE_MEASUREMENT_ID, + }; + const app = initializeApp(config); + + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + for (const userId in userIds) { + await admin.firestore().collection("userProfiles").doc(userId).delete(); + await admin.firestore().collection("authUserOnCreateTests").doc(userId).delete(); + await admin.firestore().collection("authUserOnDeleteTests").doc(userId).delete(); + await admin.firestore().collection("authBeforeCreateTests").doc(userId).delete(); + await admin.firestore().collection("authBeforeSignInTests").doc(userId).delete(); + } + }); + describe("beforeUserCreated trigger", () => { + let userRecord: UserCredential; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + userRecord = await createUserWithEmailAndPassword( + getAuth(app), + `${testId}@fake-create.com`, + "secret" + ); + + userIds.push(userRecord.user.uid); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("identityBeforeUserCreatedTests") + .doc(userRecord.user.uid) + .get(); + + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + await admin.auth().deleteUser(userRecord.user.uid); + }); + + it("should have a project as resource", () => { + expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual( + "providers/cloud.auth/eventTypes/user.beforeCreate:password" + ); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + }); + + describe("identityBeforeUserSignedInTests trigger", () => { + let userRecord: UserCredential; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + userRecord = await createUserWithEmailAndPassword( + getAuth(app), + `${testId}@fake-before-signin.com`, + "secret" + ); + + userIds.push(userRecord.user.uid); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("identityBeforeUserSignedInTests") + .doc(userRecord.user.uid) + .get(); + + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + await admin.auth().deleteUser(userRecord.user.uid); + }); + + it("should have a project as resource", () => { + expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual( + "providers/cloud.auth/eventTypes/user.beforeSignIn:password" + ); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v2/pubsub.test.ts b/integration_test/tests/v2/pubsub.test.ts new file mode 100644 index 000000000..05fd00b18 --- /dev/null +++ b/integration_test/tests/v2/pubsub.test.ts @@ -0,0 +1,74 @@ +import admin from "firebase-admin"; +import { timeout } from "../utils"; +import { PubSub } from "@google-cloud/pubsub"; +import { initializeFirebase } from "../firebaseSetup"; + +describe("Pub/Sub (v2)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + const region = process.env.REGION; + const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; + + if (!testId || !projectId || !region || !serviceAccountPath) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("pubsubOnMessagePublishedTests").doc(testId).delete(); + }); + + describe("onMessagePublished trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const serviceAccount = await import(serviceAccountPath); + const topic = new PubSub({ + credentials: serviceAccount.default, + projectId, + }).topic("custom_message_tests"); + + await topic.publish(Buffer.from(JSON.stringify({ testId }))); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("pubsubOnMessagePublishedTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have a topic as source", () => { + expect(loggedContext?.source).toEqual( + `//pubsub.googleapis.com/projects/${projectId}/topics/custom_message_tests` + ); + }); + + it("should have the correct event type", () => { + expect(loggedContext?.type).toEqual("google.cloud.pubsub.topic.v1.messagePublished"); + }); + + it("should have an event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + + it("should have pubsub data", () => { + const decodedMessage = JSON.parse(loggedContext?.message); + const decoded = new Buffer(decodedMessage.data, "base64").toString(); + const parsed = JSON.parse(decoded); + expect(parsed.testId).toEqual(testId); + }); + }); +}); diff --git a/integration_test/tests/v2/remoteConfig.test.ts b/integration_test/tests/v2/remoteConfig.test.ts new file mode 100644 index 000000000..25a97147b --- /dev/null +++ b/integration_test/tests/v2/remoteConfig.test.ts @@ -0,0 +1,68 @@ +import admin from "firebase-admin"; +import { timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; +import fetch from "node-fetch"; + +describe("Firebase Remote Config (v2)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("remoteConfigOnConfigUpdatedTests").doc(testId).delete(); + }); + + describe("onUpdated trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const accessToken = await admin.credential.applicationDefault().getAccessToken(); + const resp = await fetch( + `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/remoteConfig`, + { + method: "PUT", + headers: { + Authorization: `Bearer ${accessToken.access_token}`, + "Content-Type": "application/json; UTF-8", + "Accept-Encoding": "gzip", + "If-Match": "*", + }, + body: JSON.stringify({ version: { description: testId } }), + } + ); + if (!resp.ok) { + throw new Error(resp.statusText); + } + await timeout(20000); + const logSnapshot = await admin + .firestore() + .collection("remoteConfigOnConfigUpdatedTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have the right event type", () => { + // TODO: not sure if the nested remoteconfig.remoteconfig is expected? + expect(loggedContext?.type).toEqual("google.firebase.remoteconfig.remoteConfig.v1.updated"); + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v2/scheduler.test.ts b/integration_test/tests/v2/scheduler.test.ts index 4d75bd5d5..c27275c3f 100644 --- a/integration_test/tests/v2/scheduler.test.ts +++ b/integration_test/tests/v2/scheduler.test.ts @@ -2,55 +2,59 @@ import admin from "firebase-admin"; import { timeout } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; -// describe("Scheduler onSchedule trigger", () => { -// const projectId = process.env.PROJECT_ID; -// const region = process.env.REGION; -// const testId = process.env.TEST_RUN_ID; -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// if (!testId || !projectId || !region) { -// throw new Error("Environment configured incorrectly."); -// } -// await initializeFirebase(); - -// const accessToken = await admin.credential.applicationDefault().getAccessToken(); - -// const response = await fetch( -// `https://cloudscheduler.googleapis.com/v1/projects/${projectId}/locations/us-central1/jobs/firebase-schedule-${testId}-v2-schedule-${region}:run`, -// { -// method: "POST", -// headers: { -// "Content-Type": "application/json", -// Authorization: `Bearer ${accessToken.access_token}`, -// }, -// } -// ); -// if (!response.ok) { -// throw new Error(`Failed request with status ${response.status}!`); -// } - -// await timeout(15000); - -// const logSnapshot = await admin -// .firestore() -// .collection("schedulerOnScheduleV2Tests") -// .doc(testId) -// .get(); -// loggedContext = logSnapshot.data(); - -// if (!loggedContext) { -// throw new Error("loggedContext is undefined"); -// } -// }); - -// it("should trigger when the scheduler fires", () => { -// expect(loggedContext?.success).toBeTruthy(); -// }); -// }); - -describe("HTTP onCall trigger (DISABLED)", () => { - it("should be disabled", () => { - expect(true).toBeTruthy(); +describe("Scheduler", () => { + const projectId = process.env.PROJECT_ID; + const region = process.env.REGION; + const testId = process.env.TEST_RUN_ID; + + if (!testId || !projectId || !region) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("schedulerOnScheduleV2Tests").doc(testId).delete(); + }); + + describe("onSchedule trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const accessToken = await admin.credential.applicationDefault().getAccessToken(); + const jobName = `firebase-schedule-${testId}-v2-schedule-${region}`; + const response = await fetch( + `https://cloudscheduler.googleapis.com/v1/projects/${projectId}/locations/us-central1/jobs/firebase-schedule-${testId}-v2-schedule-${region}:run`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${accessToken.access_token}`, + }, + } + ); + if (!response.ok) { + throw new Error(`Failed request with status ${response.status}!`); + } + + await timeout(15000); + + const logSnapshot = await admin + .firestore() + .collection("schedulerOnScheduleV2Tests") + .doc(jobName) + .get(); + loggedContext = logSnapshot.data(); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should trigger when the scheduler fires", () => { + expect(loggedContext?.success).toBeTruthy(); + }); }); }); diff --git a/integration_test/tests/v2/storage.test.ts b/integration_test/tests/v2/storage.test.ts new file mode 100644 index 000000000..cec7197ee --- /dev/null +++ b/integration_test/tests/v2/storage.test.ts @@ -0,0 +1,175 @@ +import * as admin from "firebase-admin"; +import { timeout } from "../../tests/utils"; +import { initializeFirebase } from "../../tests/firebaseSetup"; + +async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { + const bucket = admin.storage().bucket(); + + const file = bucket.file(fileName); + await file.save(buffer, { + metadata: { + contentType: "text/plain", + }, + }); +} + +describe("Firebase Storage (v2)", () => { + const testId = process.env.TEST_RUN_ID; + + if (!testId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("storageOnObjectFinalizedTests").doc(testId).delete(); + await admin.firestore().collection("storageOnObjectDeletedTests").doc(testId).delete(); + await admin.firestore().collection("storageOnObjectMetadataUpdatedTests").doc(testId).delete(); + }); + + describe("onObjectFinalized trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const testContent = testId; + const buffer = Buffer.from(testContent, "utf-8"); + + await uploadBufferToFirebase(buffer, testId + ".txt"); + + await timeout(20000); + const logSnapshot = await admin + .firestore() + .collection("storageOnObjectFinalizedTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + + const [exists] = await file.exists(); + if (exists) { + await file.delete(); + } + }); + + it("should have the right event type", () => { + expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.finalized"); + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + }); + + describe("onDeleted trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const testContent = testId; + const buffer = Buffer.from(testContent, "utf-8"); + + await uploadBufferToFirebase(buffer, testId + ".txt"); + + await timeout(5000); // Short delay before delete + + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + await file.delete(); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("storageOnObjectDeletedTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have the right event type", () => { + expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.deleted"); + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + }); + + describe("onMetadataUpdated trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const testContent = testId; + const buffer = Buffer.from(testContent, "utf-8"); + + await uploadBufferToFirebase(buffer, testId + ".txt"); + + // Trigger metadata update + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + await file.setMetadata({ contentType: "application/json" }); + + await timeout(20000); + + const logSnapshot = await admin + .firestore() + .collection("storageOnObjectMetadataUpdatedTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + + const [exists] = await file.exists(); + if (exists) { + await file.delete(); + } + }); + + it("should have the right event type", () => { + expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.metadataUpdated"); + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v2/tasks.test.ts b/integration_test/tests/v2/tasks.test.ts new file mode 100644 index 000000000..cb3d9954a --- /dev/null +++ b/integration_test/tests/v2/tasks.test.ts @@ -0,0 +1,45 @@ +import * as admin from "firebase-admin"; +import { initializeFirebase } from "../firebaseSetup"; +import { createTask, timeout } from "../utils"; + +describe("Cloud Tasks (v2)", () => { + const region = process.env.REGION; + const testId = process.env.TEST_RUN_ID; + const projectId = process.env.PROJECT_ID; + const queueName = `${testId}-v2-tasksOnTaskDispatchedTests`; + + if (!testId || !projectId || !region) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("tasksOnTaskDispatchedTests").doc(testId).delete(); + }); + + describe("onDispatch trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const url = `https://${region}-${projectId}.cloudfunctions.net/${testId}-v2-tasksOnTaskDispatchedTests`; + await createTask(projectId, queueName, region, url, { data: { testId } }); + await timeout(20000); + const logSnapshot = await admin + .firestore() + .collection("tasksOnTaskDispatchedTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have correct event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v2/testLab.test.ts b/integration_test/tests/v2/testLab.test.ts new file mode 100644 index 000000000..58a6c8149 --- /dev/null +++ b/integration_test/tests/v2/testLab.test.ts @@ -0,0 +1,51 @@ +import admin from "firebase-admin"; +import { startTestRun, timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; + +describe("TestLab (v2)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("testLabOnTestMatrixCompletedTests").doc(testId).delete(); + }); + + describe("test matrix onComplete trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const accessToken = await admin.credential.applicationDefault().getAccessToken(); + await startTestRun(projectId, testId, accessToken.access_token); + await timeout(20000); + const logSnapshot = await admin + .firestore() + .collection("testLabOnTestMatrixCompletedTests") + .doc(testId) + .get(); + loggedContext = logSnapshot.data(); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have right event type", () => { + expect(loggedContext?.type).toEqual("google.firebase.testlab.testMatrix.v1.completed"); + }); + + it("should be in state 'INVALID'", () => { + expect(loggedContext?.state).toEqual("INVALID"); + }); + }); +}); From 151d19683f8419abba9131cb232f4d5d3ea7baf9 Mon Sep 17 00:00:00 2001 From: Kirsty Williams Date: Mon, 26 Feb 2024 12:10:18 +0000 Subject: [PATCH 04/25] chore: update readme --- integration_test/README.md | 10 ++++------ integration_test/tests/v2/storage.test.ts | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/integration_test/README.md b/integration_test/README.md index e774d0418..a4bcb9430 100644 --- a/integration_test/README.md +++ b/integration_test/README.md @@ -29,14 +29,12 @@ yarn start [x] Update existing tests to use jest (v1 and v2) [x] Add missing coverage for v1 and v2 (WIP) [x] Ensure proper teardown of resources (only those for current test run) -[] Check that we are properly tearing down all docs as side-effects -[] Analytics: since you cannot directly trigger onLog events from Firebase Analytics in a CI environment, the primary strategy is to isolate and test the logic within the Cloud Functions by mocking Firebase services and the Analytics event data. This is done elsewhere via unit tests, so no additional coverage necessary. -[] Alerts: same as analytics -[] Auth blocking functions can only be deployed one at a time, half-way solution is to deploy v1 functions, run v1 tests, teardown, and repeat for v2. However, this still won't allow for multiple runs to happen in parallel. Solution needed before re-enabling auth/identity tests. -[] Https tests were commented out previously, comments remain as before for same reasons +[] Analytics: since you cannot directly trigger onLog events from Firebase Analytics in a CI environment, the primary strategy is to isolate and test the logic within the Cloud Functions by mocking Firebase services and the Analytics event data. This is done elsewhere via unit tests, so no additional coverage added. +[] Alerts: same as analytics, couldn't find way to trigger. +[] Auth blocking functions can only be deployed one at a time, half-way solution is to deploy v1 functions, run v1 tests, teardown, and repeat for v2. However, this still won't allow for multiple runs to happen in parallel. Solution needed before re-enabling auth/identity tests. You can run the suite with either v1 or v2 commented out to check test runs. +[] Https tests were commented out previously, comments remain as before [] Python runtime support ## Troubleshooting - Sometimes I ran into this reported [issue](https://github.com/firebase/firebase-tools/issues/793), I had to give it some period of time and attempt deploy again. Probably an upstream issue but may affect our approach here. Seems to struggle with deploying the large amount of trigger functions...? Falls over on Firebase Storage functions (if you comment these out everything else deploys as expected). -- Ensure service account has the necessary permissions for each service, and enable object versioning for the storage onArchive tests. diff --git a/integration_test/tests/v2/storage.test.ts b/integration_test/tests/v2/storage.test.ts index cec7197ee..4280497c6 100644 --- a/integration_test/tests/v2/storage.test.ts +++ b/integration_test/tests/v2/storage.test.ts @@ -1,6 +1,6 @@ import * as admin from "firebase-admin"; -import { timeout } from "../../tests/utils"; -import { initializeFirebase } from "../../tests/firebaseSetup"; +import { timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { const bucket = admin.storage().bucket(); From 4405786e47210267cf2c605fa0d40be15509149d Mon Sep 17 00:00:00 2001 From: exaby73 Date: Mon, 29 Jul 2024 04:11:33 +0530 Subject: [PATCH 05/25] feat: Update firebase_admin t0 12.3.0 in sample env --- integration_test/.env.example | 2 +- integration_test/package-lock.json | 1661 ++++++++++++++++++---------- 2 files changed, 1100 insertions(+), 563 deletions(-) diff --git a/integration_test/.env.example b/integration_test/.env.example index c4e6136e8..2eadc6dfd 100644 --- a/integration_test/.env.example +++ b/integration_test/.env.example @@ -3,7 +3,7 @@ PROJECT_ID= DATABASE_URL= STORAGE_BUCKET= NODE_VERSION=18 -FIREBASE_ADMIN=^10.0.0 +FIREBASE_ADMIN=^12.3.0 FIREBASE_APP_ID= FIREBASE_MEASUREMENT_ID= FIREBASE_AUTH_DOMAIN= diff --git a/integration_test/package-lock.json b/integration_test/package-lock.json index 1b1c67ced..53f7d6e0f 100644 --- a/integration_test/package-lock.json +++ b/integration_test/package-lock.json @@ -6,17 +6,19 @@ "": { "name": "integration_test", "dependencies": { + "@google-cloud/eventarc": "^3.1.0", "@google-cloud/tasks": "^5.1.0", - "firebase": "^8.2.3", + "firebase": "^10.8.0", "firebase-admin": "^11.11.0", "firebase-tools": "^13.3.0", - "js-yaml": "^4.1.0" + "js-yaml": "^4.1.0", + "node-fetch": "2" }, "devDependencies": { "@types/firebase": "^3.2.1", "@types/jest": "^29.5.11", "@types/js-yaml": "^4.0.9", - "@types/node-fetch": "^2.6.9", + "@types/node-fetch": "2", "jest": "^29.7.0", "ts-jest": "^29.1.1" } @@ -695,69 +697,220 @@ "node": ">=14" } }, + "node_modules/@firebase/analytics": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.6.tgz", + "integrity": "sha512-sB59EwcAvLt0fINGfMWmcRKcdUiYhE4AJNdDXSCSDo4D/ZXFRmb6qwX9YesKHXFB59XTLT03mAjqQcDrdym9qA==", + "dependencies": { + "@firebase/component": "0.6.8", + "@firebase/installations": "0.6.8", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.9.7", + "safevalues": "0.6.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/analytics-compat": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.12.tgz", + "integrity": "sha512-rXWnOAdEHbvBPLNjFLu3U0yDZVIAi+C0DL+RkUEOirfSqAeQaKzBCATeBw6+K7FVpEnknhm4tZrvVUVtJjShMw==", + "dependencies": { + "@firebase/analytics": "0.10.6", + "@firebase/analytics-types": "0.8.2", + "@firebase/component": "0.6.8", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/analytics-compat/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/analytics-compat/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/analytics-types": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.6.0.tgz", - "integrity": "sha512-kbMawY0WRPyL/lbknBkme4CNLl+Gw+E9G4OpNeXAauqoQiNkBgpIvZYy7BRT4sNGhZbxdxXxXbruqUwDzLmvTw==" + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.2.tgz", + "integrity": "sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw==" + }, + "node_modules/@firebase/analytics/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/analytics/node_modules/@firebase/logger": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/analytics/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" + } }, "node_modules/@firebase/app": { - "version": "0.9.25", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.9.25.tgz", - "integrity": "sha512-fX22gL5USXhOK21Hlh3oTeOzQZ6th6S2JrjXNEpBARmwzuUkqmVGVdsOCIFYIsLpK0dQE3o8xZnLrRg5wnzZ/g==", - "peer": true, + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.7.tgz", + "integrity": "sha512-7OCd53B+wnk/onbMLn/vM10pDjw97zzWUD8m3swtLYKJIrL+gDZ7HZ4xcbBLw7OB8ikzu8k1ORNjRe2itgAy4g==", "dependencies": { - "@firebase/component": "0.6.4", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.3", + "@firebase/component": "0.6.8", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.9.7", "idb": "7.1.1", "tslib": "^2.1.0" } }, "node_modules/@firebase/app-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.3.2.tgz", - "integrity": "sha512-YjpsnV1xVTO1B836IKijRcDeceLgHQNJ/DWa+Vky9UHkm1Mi4qosddX8LZzldaWRTWKX7BN1MbZOLY8r7M/MZQ==", - "dependencies": { - "@firebase/app-check-interop-types": "0.1.0", - "@firebase/app-check-types": "0.3.1", - "@firebase/component": "0.5.6", - "@firebase/logger": "0.2.6", - "@firebase/util": "1.3.0", + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.6.tgz", + "integrity": "sha512-uSzl0/SDw54hwuORWHDtldb9kK/QEVZOcoPn2mlIjMrJOLDug/6kcqnIN3IHzwmPyf23Epg0AGBktvG2FugW4w==", + "dependencies": { + "@firebase/component": "0.6.8", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.9.7", + "safevalues": "0.6.0", "tslib": "^2.1.0" }, "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/app-check-compat": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.13.tgz", + "integrity": "sha512-1sbS5Apq7dLys1KYdNQsmZLFIjJoFP9Mv4bzIcdXuTkWQjr3X2qAvwiTslC6prVAUMiTV0eM9eicdQIXVsiSRw==", + "dependencies": { + "@firebase/app-check": "0.8.6", + "@firebase/app-check-types": "0.5.2", + "@firebase/component": "0.6.8", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/app-check-compat/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-check-compat/node_modules/@firebase/logger": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-check-compat/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" } }, "node_modules/@firebase/app-check-interop-types": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.1.0.tgz", - "integrity": "sha512-uZfn9s4uuRsaX5Lwx+gFP3B6YsyOKUE+Rqa6z9ojT4VSRAsZFko9FRn6OxQUA1z5t5d08fY4pf+/+Dkd5wbdbA==" + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.2.tgz", + "integrity": "sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ==" }, "node_modules/@firebase/app-check-types": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.3.1.tgz", - "integrity": "sha512-KJ+BqJbdNsx4QT/JIT1yDj5p6D+QN97iJs3GuHnORrqL+DU3RWc9nSYQsrY6Tv9jVWcOkMENXAgDT484vzsm2w==" + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.2.tgz", + "integrity": "sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA==" }, "node_modules/@firebase/app-check/node_modules/@firebase/component": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", - "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", "dependencies": { - "@firebase/util": "1.3.0", + "@firebase/util": "1.9.7", "tslib": "^2.1.0" } }, "node_modules/@firebase/app-check/node_modules/@firebase/logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", - "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "dependencies": { + "tslib": "^2.1.0" + } }, "node_modules/@firebase/app-check/node_modules/@firebase/util": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", - "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-compat": { + "version": "0.2.37", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.37.tgz", + "integrity": "sha512-yiQLYT9LYQHuJGu/msuBLFtdWWTJ3Pz04E9gSeWykSB+8s0XXJJqfqQlghH7CcQ3KnJZR+Wuc3zSMcY3a+dn6Q==", + "dependencies": { + "@firebase/app": "0.10.7", + "@firebase/component": "0.6.8", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-compat/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-compat/node_modules/@firebase/logger": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app-compat/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", "dependencies": { "tslib": "^2.1.0" } @@ -768,15 +921,83 @@ "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==", "license": "Apache-2.0" }, + "node_modules/@firebase/app/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app/node_modules/@firebase/logger": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/app/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/auth": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.16.8.tgz", - "integrity": "sha512-mR0UXG4LirWIfOiCWxVmvz1o23BuKGxeItQ2cCUgXLTjNtWJXdcky/356iTUsd7ZV5A78s2NHeN5tIDDG6H4rg==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.7.5.tgz", + "integrity": "sha512-DMFR1OA/f1/voeuFbSORg9AP36pMgOoSb/DRgiDalLmIJsDTlQNMCu+givjMP4s/XL85+tBk2MerYnK/AscJjw==", "dependencies": { - "@firebase/auth-types": "0.10.3" + "@firebase/component": "0.6.8", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0", + "undici": "5.28.4" }, "peerDependencies": { - "@firebase/app": "0.x" + "@firebase/app": "0.x", + "@react-native-async-storage/async-storage": "^1.18.1" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } + } + }, + "node_modules/@firebase/auth-compat": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.10.tgz", + "integrity": "sha512-epDhgNIXmhl9DPuTW9Ec5NDJJKMFIdXBXiQI9O0xNHveow/ETtBCY86srzF7iCacqsd30CcpLwwXlhk8Y19Olg==", + "dependencies": { + "@firebase/auth": "1.7.5", + "@firebase/auth-types": "0.12.2", + "@firebase/component": "0.6.8", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0", + "undici": "5.28.4" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/auth-compat/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/auth-compat/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" } }, "node_modules/@firebase/auth-interop-types": { @@ -786,14 +1007,39 @@ "license": "Apache-2.0" }, "node_modules/@firebase/auth-types": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.10.3.tgz", - "integrity": "sha512-zExrThRqyqGUbXOFrH/sowuh2rRtfKHp9SBVY2vOqKWdCX1Ztn682n9WLtlUDsiYVIbBcwautYWk2HyCGFv0OA==", + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.2.tgz", + "integrity": "sha512-qsEBaRMoGvHO10unlDJhaKSuPn4pyoTtlQuP1ghZfzB6rNQPuhp/N/DcFZxm9i4v0SogjCbf9reWupwIvfmH6w==", "peerDependencies": { "@firebase/app-types": "0.x", "@firebase/util": "1.x" } }, + "node_modules/@firebase/auth/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/auth/node_modules/@firebase/logger": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/auth/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/component": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.4.tgz", @@ -843,226 +1089,251 @@ } }, "node_modules/@firebase/firestore": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-2.4.1.tgz", - "integrity": "sha512-S51XnILdhNt0ZA6bPnbxpqKPI5LatbGY9RQjA2TmATrjSPE3aWndJsLIrutI6aS9K+YFwy5+HLDKVRFYQfmKAw==", - "dependencies": { - "@firebase/component": "0.5.6", - "@firebase/firestore-types": "2.4.0", - "@firebase/logger": "0.2.6", - "@firebase/util": "1.3.0", - "@firebase/webchannel-wrapper": "0.5.1", - "@grpc/grpc-js": "^1.3.2", - "@grpc/proto-loader": "^0.6.0", - "node-fetch": "2.6.7", - "tslib": "^2.1.0" + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.6.4.tgz", + "integrity": "sha512-vk2MoH5HxYEhiNg1l+yBXq1Fkhue/11bFg4HdlTv6BJHcTnnAj2a+/afPpatcW4MOdYA3Tv+d5nGzWbbOC1SHw==", + "dependencies": { + "@firebase/component": "0.6.8", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.9.7", + "@firebase/webchannel-wrapper": "1.0.1", + "@grpc/grpc-js": "~1.9.0", + "@grpc/proto-loader": "^0.7.8", + "tslib": "^2.1.0", + "undici": "5.28.4" }, "engines": { - "node": "^8.13.0 || >=10.10.0" + "node": ">=10.10.0" }, "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/firestore-compat": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.33.tgz", + "integrity": "sha512-i42a2l31N95CwYEB7zmfK0FS1mrO6pwOLwxavCrwu1BCFrVVVQhUheTPIda/iGguK/2Nog0RaIR1bo7QkZEz3g==", + "dependencies": { + "@firebase/component": "0.6.8", + "@firebase/firestore": "4.6.4", + "@firebase/firestore-types": "3.0.2", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/firestore-compat/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/firestore-compat/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" } }, "node_modules/@firebase/firestore-types": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-2.4.0.tgz", - "integrity": "sha512-0dgwfuNP7EN6/OlK2HSNSQiQNGLGaRBH0gvgr1ngtKKJuJFuq0Z48RBMeJX9CGjV4TP9h2KaB+KrUKJ5kh1hMg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.2.tgz", + "integrity": "sha512-wp1A+t5rI2Qc/2q7r2ZpjUXkRVPtGMd6zCLsiWurjsQpqPgFin3AhNibKcIzoF2rnToNa/XYtyWXuifjOOwDgg==", "peerDependencies": { "@firebase/app-types": "0.x", "@firebase/util": "1.x" } }, "node_modules/@firebase/firestore/node_modules/@firebase/component": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", - "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", "dependencies": { - "@firebase/util": "1.3.0", + "@firebase/util": "1.9.7", "tslib": "^2.1.0" } }, "node_modules/@firebase/firestore/node_modules/@firebase/logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", - "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "dependencies": { + "tslib": "^2.1.0" + } }, "node_modules/@firebase/firestore/node_modules/@firebase/util": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", - "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", "dependencies": { "tslib": "^2.1.0" } }, - "node_modules/@firebase/firestore/node_modules/@grpc/proto-loader": { - "version": "0.6.13", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", - "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", + "node_modules/@firebase/firestore/node_modules/@grpc/grpc-js": { + "version": "1.9.15", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", + "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==", "dependencies": { - "@types/long": "^4.0.1", - "lodash.camelcase": "^4.3.0", - "long": "^4.0.0", - "protobufjs": "^6.11.3", - "yargs": "^16.2.0" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + "@grpc/proto-loader": "^0.7.8", + "@types/node": ">=12.12.47" }, "engines": { - "node": ">=6" - } - }, - "node_modules/@firebase/firestore/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "node": "^8.13.0 || >=10.10.0" } }, - "node_modules/@firebase/firestore/node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "node_modules/@firebase/firestore/node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" + "node_modules/@firebase/functions": { + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.6.tgz", + "integrity": "sha512-GPfIBPtpwQvsC7SQbgaUjLTdja0CsNwMoKSgrzA1FGGRk4NX6qO7VQU6XCwBiAFWbpbQex6QWkSMsCzLx1uibQ==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.2", + "@firebase/auth-interop-types": "0.2.3", + "@firebase/component": "0.6.8", + "@firebase/messaging-interop-types": "0.2.2", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0", + "undici": "5.28.4" }, "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "@firebase/app": "0.x" } }, - "node_modules/@firebase/firestore/node_modules/protobufjs": { - "version": "6.11.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", - "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", - "hasInstallScript": true, + "node_modules/@firebase/functions-compat": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.12.tgz", + "integrity": "sha512-r3XUb5VlITWpML46JymfJPkK6I9j4SNlO7qWIXUc0TUmkv0oAfVoiIt1F83/NuMZXaGr4YWA/794nVSy4GV8tw==", "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/long": "^4.0.1", - "@types/node": ">=13.7.0", - "long": "^4.0.0" + "@firebase/component": "0.6.8", + "@firebase/functions": "0.11.6", + "@firebase/functions-types": "0.6.2", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" }, - "bin": { - "pbjs": "bin/pbjs", - "pbts": "bin/pbts" + "peerDependencies": { + "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/firestore/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/@firebase/functions-compat/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@firebase/firestore/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "engines": { - "node": ">=10" + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" } }, - "node_modules/@firebase/functions": { - "version": "0.6.16", - "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.6.16.tgz", - "integrity": "sha512-KDPjLKSjtR/zEH06YXXbdWTi8gzbKHGRzL/+ibZQA/1MLq0IilfM+1V1Fh8bADsMCUkxkqoc1yiA4SUbH5ajJA==", - "dependencies": { - "@firebase/component": "0.5.6", - "@firebase/functions-types": "0.4.0", - "@firebase/messaging-types": "0.5.0", - "node-fetch": "2.6.7", + "node_modules/@firebase/functions-compat/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" } }, "node_modules/@firebase/functions-types": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.4.0.tgz", - "integrity": "sha512-3KElyO3887HNxtxNF1ytGFrNmqD+hheqjwmT3sI09FaDCuaxGbOnsXAXH2eQ049XRXw9YQpHMgYws/aUNgXVyQ==" + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.2.tgz", + "integrity": "sha512-0KiJ9lZ28nS2iJJvimpY4nNccV21rkQyor5Iheu/nq8aKXJqtJdeSlZDspjPSBBiHRzo7/GMUttegnsEITqR+w==" + }, + "node_modules/@firebase/functions/node_modules/@firebase/auth-interop-types": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz", + "integrity": "sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==" }, "node_modules/@firebase/functions/node_modules/@firebase/component": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", - "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", "dependencies": { - "@firebase/util": "1.3.0", + "@firebase/util": "1.9.7", "tslib": "^2.1.0" } }, "node_modules/@firebase/functions/node_modules/@firebase/util": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", - "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", "dependencies": { "tslib": "^2.1.0" } }, - "node_modules/@firebase/functions/node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "node_modules/@firebase/installations": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.8.tgz", + "integrity": "sha512-57V374qdb2+wT5v7+ntpLXBjZkO6WRgmAUbVkRfFTM/4t980p0FesbqTAcOIiM8U866UeuuuF8lYH70D3jM/jQ==", "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" + "@firebase/component": "0.6.8", + "@firebase/util": "1.9.7", + "idb": "7.1.1", + "tslib": "^2.1.0" }, "peerDependencies": { - "encoding": "^0.1.0" + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/installations-compat": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.8.tgz", + "integrity": "sha512-pI2q8JFHB7yIq/szmhzGSWXtOvtzl6tCUmyykv5C8vvfOVJUH6mP4M4iwjbK8S1JotKd/K70+JWyYlxgQ0Kpyw==", + "dependencies": { + "@firebase/component": "0.6.8", + "@firebase/installations": "0.6.8", + "@firebase/installations-types": "0.5.2", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/installations-compat/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/installations-compat/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" } }, "node_modules/@firebase/installations-types": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.3.4.tgz", - "integrity": "sha512-RfePJFovmdIXb6rYwtngyxuEcWnOrzdZd9m7xAW0gRxDIjBT20n3BOhjpmgRWXo/DAxRmS7bRjWAyTHY9cqN7Q==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.2.tgz", + "integrity": "sha512-que84TqGRZJpJKHBlF2pkvc1YcXrtEDOVGiDjovP/a3s6W4nlbohGXEsBJo0JCeeg/UG9A+DEZVDUV9GpklUzA==", "peerDependencies": { "@firebase/app-types": "0.x" } }, + "node_modules/@firebase/installations/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/installations/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@firebase/logger": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz", @@ -1073,292 +1344,601 @@ } }, "node_modules/@firebase/messaging": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.8.0.tgz", - "integrity": "sha512-hkFHDyVe1kMcY9KEG+prjCbvS6MtLUgVFUbbQqq7JQfiv58E07YCzRUcMrJolbNi/1QHH6Jv16DxNWjJB9+/qA==", - "dependencies": { - "@firebase/component": "0.5.6", - "@firebase/installations": "0.4.32", - "@firebase/messaging-types": "0.5.0", - "@firebase/util": "1.3.0", - "idb": "3.0.2", + "version": "0.12.10", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.10.tgz", + "integrity": "sha512-fGbxJPKpl2DIKNJGhbk4mYPcM+qE2gl91r6xPoiol/mN88F5Ym6UeRdMVZah+pijh9WxM55alTYwXuW40r1Y2Q==", + "dependencies": { + "@firebase/component": "0.6.8", + "@firebase/installations": "0.6.8", + "@firebase/messaging-interop-types": "0.2.2", + "@firebase/util": "1.9.7", + "idb": "7.1.1", "tslib": "^2.1.0" }, "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" + "@firebase/app": "0.x" } }, - "node_modules/@firebase/messaging-types": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@firebase/messaging-types/-/messaging-types-0.5.0.tgz", - "integrity": "sha512-QaaBswrU6umJYb/ZYvjR5JDSslCGOH6D9P136PhabFAHLTR4TWjsaACvbBXuvwrfCXu10DtcjMxqfhdNIB1Xfg==", + "node_modules/@firebase/messaging-compat": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.10.tgz", + "integrity": "sha512-FXQm7rcowkDm8kFLduHV35IRYCRo+Ng0PIp/t1+EBuEbyplaKkGjZ932pE+owf/XR+G/60ku2QRBptRGLXZydg==", + "dependencies": { + "@firebase/component": "0.6.8", + "@firebase/messaging": "0.12.10", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + }, "peerDependencies": { - "@firebase/app-types": "0.x" + "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/messaging/node_modules/@firebase/component": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", - "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "node_modules/@firebase/messaging-compat/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", "dependencies": { - "@firebase/util": "1.3.0", + "@firebase/util": "1.9.7", "tslib": "^2.1.0" } }, - "node_modules/@firebase/messaging/node_modules/@firebase/installations": { - "version": "0.4.32", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.32.tgz", - "integrity": "sha512-K4UlED1Vrhd2rFQQJih+OgEj8OTtrtH4+Izkx7ip2bhXSc+unk8ZhnF69D0kmh7zjXAqEDJrmHs9O5fI3rV6Tw==", + "node_modules/@firebase/messaging-compat/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", "dependencies": { - "@firebase/component": "0.5.6", - "@firebase/installations-types": "0.3.4", - "@firebase/util": "1.3.0", - "idb": "3.0.2", "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" } }, - "node_modules/@firebase/messaging/node_modules/@firebase/util": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", - "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "node_modules/@firebase/messaging-interop-types": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.2.tgz", + "integrity": "sha512-l68HXbuD2PPzDUOFb3aG+nZj5KA3INcPwlocwLZOzPp9rFM9yeuI9YLl6DQfguTX5eAGxO0doTR+rDLDvQb5tA==" + }, + "node_modules/@firebase/messaging/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", "dependencies": { + "@firebase/util": "1.9.7", "tslib": "^2.1.0" } }, - "node_modules/@firebase/messaging/node_modules/idb": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", - "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" + "node_modules/@firebase/messaging/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" + } }, "node_modules/@firebase/performance": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.4.18.tgz", - "integrity": "sha512-lvZW/TVDne2TyOpWbv++zjRn277HZpbjxbIPfwtnmKjVY1gJ+H77Qi1c2avVIc9hg80uGX/5tNf4pOApNDJLVg==", - "dependencies": { - "@firebase/component": "0.5.6", - "@firebase/installations": "0.4.32", - "@firebase/logger": "0.2.6", - "@firebase/performance-types": "0.0.13", - "@firebase/util": "1.3.0", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.8.tgz", + "integrity": "sha512-F+alziiIZ6Yn8FG47mxwljq+4XkgkT2uJIFRlkyViUQRLzrogaUJW6u/+6ZrePXnouKlKIwzqos3PVJraPEcCA==", + "dependencies": { + "@firebase/component": "0.6.8", + "@firebase/installations": "0.6.8", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.9.7", "tslib": "^2.1.0" }, "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/performance-compat": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.8.tgz", + "integrity": "sha512-o7TFClRVJd3VIBoY7KZQqtCeW0PC6v9uBzM6Lfw3Nc9D7hM6OonqecYvh7NwJ6R14k+xM27frLS4BcCvFHKw2A==", + "dependencies": { + "@firebase/component": "0.6.8", + "@firebase/logger": "0.4.2", + "@firebase/performance": "0.6.8", + "@firebase/performance-types": "0.2.2", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/performance-compat/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/performance-compat/node_modules/@firebase/logger": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/performance-compat/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" } }, "node_modules/@firebase/performance-types": { - "version": "0.0.13", - "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.0.13.tgz", - "integrity": "sha512-6fZfIGjQpwo9S5OzMpPyqgYAUZcFzZxHFqOyNtorDIgNXq33nlldTL/vtaUZA8iT9TT5cJlCrF/jthKU7X21EA==" + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.2.tgz", + "integrity": "sha512-gVq0/lAClVH5STrIdKnHnCo2UcPLjJlDUoEB/tB4KM+hAeHUxWKnpT0nemUPvxZ5nbdY/pybeyMe8Cs29gEcHA==" }, "node_modules/@firebase/performance/node_modules/@firebase/component": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", - "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", "dependencies": { - "@firebase/util": "1.3.0", + "@firebase/util": "1.9.7", "tslib": "^2.1.0" } }, - "node_modules/@firebase/performance/node_modules/@firebase/installations": { - "version": "0.4.32", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.32.tgz", - "integrity": "sha512-K4UlED1Vrhd2rFQQJih+OgEj8OTtrtH4+Izkx7ip2bhXSc+unk8ZhnF69D0kmh7zjXAqEDJrmHs9O5fI3rV6Tw==", + "node_modules/@firebase/performance/node_modules/@firebase/logger": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", "dependencies": { - "@firebase/component": "0.5.6", - "@firebase/installations-types": "0.3.4", - "@firebase/util": "1.3.0", - "idb": "3.0.2", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/performance/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/remote-config": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.8.tgz", + "integrity": "sha512-AMLqe6wfIRnjc6FkCWOSUjhc1fSTEf8o+cv1NolFvbiJ/tU+TqN4pI7pT+MIKQzNiq5fxLehkOx+xtAQBxPJKQ==", + "dependencies": { + "@firebase/component": "0.6.8", + "@firebase/installations": "0.6.8", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/remote-config-compat": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.8.tgz", + "integrity": "sha512-UxSFOp6dzFj2AHB8Bq/BYtbq5iFyizKx4Rd6WxAdaKYM8cnPMeK+l2v+Oogtjae+AeyHRI+MfL2acsfVe5cd2A==", + "dependencies": { + "@firebase/component": "0.6.8", + "@firebase/logger": "0.4.2", + "@firebase/remote-config": "0.4.8", + "@firebase/remote-config-types": "0.3.2", + "@firebase/util": "1.9.7", "tslib": "^2.1.0" }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/remote-config-compat/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/remote-config-compat/node_modules/@firebase/logger": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/remote-config-compat/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/remote-config-types": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.2.tgz", + "integrity": "sha512-0BC4+Ud7y2aPTyhXJTMTFfrGGLqdYXrUB9sJVAB8NiqJswDTc4/2qrE/yfUbnQJhbSi6ZaTTBKyG3n1nplssaA==" + }, + "node_modules/@firebase/remote-config/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/remote-config/node_modules/@firebase/logger": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/remote-config/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/storage": { + "version": "0.12.6", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.12.6.tgz", + "integrity": "sha512-Zgb9WuehJxzhj7pGXUvkAEaH+3HvLjD9xSZ9nepuXf5f8378xME7oGJtREr/RnepdDA5YW0XIxe0QQBNHpe1nw==", + "dependencies": { + "@firebase/component": "0.6.8", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0", + "undici": "5.28.4" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/storage-compat": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.9.tgz", + "integrity": "sha512-WWgAp5bTW961oIsCc9+98m4MIVKpEqztAlIngfHfwO/x3DYoBPRl/awMRG3CAXyVxG+7B7oHC5IsnqM+vTwx2A==", + "dependencies": { + "@firebase/component": "0.6.8", + "@firebase/storage": "0.12.6", + "@firebase/storage-types": "0.8.2", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/storage-compat/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/storage-compat/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/storage-types": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.2.tgz", + "integrity": "sha512-0vWu99rdey0g53lA7IShoA2Lol1jfnPovzLDUBuon65K7uKG9G+L5uO05brD9pMw+l4HRFw23ah3GwTGpEav6g==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/storage/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/storage/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/util": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", + "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/vertexai-preview": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@firebase/vertexai-preview/-/vertexai-preview-0.0.3.tgz", + "integrity": "sha512-KVtUWLp+ScgiwkDKAvNkVucAyhLVQp6C6lhnVEuIg4mWhWcS3oerjAeVhZT4uNofKwWxRsOaB2Yec7DMTXlQPQ==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.2", + "@firebase/component": "0.6.8", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, "peerDependencies": { "@firebase/app": "0.x", "@firebase/app-types": "0.x" } }, - "node_modules/@firebase/performance/node_modules/@firebase/logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", - "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" + "node_modules/@firebase/vertexai-preview/node_modules/@firebase/component": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", + "dependencies": { + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" + } }, - "node_modules/@firebase/performance/node_modules/@firebase/util": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", - "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "node_modules/@firebase/vertexai-preview/node_modules/@firebase/logger": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", "dependencies": { "tslib": "^2.1.0" } }, - "node_modules/@firebase/performance/node_modules/idb": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", - "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" + "node_modules/@firebase/vertexai-preview/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/webchannel-wrapper": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.1.tgz", + "integrity": "sha512-jmEnr/pk0yVkA7mIlHNnxCi+wWzOFUg0WyIotgkKAb2u1J7fAeDBcVNSTjTihbAYNusCLQdW5s9IJ5qwnEufcQ==" + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "license": "MIT", + "optional": true + }, + "node_modules/@google-cloud/eventarc": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@google-cloud/eventarc/-/eventarc-3.3.0.tgz", + "integrity": "sha512-nxTEKyPcgHBrbvjDsqxRufa2gjHilHwpChtXZg585xlcg1SP8kiCcCQeeEFKrzB5z8fYkGarYWg4QoBq1K7L4A==", + "dependencies": { + "google-gax": "^4.0.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/eventarc/node_modules/@grpc/grpc-js": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.11.1.tgz", + "integrity": "sha512-gyt/WayZrVPH2w/UTLansS7F9Nwld472JxxaETamrM8HNlsa+jSLNyKAZmhxI2Me4c3mQHFiS1wWHDY1g1Kthw==", + "dependencies": { + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@google-cloud/eventarc/node_modules/gaxios": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.0.tgz", + "integrity": "sha512-DSrkyMTfAnAm4ks9Go20QGOcXEyW/NmZhvTYBU2rb4afBB393WIMQPWPEDMl/k8xqiNN9HYq2zao3oWXsdl2Tg==", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9", + "uuid": "^10.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/eventarc/node_modules/gaxios/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } }, - "node_modules/@firebase/polyfill": { - "version": "0.3.36", - "resolved": "https://registry.npmjs.org/@firebase/polyfill/-/polyfill-0.3.36.tgz", - "integrity": "sha512-zMM9oSJgY6cT2jx3Ce9LYqb0eIpDE52meIzd/oe/y70F+v9u1LDqk5kUF5mf16zovGBWMNFmgzlsh6Wj0OsFtg==", + "node_modules/@google-cloud/eventarc/node_modules/gcp-metadata": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", + "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", "dependencies": { - "core-js": "3.6.5", - "promise-polyfill": "8.1.3", - "whatwg-fetch": "2.0.4" + "gaxios": "^6.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=14" } }, - "node_modules/@firebase/polyfill/node_modules/whatwg-fetch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", - "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" - }, - "node_modules/@firebase/remote-config": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.43.tgz", - "integrity": "sha512-laNM4MN0CfeSp7XCVNjYOC4DdV6mj0l2rzUh42x4v2wLTweCoJ/kc1i4oWMX9TI7Jw8Am5Wl71Awn1J2pVe5xA==", - "dependencies": { - "@firebase/component": "0.5.6", - "@firebase/installations": "0.4.32", - "@firebase/logger": "0.2.6", - "@firebase/remote-config-types": "0.1.9", - "@firebase/util": "1.3.0", - "tslib": "^2.1.0" + "node_modules/@google-cloud/eventarc/node_modules/google-auth-library": { + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.11.0.tgz", + "integrity": "sha512-epX3ww/mNnhl6tL45EQ/oixsY8JLEgUFoT4A5E/5iAR4esld9Kqv6IJGk7EmGuOgDvaarwF95hU2+v7Irql9lw==", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" }, - "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" + "engines": { + "node": ">=14" } }, - "node_modules/@firebase/remote-config-types": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.1.9.tgz", - "integrity": "sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA==" - }, - "node_modules/@firebase/remote-config/node_modules/@firebase/component": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", - "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "node_modules/@google-cloud/eventarc/node_modules/google-gax": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.3.8.tgz", + "integrity": "sha512-SKAQKtvdjtNW3PMOhmKEqpQP+2C5ZqNKfwWxy70efpSwxvRYuAcgMJs6aRHTBPJjz3SO6ZbiXwM6WIuGYFZ7LQ==", "dependencies": { - "@firebase/util": "1.3.0", - "tslib": "^2.1.0" + "@grpc/grpc-js": "^1.10.9", + "@grpc/proto-loader": "^0.7.13", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "google-auth-library": "^9.3.0", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^2.0.2", + "protobufjs": "^7.3.2", + "retry-request": "^7.0.0", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" } }, - "node_modules/@firebase/remote-config/node_modules/@firebase/installations": { - "version": "0.4.32", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.32.tgz", - "integrity": "sha512-K4UlED1Vrhd2rFQQJih+OgEj8OTtrtH4+Izkx7ip2bhXSc+unk8ZhnF69D0kmh7zjXAqEDJrmHs9O5fI3rV6Tw==", + "node_modules/@google-cloud/eventarc/node_modules/gtoken": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", + "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", "dependencies": { - "@firebase/component": "0.5.6", - "@firebase/installations-types": "0.3.4", - "@firebase/util": "1.3.0", - "idb": "3.0.2", - "tslib": "^2.1.0" + "gaxios": "^6.0.0", + "jws": "^4.0.0" }, - "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@firebase/remote-config/node_modules/@firebase/logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", - "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" - }, - "node_modules/@firebase/remote-config/node_modules/@firebase/util": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", - "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "node_modules/@google-cloud/eventarc/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dependencies": { - "tslib": "^2.1.0" + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" } }, - "node_modules/@firebase/remote-config/node_modules/idb": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", - "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" - }, - "node_modules/@firebase/storage": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.7.1.tgz", - "integrity": "sha512-T7uH6lAgNs/Zq8V3ElvR3ypTQSGWon/R7WRM2I5Td/d0PTsNIIHSAGB6q4Au8mQEOz3HDTfjNQ9LuQ07R6S2ug==", - "dependencies": { - "@firebase/component": "0.5.6", - "@firebase/storage-types": "0.5.0", - "@firebase/util": "1.3.0", - "node-fetch": "2.6.7", - "tslib": "^2.1.0" + "node_modules/@google-cloud/eventarc/node_modules/proto3-json-serializer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz", + "integrity": "sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ==", + "dependencies": { + "protobufjs": "^7.2.5" }, - "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@firebase/storage-types": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.5.0.tgz", - "integrity": "sha512-6Wv3Lu7s18hsgW7HG4BFwycTquZ3m/C8bjBoOsmPu0TD6M1GKwCzOC7qBdN7L6tRYPh8ipTj5+rPFrmhGfUVKA==", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" + "node_modules/@google-cloud/eventarc/node_modules/protobufjs": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.3.2.tgz", + "integrity": "sha512-RXyHaACeqXeqAKGLDl68rQKbmObRsTIn4TYVUUug1KfS47YWCo5MacGITEryugIgZqORCvJWEk4l449POg5Txg==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" } }, - "node_modules/@firebase/storage/node_modules/@firebase/component": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", - "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "node_modules/@google-cloud/eventarc/node_modules/retry-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", + "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", "dependencies": { - "@firebase/util": "1.3.0", - "tslib": "^2.1.0" + "@types/request": "^2.48.8", + "extend": "^3.0.2", + "teeny-request": "^9.0.0" + }, + "engines": { + "node": ">=14" } }, - "node_modules/@firebase/storage/node_modules/@firebase/util": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", - "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "node_modules/@google-cloud/eventarc/node_modules/teeny-request": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", + "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", "dependencies": { - "tslib": "^2.1.0" + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.9", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=14" } }, - "node_modules/@firebase/storage/node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "node_modules/@google-cloud/eventarc/node_modules/teeny-request/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dependencies": { - "whatwg-url": "^5.0.0" + "debug": "4" }, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "node": ">= 6.0.0" } }, - "node_modules/@firebase/util": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", - "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", - "license": "Apache-2.0", + "node_modules/@google-cloud/eventarc/node_modules/teeny-request/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dependencies": { - "tslib": "^2.1.0" + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/@firebase/webchannel-wrapper": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.5.1.tgz", - "integrity": "sha512-dZMzN0uAjwJXWYYAcnxIwXqRTZw3o14hGe7O6uhwjD1ZQWPVYA5lASgnNskEBra0knVBsOXB4KXg+HnlKewN/A==" - }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "license": "MIT", - "optional": true + "node_modules/@google-cloud/eventarc/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } }, "node_modules/@google-cloud/firestore": { "version": "6.8.0", @@ -1753,14 +2333,13 @@ } }, "node_modules/@grpc/proto-loader": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz", - "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==", - "license": "Apache-2.0", + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", - "protobufjs": "^7.2.4", + "protobufjs": "^7.2.5", "yargs": "^17.7.2" }, "bin": { @@ -2237,6 +2816,15 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, "node_modules/@jsdevtools/ono": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", @@ -4236,17 +4824,6 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, - "node_modules/core-js": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", - "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -4611,14 +5188,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dom-storage": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.1.0.tgz", - "integrity": "sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q==", - "engines": { - "node": "*" - } - }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -5378,28 +5947,37 @@ } }, "node_modules/firebase": { - "version": "8.10.1", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-8.10.1.tgz", - "integrity": "sha512-84z/zqF8Y5IpUYN8nREZ/bxbGtF5WJDOBy4y0hAxRzGpB5+2tw9PQgtTnUzk6MQiVEf/WOniMUL3pCVXKsxALw==", - "dependencies": { - "@firebase/analytics": "0.6.18", - "@firebase/app": "0.6.30", - "@firebase/app-check": "0.3.2", - "@firebase/app-types": "0.6.3", - "@firebase/auth": "0.16.8", - "@firebase/database": "0.11.0", - "@firebase/firestore": "2.4.1", - "@firebase/functions": "0.6.16", - "@firebase/installations": "0.4.32", - "@firebase/messaging": "0.8.0", - "@firebase/performance": "0.4.18", - "@firebase/polyfill": "0.3.36", - "@firebase/remote-config": "0.1.43", - "@firebase/storage": "0.7.1", - "@firebase/util": "1.3.0" - }, - "engines": { - "node": "^8.13.0 || >=10.10.0" + "version": "10.12.4", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.12.4.tgz", + "integrity": "sha512-SQz49NMpwG4MLTPZ9C8jBp7IyS2haTvsIvjclgu+v/jvzNtjZoxIcoF6A13EIfBHmJ5eiuVlvttxElOf7LnJew==", + "dependencies": { + "@firebase/analytics": "0.10.6", + "@firebase/analytics-compat": "0.2.12", + "@firebase/app": "0.10.7", + "@firebase/app-check": "0.8.6", + "@firebase/app-check-compat": "0.3.13", + "@firebase/app-compat": "0.2.37", + "@firebase/app-types": "0.9.2", + "@firebase/auth": "1.7.5", + "@firebase/auth-compat": "0.5.10", + "@firebase/database": "1.0.6", + "@firebase/database-compat": "1.0.6", + "@firebase/firestore": "4.6.4", + "@firebase/firestore-compat": "0.3.33", + "@firebase/functions": "0.11.6", + "@firebase/functions-compat": "0.3.12", + "@firebase/installations": "0.6.8", + "@firebase/installations-compat": "0.2.8", + "@firebase/messaging": "0.12.10", + "@firebase/messaging-compat": "0.2.10", + "@firebase/performance": "0.6.8", + "@firebase/performance-compat": "0.2.8", + "@firebase/remote-config": "0.4.8", + "@firebase/remote-config-compat": "0.2.8", + "@firebase/storage": "0.12.6", + "@firebase/storage-compat": "0.3.9", + "@firebase/util": "1.9.7", + "@firebase/vertexai-preview": "0.0.3" } }, "node_modules/firebase-admin": { @@ -5619,128 +6197,77 @@ "node": ">=10" } }, - "node_modules/firebase/node_modules/@firebase/analytics": { - "version": "0.6.18", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.6.18.tgz", - "integrity": "sha512-FXNtYDxbs9ynPbzUVuG94BjFPOPpgJ7156660uvCBuKgoBCIVcNqKkJQQ7TH8384fqvGjbjdcgARY9jgAHbtog==", - "dependencies": { - "@firebase/analytics-types": "0.6.0", - "@firebase/component": "0.5.6", - "@firebase/installations": "0.4.32", - "@firebase/logger": "0.2.6", - "@firebase/util": "1.3.0", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" - } - }, - "node_modules/firebase/node_modules/@firebase/app": { - "version": "0.6.30", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.30.tgz", - "integrity": "sha512-uAYEDXyK0mmpZ8hWQj5TNd7WVvfsU8PgsqKpGljbFBG/HhsH8KbcykWAAA+c1PqL7dt/dbt0Reh1y9zEdYzMhg==", - "dependencies": { - "@firebase/app-types": "0.6.3", - "@firebase/component": "0.5.6", - "@firebase/logger": "0.2.6", - "@firebase/util": "1.3.0", - "dom-storage": "2.1.0", - "tslib": "^2.1.0", - "xmlhttprequest": "1.8.0" - } - }, "node_modules/firebase/node_modules/@firebase/app-types": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.6.3.tgz", - "integrity": "sha512-/M13DPPati7FQHEQ9Minjk1HGLm/4K4gs9bR4rzLCWJg64yGtVC0zNg9gDpkw9yc2cvol/mNFxqTtd4geGrwdw==" + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz", + "integrity": "sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==" }, "node_modules/firebase/node_modules/@firebase/auth-interop-types": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.6.tgz", - "integrity": "sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" - } + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz", + "integrity": "sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==" }, "node_modules/firebase/node_modules/@firebase/component": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", - "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", + "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", "dependencies": { - "@firebase/util": "1.3.0", + "@firebase/util": "1.9.7", "tslib": "^2.1.0" } }, "node_modules/firebase/node_modules/@firebase/database": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.11.0.tgz", - "integrity": "sha512-b/kwvCubr6G9coPlo48PbieBDln7ViFBHOGeVt/bt82yuv5jYZBEYAac/mtOVSxpf14aMo/tAN+Edl6SWqXApw==", - "dependencies": { - "@firebase/auth-interop-types": "0.1.6", - "@firebase/component": "0.5.6", - "@firebase/database-types": "0.8.0", - "@firebase/logger": "0.2.6", - "@firebase/util": "1.3.0", - "faye-websocket": "0.11.3", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.6.tgz", + "integrity": "sha512-nrexUEG/fpVlHtWKkyfhTC3834kZ1WS7voNyqbBsBCqHXQOvznN5Z0L3nxBqdXSJyltNAf4ndFlQqm5gZiEczQ==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.2", + "@firebase/auth-interop-types": "0.2.3", + "@firebase/component": "0.6.8", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.9.7", + "faye-websocket": "0.11.4", "tslib": "^2.1.0" } }, - "node_modules/firebase/node_modules/@firebase/database-types": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.8.0.tgz", - "integrity": "sha512-7IdjAFRfPWyG3b4wcXyghb3Y1CLCSJFZIg1xl5GbTVMttSQFT4B5NYdhsfA34JwAsv5pMzPpjOaS3/K9XJ2KiA==", - "dependencies": { - "@firebase/app-types": "0.6.3", - "@firebase/util": "1.3.0" + "node_modules/firebase/node_modules/@firebase/database-compat": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.6.tgz", + "integrity": "sha512-1OGA0sLY47mkXjhICCrUTXEYFnSSXoiXWm1SHsN62b+Lzs5aKA3aWTjTUmYIoK93kDAMPkYpulSv8jcbH4Hwew==", + "dependencies": { + "@firebase/component": "0.6.8", + "@firebase/database": "1.0.6", + "@firebase/database-types": "1.0.4", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.9.7", + "tslib": "^2.1.0" } }, - "node_modules/firebase/node_modules/@firebase/installations": { - "version": "0.4.32", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.32.tgz", - "integrity": "sha512-K4UlED1Vrhd2rFQQJih+OgEj8OTtrtH4+Izkx7ip2bhXSc+unk8ZhnF69D0kmh7zjXAqEDJrmHs9O5fI3rV6Tw==", + "node_modules/firebase/node_modules/@firebase/database-types": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.4.tgz", + "integrity": "sha512-mz9ZzbH6euFXbcBo+enuJ36I5dR5w+enJHHjy9Y5ThCdKUseqfDjW3vCp1YxE9zygFCSjJJ/z1cQ+zodvUcwPQ==", "dependencies": { - "@firebase/component": "0.5.6", - "@firebase/installations-types": "0.3.4", - "@firebase/util": "1.3.0", - "idb": "3.0.2", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" + "@firebase/app-types": "0.9.2", + "@firebase/util": "1.9.7" } }, "node_modules/firebase/node_modules/@firebase/logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", - "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" - }, - "node_modules/firebase/node_modules/@firebase/util": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", - "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", "dependencies": { "tslib": "^2.1.0" } }, - "node_modules/firebase/node_modules/faye-websocket": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", - "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "node_modules/firebase/node_modules/@firebase/util": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", + "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" + "tslib": "^2.1.0" } }, - "node_modules/firebase/node_modules/idb": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", - "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" - }, "node_modules/fn.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", @@ -6360,8 +6887,7 @@ "node_modules/idb": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", - "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", - "peer": true + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" }, "node_modules/ieee754": { "version": "1.2.1", @@ -9216,11 +9742,6 @@ "license": "ISC", "optional": true }, - "node_modules/promise-polyfill": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz", - "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g==" - }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", @@ -9875,6 +10396,11 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, + "node_modules/safevalues": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/safevalues/-/safevalues-0.6.0.tgz", + "integrity": "sha512-MZ7DcTOcIoPXN36/UONVE9BT0pmwlCr9WcS7Pj/q4FxOwr33FkWC0CUWj/THQXYWxf/F7urbhaHaOeFPSqGqHA==" + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -10770,12 +11296,31 @@ "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", "license": "MIT" }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "license": "MIT" }, + "node_modules/undici/node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "engines": { + "node": ">=14" + } + }, "node_modules/unique-filename": { "version": "2.0.1", "license": "ISC", @@ -11191,14 +11736,6 @@ "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", "license": "Apache-2.0" }, - "node_modules/xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", From b0b39d6ad65add34515ac33801da91a89624bae3 Mon Sep 17 00:00:00 2001 From: exaby73 Date: Mon, 7 Oct 2024 10:32:17 +0530 Subject: [PATCH 06/25] wip: Integration tests fixes --- cloudbuild.yaml | 16 + integration_test/.gitignore | 3 + integration_test/functions/src/region.ts | 3 +- .../functions/src/v1/storage-tests.ts | 80 +- .../functions/src/v2/firestore-tests.ts | 10 +- integration_test/integration_test.iml | 9 + integration_test/package-lock.json | 4179 +++++++---------- integration_test/package.json | 11 +- integration_test/run.ts | 79 +- integration_test/setup-local.ts | 6 + integration_test/setup.ts | 131 +- integration_test/tests/firebaseSetup.ts | 16 +- integration_test/tests/utils.ts | 24 + integration_test/tests/v1/auth.test.ts | 88 +- integration_test/tests/v1/database.test.ts | 30 +- integration_test/tests/v1/firestore.test.ts | 84 +- integration_test/tests/v1/pubsub.test.ts | 39 +- .../tests/v1/remoteConfig.test.ts | 20 +- integration_test/tests/v1/storage.test.ts | 64 +- integration_test/tests/v1/tasks.test.ts | 20 +- integration_test/tests/v1/testLab.test.ts | 21 +- integration_test/tests/v2/database.test.ts | 34 +- integration_test/tests/v2/eventarc.test.ts | 22 +- integration_test/tests/v2/firestore.test.ts | 82 +- integration_test/tests/v2/identity.test.ts | 44 +- integration_test/tests/v2/pubsub.test.ts | 21 +- .../tests/v2/remoteConfig.test.ts | 21 +- integration_test/tests/v2/scheduler.test.ts | 22 +- integration_test/tests/v2/storage.test.ts | 58 +- integration_test/tests/v2/tasks.test.ts | 21 +- integration_test/tests/v2/testLab.test.ts | 21 +- integration_test/tsconfig.build.json | 14 + integration_test/tsconfig.json | 14 +- integration_test/tsconfig.test.json | 8 - integration_test/utils.ts | 17 + 35 files changed, 2406 insertions(+), 2926 deletions(-) create mode 100644 cloudbuild.yaml create mode 100644 integration_test/integration_test.iml create mode 100644 integration_test/setup-local.ts create mode 100644 integration_test/tsconfig.build.json delete mode 100644 integration_test/tsconfig.test.json create mode 100644 integration_test/utils.ts diff --git a/cloudbuild.yaml b/cloudbuild.yaml new file mode 100644 index 000000000..b86f7b8a7 --- /dev/null +++ b/cloudbuild.yaml @@ -0,0 +1,16 @@ +steps: + - name: "node:18" + entrypoint: "npm" + dir: "integration_test" + args: ["install"] + - name: "node:18" + entrypoint: "npx" + dir: "integration_test" + args: ["firebase", "use", "cf3-integration-tests-d7be6"] + - name: "node:18" + entrypoint: "npm" + dir: "integration_test" + args: ["start"] + +options: + defaultLogsBucketBehavior: REGIONAL_USER_OWNED_BUCKET diff --git a/integration_test/.gitignore b/integration_test/.gitignore index e6918b9b4..40d9537c9 100644 --- a/integration_test/.gitignore +++ b/integration_test/.gitignore @@ -70,3 +70,6 @@ node_modules/ serviceAccount.json functions.yaml functions/src/package.json +functions/package/ + +.nvmrc diff --git a/integration_test/functions/src/region.ts b/integration_test/functions/src/region.ts index 4ce175234..a20596872 100644 --- a/integration_test/functions/src/region.ts +++ b/integration_test/functions/src/region.ts @@ -1,2 +1 @@ -// TODO: Add back support for selecting region for integration test once params is ready. -export const REGION = "us-central1"; +export const REGION = process.env.REGION; diff --git a/integration_test/functions/src/v1/storage-tests.ts b/integration_test/functions/src/v1/storage-tests.ts index ad91d4974..21a75998d 100644 --- a/integration_test/functions/src/v1/storage-tests.ts +++ b/integration_test/functions/src/v1/storage-tests.ts @@ -3,47 +3,47 @@ import * as functions from "firebase-functions"; import { REGION } from "../region"; import { sanitizeData } from "../utils"; -export const storageOnDeleteTests: any = functions - .runWith({ - timeoutSeconds: 540, - }) - .region(REGION) - .storage.bucket() - .object() - .onDelete(async (object, context) => { - const testId = object.name?.split(".")[0]; - if (!testId) { - functions.logger.error("TestId not found for storage object delete"); - return; - } - - await admin - .firestore() - .collection("storageOnDeleteTests") - .doc(testId) - .set(sanitizeData(context)); - }); +// export const storageOnDeleteTests: any = functions +// .runWith({ +// timeoutSeconds: 540, +// }) +// .region(REGION) +// .storage.bucket() +// .object() +// .onDelete(async (object, context) => { +// const testId = object.name?.split(".")[0]; +// if (!testId) { +// functions.logger.error("TestId not found for storage object delete"); +// return; +// } +// +// await admin +// .firestore() +// .collection("storageOnDeleteTests") +// .doc(testId) +// .set(sanitizeData(context)); +// }); -export const storageOnFinalizeTests: any = functions - .runWith({ - timeoutSeconds: 540, - }) - .region(REGION) - .storage.bucket() - .object() - .onFinalize(async (object, context) => { - const testId = object.name?.split(".")[0]; - if (!testId) { - functions.logger.error("TestId not found for storage object finalize"); - return; - } - - await admin - .firestore() - .collection("storageOnFinalizeTests") - .doc(testId) - .set(sanitizeData(context)); - }); +// export const storageOnFinalizeTests: any = functions +// .runWith({ +// timeoutSeconds: 540, +// }) +// .region(REGION) +// .storage.bucket() +// .object() +// .onFinalize(async (object, context) => { +// const testId = object.name?.split(".")[0]; +// if (!testId) { +// functions.logger.error("TestId not found for storage object finalize"); +// return; +// } +// +// await admin +// .firestore() +// .collection("storageOnFinalizeTests") +// .doc(testId) +// .set(sanitizeData(context)); +// }); export const storageOnMetadataUpdateTests: any = functions .runWith({ diff --git a/integration_test/functions/src/v2/firestore-tests.ts b/integration_test/functions/src/v2/firestore-tests.ts index 72741408d..e0a863dc2 100644 --- a/integration_test/functions/src/v2/firestore-tests.ts +++ b/integration_test/functions/src/v2/firestore-tests.ts @@ -6,13 +6,13 @@ import { onDocumentUpdated, onDocumentWritten, } from "firebase-functions/v2/firestore"; -import { REGION } from "../region"; import { sanitizeData } from "../utils"; +import { FIRESTORE_REGION } from "../region"; export const firestoreOnDocumentCreatedTests = onDocumentCreated( { document: "tests/{documentId}", - region: REGION, + region: FIRESTORE_REGION, timeoutSeconds: 540, }, async (event) => { @@ -37,7 +37,7 @@ export const firestoreOnDocumentCreatedTests = onDocumentCreated( export const firestoreOnDocumentDeletedTests = onDocumentDeleted( { document: "tests/{documentId}", - region: REGION, + region: FIRESTORE_REGION, timeoutSeconds: 540, }, async (event) => { @@ -62,7 +62,7 @@ export const firestoreOnDocumentDeletedTests = onDocumentDeleted( export const firestoreOnDocumentUpdatedTests = onDocumentUpdated( { document: "tests/{documentId}", - region: REGION, + region: FIRESTORE_REGION, timeoutSeconds: 540, }, async (event) => { @@ -87,7 +87,7 @@ export const firestoreOnDocumentUpdatedTests = onDocumentUpdated( export const firestoreOnDocumentWrittenTests = onDocumentWritten( { document: "tests/{documentId}", - region: REGION, + region: FIRESTORE_REGION, timeoutSeconds: 540, }, async (event) => { diff --git a/integration_test/integration_test.iml b/integration_test/integration_test.iml new file mode 100644 index 000000000..8021953ed --- /dev/null +++ b/integration_test/integration_test.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/integration_test/package-lock.json b/integration_test/package-lock.json index 53f7d6e0f..c417d2bb2 100644 --- a/integration_test/package-lock.json +++ b/integration_test/package-lock.json @@ -8,17 +8,15 @@ "dependencies": { "@google-cloud/eventarc": "^3.1.0", "@google-cloud/tasks": "^5.1.0", - "firebase": "^10.8.0", - "firebase-admin": "^11.11.0", - "firebase-tools": "^13.3.0", + "firebase": "^10.14.0", + "firebase-admin": "^12.6.0", + "firebase-tools": "^13.20.2", "js-yaml": "^4.1.0", "node-fetch": "2" }, "devDependencies": { - "@types/firebase": "^3.2.1", "@types/jest": "^29.5.11", "@types/js-yaml": "^4.0.9", - "@types/node-fetch": "2", "jest": "^29.7.0", "ts-jest": "^29.1.1" } @@ -685,28 +683,25 @@ "kuler": "^2.0.0" } }, + "node_modules/@electric-sql/pglite": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.2.10.tgz", + "integrity": "sha512-0TJF/1ouBweCtyZC4oHwx+dHGn/lP16KfEO/3q22RDuZUsV2saTuYAwb6eK3gBLzVdXG4dj4xZilvmBYEM/WQg==" + }, "node_modules/@fastify/busboy": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.2.1.tgz", - "integrity": "sha512-7PQA7EH43S0CxcOa9OeAnaeA0oQ+e/DHNPZwSQM9CQHW76jle5+OvLdibRp/Aafs9KXbLhxyjOTkRjWUbQEd3Q==", - "license": "MIT", - "dependencies": { - "text-decoding": "^1.0.0" - }, - "engines": { - "node": ">=14" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.0.0.tgz", + "integrity": "sha512-83rnH2nCvclWaPQQKvkJ2pdOjG4TZyEVuFDnlOF6KP08lDaaceVyw/W63mDuafQT+MKHCvXIPpE5uYWeM0rT4w==" }, "node_modules/@firebase/analytics": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.6.tgz", - "integrity": "sha512-sB59EwcAvLt0fINGfMWmcRKcdUiYhE4AJNdDXSCSDo4D/ZXFRmb6qwX9YesKHXFB59XTLT03mAjqQcDrdym9qA==", + "version": "0.10.8", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.8.tgz", + "integrity": "sha512-CVnHcS4iRJPqtIDc411+UmFldk0ShSK3OB+D0bKD8Ck5Vro6dbK5+APZpkuWpbfdL359DIQUnAaMLE+zs/PVyA==", "dependencies": { - "@firebase/component": "0.6.8", - "@firebase/installations": "0.6.8", + "@firebase/component": "0.6.9", + "@firebase/installations": "0.6.9", "@firebase/logger": "0.4.2", - "@firebase/util": "1.9.7", - "safevalues": "0.6.0", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -714,88 +709,45 @@ } }, "node_modules/@firebase/analytics-compat": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.12.tgz", - "integrity": "sha512-rXWnOAdEHbvBPLNjFLu3U0yDZVIAi+C0DL+RkUEOirfSqAeQaKzBCATeBw6+K7FVpEnknhm4tZrvVUVtJjShMw==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.14.tgz", + "integrity": "sha512-unRVY6SvRqfNFIAA/kwl4vK+lvQAL2HVcgu9zTrUtTyYDmtIt/lOuHJynBMYEgLnKm39YKBDhtqdapP2e++ASw==", "dependencies": { - "@firebase/analytics": "0.10.6", + "@firebase/analytics": "0.10.8", "@firebase/analytics-types": "0.8.2", - "@firebase/component": "0.6.8", - "@firebase/util": "1.9.7", + "@firebase/component": "0.6.9", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/analytics-compat/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/analytics-compat/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/analytics-types": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.2.tgz", "integrity": "sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw==" }, - "node_modules/@firebase/analytics/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/analytics/node_modules/@firebase/logger": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/analytics/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/app": { - "version": "0.10.7", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.7.tgz", - "integrity": "sha512-7OCd53B+wnk/onbMLn/vM10pDjw97zzWUD8m3swtLYKJIrL+gDZ7HZ4xcbBLw7OB8ikzu8k1ORNjRe2itgAy4g==", + "version": "0.10.12", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.12.tgz", + "integrity": "sha512-fgBqe5j7GKv7/eMfyU4N1FdiW6O1EyrrVbMa8rJOT5MYNpCXqdL/5NNcLDStS1l6CN7h65a7jUNXmMnMSWo0sw==", "dependencies": { - "@firebase/component": "0.6.8", + "@firebase/component": "0.6.9", "@firebase/logger": "0.4.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "idb": "7.1.1", "tslib": "^2.1.0" } }, "node_modules/@firebase/app-check": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.6.tgz", - "integrity": "sha512-uSzl0/SDw54hwuORWHDtldb9kK/QEVZOcoPn2mlIjMrJOLDug/6kcqnIN3IHzwmPyf23Epg0AGBktvG2FugW4w==", + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.8.tgz", + "integrity": "sha512-O49RGF1xj7k6BuhxGpHmqOW5hqBIAEbt2q6POW0lIywx7emYtzPDeQI+ryQpC4zbKX646SoVZ711TN1DBLNSOQ==", "dependencies": { - "@firebase/component": "0.6.8", + "@firebase/component": "0.6.9", "@firebase/logger": "0.4.2", - "@firebase/util": "1.9.7", - "safevalues": "0.6.0", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -803,46 +755,21 @@ } }, "node_modules/@firebase/app-check-compat": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.13.tgz", - "integrity": "sha512-1sbS5Apq7dLys1KYdNQsmZLFIjJoFP9Mv4bzIcdXuTkWQjr3X2qAvwiTslC6prVAUMiTV0eM9eicdQIXVsiSRw==", + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.15.tgz", + "integrity": "sha512-zFIvIFFNqDXpOT2huorz9cwf56VT3oJYRFjSFYdSbGYEJYEaXjLJbfC79lx/zjx4Fh+yuN8pry3TtvwaevrGbg==", "dependencies": { - "@firebase/app-check": "0.8.6", + "@firebase/app-check": "0.8.8", "@firebase/app-check-types": "0.5.2", - "@firebase/component": "0.6.8", + "@firebase/component": "0.6.9", "@firebase/logger": "0.4.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/app-check-compat/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/app-check-compat/node_modules/@firebase/logger": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/app-check-compat/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/app-check-interop-types": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.2.tgz", @@ -853,109 +780,33 @@ "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.2.tgz", "integrity": "sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA==" }, - "node_modules/@firebase/app-check/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/app-check/node_modules/@firebase/logger": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/app-check/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/app-compat": { - "version": "0.2.37", - "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.37.tgz", - "integrity": "sha512-yiQLYT9LYQHuJGu/msuBLFtdWWTJ3Pz04E9gSeWykSB+8s0XXJJqfqQlghH7CcQ3KnJZR+Wuc3zSMcY3a+dn6Q==", + "version": "0.2.42", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.42.tgz", + "integrity": "sha512-vPI0Aksk8ZuHywigyTxrx/oWbuD41kHxajfxRly7urHOFRiXKxf/q2ftgmcMVPfIeg0K02LzYNBmoh2PWzERpg==", "dependencies": { - "@firebase/app": "0.10.7", - "@firebase/component": "0.6.8", + "@firebase/app": "0.10.12", + "@firebase/component": "0.6.9", "@firebase/logger": "0.4.2", - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/app-compat/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/app-compat/node_modules/@firebase/logger": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/app-compat/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { + "@firebase/util": "1.10.0", "tslib": "^2.1.0" } }, "node_modules/@firebase/app-types": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz", - "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==", - "license": "Apache-2.0" - }, - "node_modules/@firebase/app/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/app/node_modules/@firebase/logger": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/app/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz", + "integrity": "sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==" }, "node_modules/@firebase/auth": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.7.5.tgz", - "integrity": "sha512-DMFR1OA/f1/voeuFbSORg9AP36pMgOoSb/DRgiDalLmIJsDTlQNMCu+givjMP4s/XL85+tBk2MerYnK/AscJjw==", + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.7.9.tgz", + "integrity": "sha512-yLD5095kVgDw965jepMyUrIgDklD6qH/BZNHeKOgvu7pchOKNjVM+zQoOVYJIKWMWOWBq8IRNVU6NXzBbozaJg==", "dependencies": { - "@firebase/component": "0.6.8", + "@firebase/component": "0.6.9", "@firebase/logger": "0.4.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "tslib": "^2.1.0", - "undici": "5.28.4" + "undici": "6.19.7" }, "peerDependencies": { "@firebase/app": "0.x", @@ -968,43 +819,25 @@ } }, "node_modules/@firebase/auth-compat": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.10.tgz", - "integrity": "sha512-epDhgNIXmhl9DPuTW9Ec5NDJJKMFIdXBXiQI9O0xNHveow/ETtBCY86srzF7iCacqsd30CcpLwwXlhk8Y19Olg==", + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.14.tgz", + "integrity": "sha512-2eczCSqBl1KUPJacZlFpQayvpilg3dxXLy9cSMTKtQMTQSmondUtPI47P3ikH3bQAXhzKLOE+qVxJ3/IRtu9pw==", "dependencies": { - "@firebase/auth": "1.7.5", + "@firebase/auth": "1.7.9", "@firebase/auth-types": "0.12.2", - "@firebase/component": "0.6.8", - "@firebase/util": "1.9.7", + "@firebase/component": "0.6.9", + "@firebase/util": "1.10.0", "tslib": "^2.1.0", - "undici": "5.28.4" + "undici": "6.19.7" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/auth-compat/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/auth-compat/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/auth-interop-types": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz", - "integrity": "sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg==", - "license": "Apache-2.0" + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz", + "integrity": "sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==" }, "node_modules/@firebase/auth-types": { "version": "0.12.2", @@ -1015,92 +848,79 @@ "@firebase/util": "1.x" } }, - "node_modules/@firebase/auth/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/auth/node_modules/@firebase/logger": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/auth/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "node_modules/@firebase/component": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.9.tgz", + "integrity": "sha512-gm8EUEJE/fEac86AvHn8Z/QW8BvR56TBw3hMW0O838J/1mThYQXAIQBgUv75EqlCZfdawpWLrKt1uXvp9ciK3Q==", "dependencies": { + "@firebase/util": "1.10.0", "tslib": "^2.1.0" } }, - "node_modules/@firebase/component": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.4.tgz", - "integrity": "sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA==", - "license": "Apache-2.0", + "node_modules/@firebase/data-connect": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.0.tgz", + "integrity": "sha512-vSe5s8dY13ilhLnfY0eYRmQsdTbH7PUFZtBbqU6JVX/j8Qp9A6G5gG6//ulbX9/1JFOF1IWNOne9c8S/DOCJaQ==", "dependencies": { - "@firebase/util": "1.9.3", + "@firebase/auth-interop-types": "0.2.3", + "@firebase/component": "0.6.9", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" } }, "node_modules/@firebase/database": { - "version": "0.14.4", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.14.4.tgz", - "integrity": "sha512-+Ea/IKGwh42jwdjCyzTmeZeLM3oy1h0mFPsTy6OqCWzcu/KFqRAr5Tt1HRCOBlNOdbh84JPZC47WLU18n2VbxQ==", - "license": "Apache-2.0", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.8.tgz", + "integrity": "sha512-dzXALZeBI1U5TXt6619cv0+tgEhJiwlUtQ55WNZY7vGAjv7Q1QioV969iYwt1AQQ0ovHnEW0YW9TiBfefLvErg==", "dependencies": { - "@firebase/auth-interop-types": "0.2.1", - "@firebase/component": "0.6.4", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.3", + "@firebase/app-check-interop-types": "0.3.2", + "@firebase/auth-interop-types": "0.2.3", + "@firebase/component": "0.6.9", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.10.0", "faye-websocket": "0.11.4", "tslib": "^2.1.0" } }, "node_modules/@firebase/database-compat": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.3.4.tgz", - "integrity": "sha512-kuAW+l+sLMUKBThnvxvUZ+Q1ZrF/vFJ58iUY9kAcbX48U03nVzIF6Tmkf0p3WVQwMqiXguSgtOPIB6ZCeF+5Gg==", - "license": "Apache-2.0", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.8.tgz", + "integrity": "sha512-OpeWZoPE3sGIRPBKYnW9wLad25RaWbGyk7fFQe4xnJQKRzlynWeFBSRRAoLE2Old01WXwskUiucNqUUVlFsceg==", "dependencies": { - "@firebase/component": "0.6.4", - "@firebase/database": "0.14.4", - "@firebase/database-types": "0.10.4", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.3", + "@firebase/component": "0.6.9", + "@firebase/database": "1.0.8", + "@firebase/database-types": "1.0.5", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" } }, "node_modules/@firebase/database-types": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.10.4.tgz", - "integrity": "sha512-dPySn0vJ/89ZeBac70T+2tWWPiJXWbmRygYv0smT5TfE3hDrQ09eKMF3Y+vMlTdrMWq7mUdYW5REWPSGH4kAZQ==", - "license": "Apache-2.0", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.5.tgz", + "integrity": "sha512-fTlqCNwFYyq/C6W7AJ5OCuq5CeZuBEsEwptnVxlNPkWCo5cTTyukzAHRSO/jaQcItz33FfYrrFk1SJofcu2AaQ==", "dependencies": { - "@firebase/app-types": "0.9.0", - "@firebase/util": "1.9.3" + "@firebase/app-types": "0.9.2", + "@firebase/util": "1.10.0" } }, "node_modules/@firebase/firestore": { - "version": "4.6.4", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.6.4.tgz", - "integrity": "sha512-vk2MoH5HxYEhiNg1l+yBXq1Fkhue/11bFg4HdlTv6BJHcTnnAj2a+/afPpatcW4MOdYA3Tv+d5nGzWbbOC1SHw==", + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.3.tgz", + "integrity": "sha512-NwVU+JPZ/3bhvNSJMCSzfcBZZg8SUGyzZ2T0EW3/bkUeefCyzMISSt/TTIfEHc8cdyXGlMqfGe3/62u9s74UEg==", "dependencies": { - "@firebase/component": "0.6.8", + "@firebase/component": "0.6.9", "@firebase/logger": "0.4.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "@firebase/webchannel-wrapper": "1.0.1", "@grpc/grpc-js": "~1.9.0", "@grpc/proto-loader": "^0.7.8", "tslib": "^2.1.0", - "undici": "5.28.4" + "undici": "6.19.7" }, "engines": { "node": ">=10.10.0" @@ -1110,37 +930,20 @@ } }, "node_modules/@firebase/firestore-compat": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.33.tgz", - "integrity": "sha512-i42a2l31N95CwYEB7zmfK0FS1mrO6pwOLwxavCrwu1BCFrVVVQhUheTPIda/iGguK/2Nog0RaIR1bo7QkZEz3g==", + "version": "0.3.38", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.38.tgz", + "integrity": "sha512-GoS0bIMMkjpLni6StSwRJarpu2+S5m346Na7gr9YZ/BZ/W3/8iHGNr9PxC+f0rNZXqS4fGRn88pICjrZEgbkqQ==", "dependencies": { - "@firebase/component": "0.6.8", - "@firebase/firestore": "4.6.4", + "@firebase/component": "0.6.9", + "@firebase/firestore": "4.7.3", "@firebase/firestore-types": "3.0.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/firestore-compat/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/firestore-compat/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/firestore-types": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.2.tgz", @@ -1150,31 +953,6 @@ "@firebase/util": "1.x" } }, - "node_modules/@firebase/firestore/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/firestore/node_modules/@firebase/logger": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/firestore/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/firestore/node_modules/@grpc/grpc-js": { "version": "1.9.15", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", @@ -1188,88 +966,49 @@ } }, "node_modules/@firebase/functions": { - "version": "0.11.6", - "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.6.tgz", - "integrity": "sha512-GPfIBPtpwQvsC7SQbgaUjLTdja0CsNwMoKSgrzA1FGGRk4NX6qO7VQU6XCwBiAFWbpbQex6QWkSMsCzLx1uibQ==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.8.tgz", + "integrity": "sha512-Lo2rTPDn96naFIlSZKVd1yvRRqqqwiJk7cf9TZhUerwnPKgBzXy+aHE22ry+6EjCaQusUoNai6mU6p+G8QZT1g==", "dependencies": { "@firebase/app-check-interop-types": "0.3.2", "@firebase/auth-interop-types": "0.2.3", - "@firebase/component": "0.6.8", + "@firebase/component": "0.6.9", "@firebase/messaging-interop-types": "0.2.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "tslib": "^2.1.0", - "undici": "5.28.4" + "undici": "6.19.7" }, "peerDependencies": { "@firebase/app": "0.x" } }, "node_modules/@firebase/functions-compat": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.12.tgz", - "integrity": "sha512-r3XUb5VlITWpML46JymfJPkK6I9j4SNlO7qWIXUc0TUmkv0oAfVoiIt1F83/NuMZXaGr4YWA/794nVSy4GV8tw==", + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.14.tgz", + "integrity": "sha512-dZ0PKOKQFnOlMfcim39XzaXonSuPPAVuzpqA4ONTIdyaJK/OnBaIEVs/+BH4faa1a2tLeR+Jy15PKqDRQoNIJw==", "dependencies": { - "@firebase/component": "0.6.8", - "@firebase/functions": "0.11.6", + "@firebase/component": "0.6.9", + "@firebase/functions": "0.11.8", "@firebase/functions-types": "0.6.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/functions-compat/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/functions-compat/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/functions-types": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.2.tgz", "integrity": "sha512-0KiJ9lZ28nS2iJJvimpY4nNccV21rkQyor5Iheu/nq8aKXJqtJdeSlZDspjPSBBiHRzo7/GMUttegnsEITqR+w==" }, - "node_modules/@firebase/functions/node_modules/@firebase/auth-interop-types": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz", - "integrity": "sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==" - }, - "node_modules/@firebase/functions/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/functions/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/installations": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.8.tgz", - "integrity": "sha512-57V374qdb2+wT5v7+ntpLXBjZkO6WRgmAUbVkRfFTM/4t980p0FesbqTAcOIiM8U866UeuuuF8lYH70D3jM/jQ==", + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.9.tgz", + "integrity": "sha512-hlT7AwCiKghOX3XizLxXOsTFiFCQnp/oj86zp1UxwDGmyzsyoxtX+UIZyVyH/oBF5+XtblFG9KZzZQ/h+dpy+Q==", "dependencies": { - "@firebase/component": "0.6.8", - "@firebase/util": "1.9.7", + "@firebase/component": "0.6.9", + "@firebase/util": "1.10.0", "idb": "7.1.1", "tslib": "^2.1.0" }, @@ -1278,37 +1017,20 @@ } }, "node_modules/@firebase/installations-compat": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.8.tgz", - "integrity": "sha512-pI2q8JFHB7yIq/szmhzGSWXtOvtzl6tCUmyykv5C8vvfOVJUH6mP4M4iwjbK8S1JotKd/K70+JWyYlxgQ0Kpyw==", + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.9.tgz", + "integrity": "sha512-2lfdc6kPXR7WaL4FCQSQUhXcPbI7ol3wF+vkgtU25r77OxPf8F/VmswQ7sgIkBBWtymn5ZF20TIKtnOj9rjb6w==", "dependencies": { - "@firebase/component": "0.6.8", - "@firebase/installations": "0.6.8", + "@firebase/component": "0.6.9", + "@firebase/installations": "0.6.9", "@firebase/installations-types": "0.5.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/installations-compat/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/installations-compat/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/installations-types": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.2.tgz", @@ -1317,41 +1039,23 @@ "@firebase/app-types": "0.x" } }, - "node_modules/@firebase/installations/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/installations/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/logger": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz", - "integrity": "sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==", - "license": "Apache-2.0", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/@firebase/messaging": { - "version": "0.12.10", - "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.10.tgz", - "integrity": "sha512-fGbxJPKpl2DIKNJGhbk4mYPcM+qE2gl91r6xPoiol/mN88F5Ym6UeRdMVZah+pijh9WxM55alTYwXuW40r1Y2Q==", + "version": "0.12.11", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.11.tgz", + "integrity": "sha512-zn5zGhF46BmiZ7W9yAUoHlqzJGakmWn1FNp//roXHN62dgdEFIKfXY7IODA2iQiXpmUO3sBdI/Tf+Hsft1mVkw==", "dependencies": { - "@firebase/component": "0.6.8", - "@firebase/installations": "0.6.8", + "@firebase/component": "0.6.9", + "@firebase/installations": "0.6.9", "@firebase/messaging-interop-types": "0.2.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "idb": "7.1.1", "tslib": "^2.1.0" }, @@ -1360,67 +1064,33 @@ } }, "node_modules/@firebase/messaging-compat": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.10.tgz", - "integrity": "sha512-FXQm7rcowkDm8kFLduHV35IRYCRo+Ng0PIp/t1+EBuEbyplaKkGjZ932pE+owf/XR+G/60ku2QRBptRGLXZydg==", + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.11.tgz", + "integrity": "sha512-2NCkfE1L9jSn5OC+2n5rGAz5BEAQreK2lQGdPYQEJlAbKB2efoF+2FdiQ+LD8SlioSXz66REfeaEdesoLPFQcw==", "dependencies": { - "@firebase/component": "0.6.8", - "@firebase/messaging": "0.12.10", - "@firebase/util": "1.9.7", + "@firebase/component": "0.6.9", + "@firebase/messaging": "0.12.11", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/messaging-compat/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/messaging-compat/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/messaging-interop-types": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.2.tgz", "integrity": "sha512-l68HXbuD2PPzDUOFb3aG+nZj5KA3INcPwlocwLZOzPp9rFM9yeuI9YLl6DQfguTX5eAGxO0doTR+rDLDvQb5tA==" }, - "node_modules/@firebase/messaging/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/messaging/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/performance": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.8.tgz", - "integrity": "sha512-F+alziiIZ6Yn8FG47mxwljq+4XkgkT2uJIFRlkyViUQRLzrogaUJW6u/+6ZrePXnouKlKIwzqos3PVJraPEcCA==", + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.9.tgz", + "integrity": "sha512-PnVaak5sqfz5ivhua+HserxTJHtCar/7zM0flCX6NkzBNzJzyzlH4Hs94h2Il0LQB99roBqoE5QT1JqWqcLJHQ==", "dependencies": { - "@firebase/component": "0.6.8", - "@firebase/installations": "0.6.8", + "@firebase/component": "0.6.9", + "@firebase/installations": "0.6.9", "@firebase/logger": "0.4.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -1428,85 +1098,35 @@ } }, "node_modules/@firebase/performance-compat": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.8.tgz", - "integrity": "sha512-o7TFClRVJd3VIBoY7KZQqtCeW0PC6v9uBzM6Lfw3Nc9D7hM6OonqecYvh7NwJ6R14k+xM27frLS4BcCvFHKw2A==", + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.9.tgz", + "integrity": "sha512-dNl95IUnpsu3fAfYBZDCVhXNkASE0uo4HYaEPd2/PKscfTvsgqFAOxfAXzBEDOnynDWiaGUnb5M1O00JQ+3FXA==", "dependencies": { - "@firebase/component": "0.6.8", + "@firebase/component": "0.6.9", "@firebase/logger": "0.4.2", - "@firebase/performance": "0.6.8", + "@firebase/performance": "0.6.9", "@firebase/performance-types": "0.2.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/performance-compat/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/performance-compat/node_modules/@firebase/logger": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/performance-compat/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/performance-types": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.2.tgz", "integrity": "sha512-gVq0/lAClVH5STrIdKnHnCo2UcPLjJlDUoEB/tB4KM+hAeHUxWKnpT0nemUPvxZ5nbdY/pybeyMe8Cs29gEcHA==" }, - "node_modules/@firebase/performance/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/performance/node_modules/@firebase/logger": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/performance/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/remote-config": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.8.tgz", - "integrity": "sha512-AMLqe6wfIRnjc6FkCWOSUjhc1fSTEf8o+cv1NolFvbiJ/tU+TqN4pI7pT+MIKQzNiq5fxLehkOx+xtAQBxPJKQ==", + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.9.tgz", + "integrity": "sha512-EO1NLCWSPMHdDSRGwZ73kxEEcTopAxX1naqLJFNApp4hO8WfKfmEpmjxmP5TrrnypjIf2tUkYaKsfbEA7+AMmA==", "dependencies": { - "@firebase/component": "0.6.8", - "@firebase/installations": "0.6.8", + "@firebase/component": "0.6.9", + "@firebase/installations": "0.6.9", "@firebase/logger": "0.4.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -1514,122 +1134,55 @@ } }, "node_modules/@firebase/remote-config-compat": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.8.tgz", - "integrity": "sha512-UxSFOp6dzFj2AHB8Bq/BYtbq5iFyizKx4Rd6WxAdaKYM8cnPMeK+l2v+Oogtjae+AeyHRI+MfL2acsfVe5cd2A==", + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.9.tgz", + "integrity": "sha512-AxzGpWfWFYejH2twxfdOJt5Cfh/ATHONegTd/a0p5flEzsD5JsxXgfkFToop+mypEL3gNwawxrxlZddmDoNxyA==", "dependencies": { - "@firebase/component": "0.6.8", + "@firebase/component": "0.6.9", "@firebase/logger": "0.4.2", - "@firebase/remote-config": "0.4.8", + "@firebase/remote-config": "0.4.9", "@firebase/remote-config-types": "0.3.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/remote-config-compat/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/remote-config-compat/node_modules/@firebase/logger": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/remote-config-compat/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/remote-config-types": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.2.tgz", "integrity": "sha512-0BC4+Ud7y2aPTyhXJTMTFfrGGLqdYXrUB9sJVAB8NiqJswDTc4/2qrE/yfUbnQJhbSi6ZaTTBKyG3n1nplssaA==" }, - "node_modules/@firebase/remote-config/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/remote-config/node_modules/@firebase/logger": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/remote-config/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/storage": { - "version": "0.12.6", - "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.12.6.tgz", - "integrity": "sha512-Zgb9WuehJxzhj7pGXUvkAEaH+3HvLjD9xSZ9nepuXf5f8378xME7oGJtREr/RnepdDA5YW0XIxe0QQBNHpe1nw==", + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.2.tgz", + "integrity": "sha512-fxuJnHshbhVwuJ4FuISLu+/76Aby2sh+44ztjF2ppoe0TELIDxPW6/r1KGlWYt//AD0IodDYYA8ZTN89q8YqUw==", "dependencies": { - "@firebase/component": "0.6.8", - "@firebase/util": "1.9.7", + "@firebase/component": "0.6.9", + "@firebase/util": "1.10.0", "tslib": "^2.1.0", - "undici": "5.28.4" + "undici": "6.19.7" }, "peerDependencies": { "@firebase/app": "0.x" } }, "node_modules/@firebase/storage-compat": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.9.tgz", - "integrity": "sha512-WWgAp5bTW961oIsCc9+98m4MIVKpEqztAlIngfHfwO/x3DYoBPRl/awMRG3CAXyVxG+7B7oHC5IsnqM+vTwx2A==", + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.12.tgz", + "integrity": "sha512-hA4VWKyGU5bWOll+uwzzhEMMYGu9PlKQc1w4DWxB3aIErWYzonrZjF0icqNQZbwKNIdh8SHjZlFeB2w6OSsjfg==", "dependencies": { - "@firebase/component": "0.6.8", - "@firebase/storage": "0.12.6", + "@firebase/component": "0.6.9", + "@firebase/storage": "0.13.2", "@firebase/storage-types": "0.8.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/storage-compat/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/storage-compat/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/storage-types": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.2.tgz", @@ -1639,41 +1192,23 @@ "@firebase/util": "1.x" } }, - "node_modules/@firebase/storage/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/storage/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/util": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz", - "integrity": "sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA==", - "license": "Apache-2.0", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.0.tgz", + "integrity": "sha512-xKtx4A668icQqoANRxyDLBLz51TAbDP9KRfpbKGxiCAW346d0BeJe5vN6/hKxxmWwnZ0mautyv39JxviwwQMOQ==", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/@firebase/vertexai-preview": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@firebase/vertexai-preview/-/vertexai-preview-0.0.3.tgz", - "integrity": "sha512-KVtUWLp+ScgiwkDKAvNkVucAyhLVQp6C6lhnVEuIg4mWhWcS3oerjAeVhZT4uNofKwWxRsOaB2Yec7DMTXlQPQ==", + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@firebase/vertexai-preview/-/vertexai-preview-0.0.4.tgz", + "integrity": "sha512-EBSqyu9eg8frQlVU9/HjKtHN7odqbh9MtAcVz3WwHj4gLCLOoN9F/o+oxlq3CxvFrd3CNTZwu6d2mZtVlEInng==", "dependencies": { "@firebase/app-check-interop-types": "0.3.2", - "@firebase/component": "0.6.8", + "@firebase/component": "0.6.9", "@firebase/logger": "0.4.2", - "@firebase/util": "1.9.7", + "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "engines": { @@ -1684,31 +1219,6 @@ "@firebase/app-types": "0.x" } }, - "node_modules/@firebase/vertexai-preview/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/vertexai-preview/node_modules/@firebase/logger": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/vertexai-preview/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@firebase/webchannel-wrapper": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.1.tgz", @@ -1719,617 +1229,177 @@ "license": "MIT", "optional": true }, - "node_modules/@google-cloud/eventarc": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@google-cloud/eventarc/-/eventarc-3.3.0.tgz", - "integrity": "sha512-nxTEKyPcgHBrbvjDsqxRufa2gjHilHwpChtXZg585xlcg1SP8kiCcCQeeEFKrzB5z8fYkGarYWg4QoBq1K7L4A==", - "dependencies": { - "google-gax": "^4.0.3" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/@grpc/grpc-js": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.11.1.tgz", - "integrity": "sha512-gyt/WayZrVPH2w/UTLansS7F9Nwld472JxxaETamrM8HNlsa+jSLNyKAZmhxI2Me4c3mQHFiS1wWHDY1g1Kthw==", - "dependencies": { - "@grpc/proto-loader": "^0.7.13", - "@js-sdsl/ordered-map": "^4.4.2" - }, - "engines": { - "node": ">=12.10.0" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/gaxios": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.0.tgz", - "integrity": "sha512-DSrkyMTfAnAm4ks9Go20QGOcXEyW/NmZhvTYBU2rb4afBB393WIMQPWPEDMl/k8xqiNN9HYq2zao3oWXsdl2Tg==", - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^7.0.1", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.9", - "uuid": "^10.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/gaxios/node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/gcp-metadata": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", - "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", - "dependencies": { - "gaxios": "^6.0.0", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/google-auth-library": { - "version": "9.11.0", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.11.0.tgz", - "integrity": "sha512-epX3ww/mNnhl6tL45EQ/oixsY8JLEgUFoT4A5E/5iAR4esld9Kqv6IJGk7EmGuOgDvaarwF95hU2+v7Irql9lw==", - "dependencies": { - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "gaxios": "^6.1.1", - "gcp-metadata": "^6.1.0", - "gtoken": "^7.0.0", - "jws": "^4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/google-gax": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.3.8.tgz", - "integrity": "sha512-SKAQKtvdjtNW3PMOhmKEqpQP+2C5ZqNKfwWxy70efpSwxvRYuAcgMJs6aRHTBPJjz3SO6ZbiXwM6WIuGYFZ7LQ==", - "dependencies": { - "@grpc/grpc-js": "^1.10.9", - "@grpc/proto-loader": "^0.7.13", - "@types/long": "^4.0.0", - "abort-controller": "^3.0.0", - "duplexify": "^4.0.0", - "google-auth-library": "^9.3.0", - "node-fetch": "^2.6.1", - "object-hash": "^3.0.0", - "proto3-json-serializer": "^2.0.2", - "protobufjs": "^7.3.2", - "retry-request": "^7.0.0", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/gtoken": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", - "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", - "dependencies": { - "gaxios": "^6.0.0", - "jws": "^4.0.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/proto3-json-serializer": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz", - "integrity": "sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ==", - "dependencies": { - "protobufjs": "^7.2.5" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/protobufjs": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.3.2.tgz", - "integrity": "sha512-RXyHaACeqXeqAKGLDl68rQKbmObRsTIn4TYVUUug1KfS47YWCo5MacGITEryugIgZqORCvJWEk4l449POg5Txg==", - "hasInstallScript": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/retry-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", - "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", - "dependencies": { - "@types/request": "^2.48.8", - "extend": "^3.0.2", - "teeny-request": "^9.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/teeny-request": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", - "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", - "dependencies": { - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.9", - "stream-events": "^1.0.5", - "uuid": "^9.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/teeny-request/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/teeny-request/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@google-cloud/eventarc/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@google-cloud/firestore": { - "version": "6.8.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "functional-red-black-tree": "^1.0.1", - "google-gax": "^3.5.7", - "protobufjs": "^7.2.5" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@google-cloud/firestore/node_modules/protobufjs": { - "version": "7.2.5", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "optional": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@google-cloud/paginator": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.7.tgz", - "integrity": "sha512-jJNutk0arIQhmpUUQJPJErsojqo834KcyB6X7a1mxuic8i1tKXxde8E69IZxNZawRIlZdIK2QY4WALvlK5MzYQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "arrify": "^2.0.0", - "extend": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@google-cloud/precise-date": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@google-cloud/precise-date/-/precise-date-3.0.1.tgz", - "integrity": "sha512-crK2rgNFfvLoSgcKJY7ZBOLW91IimVNmPfi1CL+kMTf78pTJYd29XqEVedAeBu4DwCJc0EDIp1MpctLgoPq+Uw==", - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@google-cloud/projectify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz", - "integrity": "sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA==", - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@google-cloud/promisify": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.4.tgz", - "integrity": "sha512-j8yRSSqswWi1QqUGKVEKOG03Q7qOoZP6/h2zN2YO+F5h2+DHU0bSrHCK9Y7lo2DI9fBd8qGAw795sf+3Jva4yA==", - "license": "Apache-2.0", - "engines": { - "node": ">=10" - } - }, - "node_modules/@google-cloud/pubsub": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/@google-cloud/pubsub/-/pubsub-3.7.5.tgz", - "integrity": "sha512-4Qrry4vIToth5mqduVslltWVsyb7DR8OhnkBA3F7XiE0jgQsiuUfwp/RB2F559aXnRbwcfmjvP4jSuEaGcjrCQ==", - "license": "Apache-2.0", - "dependencies": { - "@google-cloud/paginator": "^4.0.0", - "@google-cloud/precise-date": "^3.0.0", - "@google-cloud/projectify": "^3.0.0", - "@google-cloud/promisify": "^2.0.0", - "@opentelemetry/api": "^1.6.0", - "@opentelemetry/semantic-conventions": "~1.3.0", - "@types/duplexify": "^3.6.0", - "@types/long": "^4.0.0", - "arrify": "^2.0.0", - "extend": "^3.0.2", - "google-auth-library": "^8.0.2", - "google-gax": "^3.6.1", - "heap-js": "^2.2.0", - "is-stream-ended": "^0.1.4", - "lodash.snakecase": "^4.1.1", - "p-defer": "^3.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@google-cloud/pubsub/node_modules/@google-cloud/paginator": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-4.0.1.tgz", - "integrity": "sha512-6G1ui6bWhNyHjmbYwavdN7mpVPRBtyDg/bfqBTAlwr413On2TnFNfDxc9UhTJctkgoCDgQXEKiRPLPR9USlkbQ==", - "license": "Apache-2.0", - "dependencies": { - "arrify": "^2.0.0", - "extend": "^3.0.2" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@google-cloud/storage": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.12.0.tgz", - "integrity": "sha512-78nNAY7iiZ4O/BouWMWTD/oSF2YtYgYB3GZirn0To6eBOugjXVoK+GXgUXOl+HlqbAOyHxAVXOlsj3snfbQ1dw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@google-cloud/paginator": "^3.0.7", - "@google-cloud/projectify": "^3.0.0", - "@google-cloud/promisify": "^3.0.0", - "abort-controller": "^3.0.0", - "async-retry": "^1.3.3", - "compressible": "^2.0.12", - "duplexify": "^4.0.0", - "ent": "^2.2.0", - "extend": "^3.0.2", - "fast-xml-parser": "^4.2.2", - "gaxios": "^5.0.0", - "google-auth-library": "^8.0.1", - "mime": "^3.0.0", - "mime-types": "^2.0.8", - "p-limit": "^3.0.1", - "retry-request": "^5.0.0", - "teeny-request": "^8.0.0", - "uuid": "^8.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@google-cloud/storage/node_modules/@google-cloud/promisify": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-3.0.1.tgz", - "integrity": "sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA==", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/@google-cloud/storage/node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "license": "MIT", - "optional": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@google-cloud/tasks": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@google-cloud/tasks/-/tasks-5.1.0.tgz", - "integrity": "sha512-6TU2BqK5G62iLSiNzIAK7EBXJzDtjY9kiOjvXm1bcZAnRbmlow+2QtunSWzRlcLYJW9oz4v4mTGkuvNWa/QC0A==", - "dependencies": { - "google-gax": "^4.0.4" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@google-cloud/tasks/node_modules/@grpc/grpc-js": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.1.tgz", - "integrity": "sha512-55ONqFytZExfOIjF1RjXPcVmT/jJqFzbbDqxK9jmRV4nxiYWtL9hENSW1Jfx0SdZfrvoqd44YJ/GJTqfRrawSQ==", - "dependencies": { - "@grpc/proto-loader": "^0.7.8", - "@types/node": ">=12.12.47" - }, - "engines": { - "node": "^8.13.0 || >=10.10.0" - } - }, - "node_modules/@google-cloud/tasks/node_modules/gaxios": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.2.0.tgz", - "integrity": "sha512-H6+bHeoEAU5D6XNc6mPKeN5dLZqEDs9Gpk6I+SZBEzK5So58JVrHPmevNi35fRl1J9Y5TaeLW0kYx3pCJ1U2mQ==", - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^7.0.1", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.9" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/tasks/node_modules/gcp-metadata": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", - "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", - "dependencies": { - "gaxios": "^6.0.0", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/tasks/node_modules/google-auth-library": { - "version": "9.6.3", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.6.3.tgz", - "integrity": "sha512-4CacM29MLC2eT9Cey5GDVK4Q8t+MMp8+OEdOaqD9MG6b0dOyLORaaeJMPQ7EESVgm/+z5EKYyFLxgzBJlJgyHQ==", + "node_modules/@google-cloud/cloud-sql-connector": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@google-cloud/cloud-sql-connector/-/cloud-sql-connector-1.4.0.tgz", + "integrity": "sha512-OUXs2f91u3afbFjufCJom9lF+GgS9if4F/eKxrLvdkbwkYAQrQUOY6Jw4YfVXUxF3oNDioTgZ4fpwt1MQXwfKg==", "dependencies": { - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "gaxios": "^6.1.1", - "gcp-metadata": "^6.1.0", - "gtoken": "^7.0.0", - "jws": "^4.0.0" + "@googleapis/sqladmin": "^24.0.0", + "gaxios": "^6.1.1", + "google-auth-library": "^9.2.0", + "p-throttle": "^5.1.0" }, "engines": { "node": ">=14" } }, - "node_modules/@google-cloud/tasks/node_modules/google-gax": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.3.1.tgz", - "integrity": "sha512-qpSfslpwqToIgQ+Tf3MjWIDjYK4UFIZ0uz6nLtttlW9N1NQA4PhGf9tlGo6KDYJ4rgL2w4CjXVd0z5yeNpN/Iw==", + "node_modules/@google-cloud/eventarc": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@google-cloud/eventarc/-/eventarc-3.3.0.tgz", + "integrity": "sha512-nxTEKyPcgHBrbvjDsqxRufa2gjHilHwpChtXZg585xlcg1SP8kiCcCQeeEFKrzB5z8fYkGarYWg4QoBq1K7L4A==", "dependencies": { - "@grpc/grpc-js": "~1.10.0", - "@grpc/proto-loader": "^0.7.0", - "@types/long": "^4.0.0", - "abort-controller": "^3.0.0", - "duplexify": "^4.0.0", - "google-auth-library": "^9.3.0", - "node-fetch": "^2.6.1", - "object-hash": "^3.0.0", - "proto3-json-serializer": "^2.0.0", - "protobufjs": "7.2.6", - "retry-request": "^7.0.0", - "uuid": "^9.0.1" + "google-gax": "^4.0.3" }, "engines": { - "node": ">=14" + "node": ">=14.0.0" } }, - "node_modules/@google-cloud/tasks/node_modules/gtoken": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", - "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", + "node_modules/@google-cloud/firestore": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.10.0.tgz", + "integrity": "sha512-VFNhdHvfnmqcHHs6YhmSNHHxQqaaD64GwiL0c+e1qz85S8SWZPC2XFRf8p9yHRTF40Kow424s1KBU9f0fdQa+Q==", + "optional": true, "dependencies": { - "gaxios": "^6.0.0", - "jws": "^4.0.0" + "@opentelemetry/api": "^1.3.0", + "fast-deep-equal": "^3.1.1", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^4.3.3", + "protobufjs": "^7.2.6" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@google-cloud/tasks/node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "node_modules/@google-cloud/paginator": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz", + "integrity": "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==", "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" + "arrify": "^2.0.0", + "extend": "^3.0.2" }, "engines": { - "node": ">= 14" + "node": ">=14.0.0" } }, - "node_modules/@google-cloud/tasks/node_modules/proto3-json-serializer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.1.tgz", - "integrity": "sha512-8awBvjO+FwkMd6gNoGFZyqkHZXCFd54CIYTb6De7dPaufGJ2XNW+QUNqbMr8MaAocMdb+KpsD4rxEOaTBDCffA==", - "dependencies": { - "protobufjs": "^7.2.5" - }, + "node_modules/@google-cloud/precise-date": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/precise-date/-/precise-date-4.0.0.tgz", + "integrity": "sha512-1TUx3KdaU3cN7nfCdNf+UVqA/PSX29Cjcox3fZZBtINlRrXVTmUkQnCKv2MbBUbCopbK4olAT1IHl76uZyCiVA==", "engines": { "node": ">=14.0.0" } }, - "node_modules/@google-cloud/tasks/node_modules/protobufjs": { - "version": "7.2.6", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", - "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", - "hasInstallScript": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, + "node_modules/@google-cloud/projectify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz", + "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==", "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" } }, - "node_modules/@google-cloud/tasks/node_modules/retry-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", - "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", - "dependencies": { - "@types/request": "^2.48.8", + "node_modules/@google-cloud/promisify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", + "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/pubsub": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/@google-cloud/pubsub/-/pubsub-4.7.2.tgz", + "integrity": "sha512-N9Cziu5d7sju4gtHsbbjOXDMCewNwGaPZ/o+sBbWl9sBR7S+kHkD4BVg6hCi9SvH1sst0AGan8UAQAxbac8cRg==", + "dependencies": { + "@google-cloud/paginator": "^5.0.0", + "@google-cloud/precise-date": "^4.0.0", + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "^4.0.0", + "@opentelemetry/api": "~1.9.0", + "@opentelemetry/semantic-conventions": "~1.26.0", + "arrify": "^2.0.0", "extend": "^3.0.2", - "teeny-request": "^9.0.0" + "google-auth-library": "^9.3.0", + "google-gax": "^4.3.3", + "heap-js": "^2.2.0", + "is-stream-ended": "^0.1.4", + "lodash.snakecase": "^4.1.1", + "p-defer": "^3.0.0" }, "engines": { - "node": ">=14" + "node": ">=14.0.0" } }, - "node_modules/@google-cloud/tasks/node_modules/teeny-request": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", - "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", + "node_modules/@google-cloud/storage": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.13.0.tgz", + "integrity": "sha512-Y0rYdwM5ZPW3jw/T26sMxxfPrVQTKm9vGrZG8PRyGuUmUJ8a2xNuQ9W/NNA1prxqv2i54DSydV8SJqxF2oCVgA==", + "optional": true, "dependencies": { - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.9", - "stream-events": "^1.0.5", - "uuid": "^9.0.0" + "@google-cloud/paginator": "^5.0.0", + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "^4.0.0", + "abort-controller": "^3.0.0", + "async-retry": "^1.3.3", + "duplexify": "^4.1.3", + "fast-xml-parser": "^4.4.1", + "gaxios": "^6.0.2", + "google-auth-library": "^9.6.3", + "html-entities": "^2.5.2", + "mime": "^3.0.0", + "p-limit": "^3.0.1", + "retry-request": "^7.0.0", + "teeny-request": "^9.0.0", + "uuid": "^8.0.0" }, "engines": { "node": ">=14" } }, - "node_modules/@google-cloud/tasks/node_modules/teeny-request/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" + "node_modules/@google-cloud/storage/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "optional": true, + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">= 6.0.0" + "node": ">=10.0.0" } }, - "node_modules/@google-cloud/tasks/node_modules/teeny-request/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/@google-cloud/tasks": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@google-cloud/tasks/-/tasks-5.1.0.tgz", + "integrity": "sha512-6TU2BqK5G62iLSiNzIAK7EBXJzDtjY9kiOjvXm1bcZAnRbmlow+2QtunSWzRlcLYJW9oz4v4mTGkuvNWa/QC0A==", "dependencies": { - "agent-base": "6", - "debug": "4" + "google-gax": "^4.0.4" }, "engines": { - "node": ">= 6" + "node": ">=v14" } }, - "node_modules/@google-cloud/tasks/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/@googleapis/sqladmin": { + "version": "24.0.0", + "resolved": "https://registry.npmjs.org/@googleapis/sqladmin/-/sqladmin-24.0.0.tgz", + "integrity": "sha512-Sj2MerYrr4Z6ksK81Scj0gIdFjC3bC0vcqdM+TSfnOskg6d9iIALWdFDc3xgNHQWO58rUb6HjBzr1XbuNjYlPg==", + "dependencies": { + "googleapis-common": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" } }, "node_modules/@grpc/grpc-js": { - "version": "1.8.21", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.21.tgz", - "integrity": "sha512-KeyQeZpxeEBSqFVTi3q2K7PiPXmgBfECc4updA1ejCLjYmoAlvvM3ZMp5ztTDUCUQmoY3CpDxvchjO1+rFkoHg==", - "license": "Apache-2.0", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.0.tgz", + "integrity": "sha512-eWdP97A6xKtZXVP/ze9y8zYRB2t6ugQAuLXFuZXAsyqmyltaAjl4yPkmIfc0wuTFJMOUF1AdvIFQCL7fMtaX6g==", "dependencies": { - "@grpc/proto-loader": "^0.7.0", - "@types/node": ">=12.12.47" + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" }, "engines": { - "node": "^8.13.0 || >=10.10.0" + "node": ">=12.10.0" } }, "node_modules/@grpc/proto-loader": { @@ -2349,26 +1419,93 @@ "node": ">=6" } }, - "node_modules/@grpc/proto-loader/node_modules/protobufjs": { - "version": "7.2.5", - "hasInstallScript": true, - "license": "BSD-3-Clause", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "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" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/@istanbuljs/load-nyc-config": { @@ -2831,16 +1968,6 @@ "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", "license": "MIT" }, - "node_modules/@jsdoc/salty": { - "version": "0.2.5", - "license": "Apache-2.0", - "dependencies": { - "lodash": "^4.17.21" - }, - "engines": { - "node": ">=v12.0.0" - } - }, "node_modules/@npmcli/fs": { "version": "2.1.2", "license": "ISC", @@ -2880,19 +2007,28 @@ } }, "node_modules/@opentelemetry/api": { - "version": "1.6.0", - "license": "Apache-2.0", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "engines": { "node": ">=8.0.0" } }, "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.3.1.tgz", - "integrity": "sha512-wU5J8rUoo32oSef/rFpOT1HIjLjAv3qIDHkw1QIhODV3OpAVHi5oVzlouozg9obUmZKtbZ0qUe/m7FP0y0yBzA==", - "license": "Apache-2.0", + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.26.0.tgz", + "integrity": "sha512-U9PJlOswJPSgQVPI+XEuNLElyFWkb0hAiMg+DExD9V0St03X2lPHGMdxMY/LrVmoukuIpXJ12oyrOtEZ4uXFkw==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, "engines": { - "node": ">=8.12.0" + "node": ">=14" } }, "node_modules/@pnpm/config.env-replace": { @@ -3007,6 +2143,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, "node_modules/@sinonjs/commons": { "version": "3.0.0", "dev": true, @@ -3105,13 +2252,6 @@ "@types/node": "*" } }, - "node_modules/@types/duplexify": { - "version": "3.6.3", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", @@ -3134,26 +2274,6 @@ "@types/send": "*" } }, - "node_modules/@types/firebase": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@types/firebase/-/firebase-3.2.1.tgz", - "integrity": "sha512-G8XgHMu2jHlElfc2xVNaYP50F0qrqeTCjgeG1v5b4SRwWG4XKC4fCuEdVZuZaMRmVygcnbRZBAo9O7RsDvmkGQ==", - "deprecated": "This is a stub types definition for Firebase API (https://www.firebase.com/docs/javascript/firebase). Firebase API provides its own type definitions, so you don't need @types/firebase installed!", - "dev": true, - "dependencies": { - "firebase": "*" - } - }, - "node_modules/@types/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", - "license": "MIT", - "dependencies": { - "@types/minimatch": "^5.1.2", - "@types/node": "*" - } - }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -3226,28 +2346,10 @@ "@types/node": "*" } }, - "node_modules/@types/linkify-it": { - "version": "3.0.4", - "license": "MIT" - }, - "node_modules/@types/long": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", - "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", - "license": "MIT" - }, - "node_modules/@types/markdown-it": { - "version": "12.2.3", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", - "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", - "license": "MIT", - "dependencies": { - "@types/linkify-it": "*", - "@types/mdurl": "*" - } - }, - "node_modules/@types/mdurl": { - "version": "1.0.4", + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", "license": "MIT" }, "node_modules/@types/mime": { @@ -3256,27 +2358,12 @@ "integrity": "sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==", "license": "MIT" }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "license": "MIT" - }, "node_modules/@types/node": { - "version": "20.8.10", - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-bQVlnMLFJ2d35DkPNjEPmd9ueO/rh5EiaZt2bhqiSarPjZIuIV6bPQVqcrEyvNo+AfTrRGVazle1tl597w3gfA==", - "dev": true, + "version": "22.7.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", + "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", "dependencies": { - "@types/node": "*", - "form-data": "^4.0.0" + "undici-types": "~6.19.2" } }, "node_modules/@types/qs": { @@ -3313,16 +2400,6 @@ "node": ">= 0.12" } }, - "node_modules/@types/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==", - "license": "MIT", - "dependencies": { - "@types/glob": "*", - "@types/node": "*" - } - }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", @@ -3339,13 +2416,6 @@ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "license": "MIT" }, - "node_modules/@types/send/node_modules/@types/node": { - "version": "20.8.10", - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, "node_modules/@types/serve-static": { "version": "1.15.5", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", @@ -3420,25 +2490,6 @@ "node": ">= 0.6" } }, - "node_modules/acorn": { - "version": "8.11.2", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, "node_modules/agent-base": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", @@ -3556,11 +2607,10 @@ "node": ">=7.0.0" } }, - "node_modules/ansicolors": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", - "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==", - "license": "MIT" + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" }, "node_modules/anymatch": { "version": "3.1.3", @@ -3581,78 +2631,154 @@ "optional": true }, "node_modules/archiver": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", - "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", - "license": "MIT", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", + "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", "dependencies": { - "archiver-utils": "^2.1.0", + "archiver-utils": "^5.0.2", "async": "^3.2.4", - "buffer-crc32": "^0.2.1", - "readable-stream": "^3.6.0", + "buffer-crc32": "^1.0.0", + "readable-stream": "^4.0.0", "readdir-glob": "^1.1.2", - "tar-stream": "^2.2.0", - "zip-stream": "^4.1.0" + "tar-stream": "^3.0.0", + "zip-stream": "^6.0.1" }, "engines": { - "node": ">= 10" + "node": ">= 14" } }, "node_modules/archiver-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", - "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", - "license": "MIT", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", + "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", "dependencies": { - "glob": "^7.1.4", + "glob": "^10.0.0", "graceful-fs": "^4.2.0", + "is-stream": "^2.0.1", "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", + "lodash": "^4.17.15", "normalize-path": "^3.0.0", - "readable-stream": "^2.0.0" + "readable-stream": "^4.0.0" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, - "node_modules/archiver-utils/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" + "node_modules/archiver-utils/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/archiver-utils/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/archiver-utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/archiver-utils/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } }, "node_modules/archiver-utils/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "license": "MIT", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/archiver-utils/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" + "node_modules/archiver/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } }, - "node_modules/archiver-utils/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "license": "MIT", + "node_modules/archiver/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", "dependencies": { - "safe-buffer": "~5.1.0" + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/are-we-there-yet": { @@ -3711,16 +2837,14 @@ "license": "MIT" }, "node_modules/async-lock": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.3.2.tgz", - "integrity": "sha512-phnXdS3RP7PPcmP6NWWzWMU0sLTeyvtZCxBPpZdkYE3seGLKSQZs9FrmVO/qwypq98FUtWWUEYxziLkdGk5nnA==", - "license": "MIT" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", + "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==" }, "node_modules/async-retry": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", - "license": "MIT", "optional": true, "dependencies": { "retry": "0.13.1" @@ -3732,6 +2856,11 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, + "node_modules/b4a": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==" + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -3834,6 +2963,12 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, + "node_modules/bare-events": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.0.tgz", + "integrity": "sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==", + "optional": true + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -3889,18 +3024,19 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", - "license": "MIT", "engines": { "node": "*" } }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "license": "MIT", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/bl": { @@ -3914,12 +3050,6 @@ "readable-stream": "^3.4.0" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "license": "MIT" - }, "node_modules/body-parser": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", @@ -4092,12 +3222,11 @@ } }, "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "license": "MIT", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", "engines": { - "node": "*" + "node": ">=8.0.0" } }, "node_modules/buffer-equal-constant-time": { @@ -4248,31 +3377,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/cardinal": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", - "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", - "license": "MIT", - "dependencies": { - "ansicolors": "~0.3.2", - "redeyed": "~2.1.0" - }, - "bin": { - "cdl": "bin/cdl.js" - } - }, - "node_modules/catharsis": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", - "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", - "license": "MIT", - "dependencies": { - "lodash": "^4.17.15" - }, - "engines": { - "node": ">= 10" - } - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -4293,7 +3397,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -4306,14 +3409,9 @@ "license": "MIT" }, "node_modules/chokidar": { - "version": "3.5.3", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -4326,6 +3424,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -4408,6 +3509,61 @@ "node": ">=8" } }, + "node_modules/cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/cli-highlight/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cli-highlight/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cli-highlight/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, "node_modules/cli-spinners": { "version": "2.9.1", "license": "MIT", @@ -4430,10 +3586,9 @@ } }, "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", - "license": "MIT", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dependencies": { "string-width": "^4.2.0" }, @@ -4448,7 +3603,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "license": "MIT", "optional": true, "engines": { "node": ">=0.1.90" @@ -4600,18 +3754,56 @@ } }, "node_modules/compress-commons": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", - "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", - "license": "MIT", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", + "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", "dependencies": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^4.0.2", + "crc-32": "^1.2.0", + "crc32-stream": "^6.0.0", + "is-stream": "^2.0.1", "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" + "readable-stream": "^4.0.0" }, "engines": { - "node": ">= 10" + "node": ">= 14" + } + }, + "node_modules/compress-commons/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/compress-commons/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/compressible": { @@ -4827,8 +4019,7 @@ "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "license": "MIT" + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "node_modules/cors": { "version": "2.8.5", @@ -4847,25 +4038,61 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "license": "Apache-2.0", "bin": { "crc32": "bin/crc32.njs" }, "engines": { - "node": ">=0.8" + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", + "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" } }, - "node_modules/crc32-stream": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", - "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", - "license": "MIT", + "node_modules/crc32-stream/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "crc-32": "^1.2.0", - "readable-stream": "^3.4.0" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/crc32-stream/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { - "node": ">= 10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/create-jest": { @@ -5045,6 +4272,15 @@ } } }, + "node_modules/deep-equal-in-any-order": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/deep-equal-in-any-order/-/deep-equal-in-any-order-2.0.6.tgz", + "integrity": "sha512-RfnWHQzph10YrUjvWwhd15Dne8ciSJcZ3U6OD7owPwiVwsdE5IFSoZGg8rlwJD11ES+9H5y8j3fCofviRHOqLQ==", + "dependencies": { + "lodash.mapvalues": "^4.6.0", + "sort-any": "^2.0.0" + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -5188,6 +4424,11 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" + }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -5201,17 +4442,21 @@ } }, "node_modules/duplexify": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", - "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", - "license": "MIT", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", + "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", "dependencies": { "end-of-stream": "^1.4.1", "inherits": "^2.0.3", "readable-stream": "^3.1.1", - "stream-shift": "^1.0.0" + "stream-shift": "^1.0.2" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -5251,6 +4496,11 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==" + }, "node_modules/enabled": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", @@ -5298,22 +4548,6 @@ "once": "^1.4.0" } }, - "node_modules/ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", - "license": "MIT", - "optional": true - }, - "node_modules/entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -5324,6 +4558,17 @@ "node": ">=6" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/err-code": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", @@ -5372,66 +4617,6 @@ "node": ">=0.8.0" } }, - "node_modules/escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "license": "BSD-2-Clause", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=4.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -5481,6 +4666,14 @@ "node": ">=6" } }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/events-listener": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/events-listener/-/events-listener-1.1.0.tgz", @@ -5512,10 +4705,9 @@ } }, "node_modules/exegesis": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/exegesis/-/exegesis-4.1.1.tgz", - "integrity": "sha512-PvSqaMOw2absLBgsthtJyVOeCHN4lxQ1dM7ibXb6TfZZJaoXtGELoEAGJRFvdN16+u9kg8oy1okZXRk8VpimWA==", - "license": "MIT", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/exegesis/-/exegesis-4.2.0.tgz", + "integrity": "sha512-MOzRyqhvl+hTA4+W4p0saWRIPlu0grIx4ykjMEYgGLiqr/z9NCIlwSq2jF0gyxNjPZD3xyHgmkW6BSaLVUdctg==", "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.3", "ajv": "^8.3.0", @@ -5524,7 +4716,7 @@ "content-type": "^1.0.4", "deep-freeze": "0.0.1", "events-listener": "^1.1.0", - "glob": "^7.1.3", + "glob": "^10.3.10", "json-ptr": "^3.0.1", "json-schema-traverse": "^1.0.0", "lodash": "^4.17.11", @@ -5586,6 +4778,47 @@ } } }, + "node_modules/exegesis/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/exegesis/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/exegesis/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/exegesis/node_modules/qs": { "version": "6.11.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", @@ -5775,30 +5008,31 @@ "node": ">=0.6.0" } }, + "node_modules/farmhash-modern": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/farmhash-modern/-/farmhash-modern-1.1.0.tgz", + "integrity": "sha512-6ypT4XfgqJk/F3Yuv4SX26I3doUjt0GTG4a+JgWxXQpxXzTBq8fPUeGHfcYMMDPHJHm3yPOSjaeBwBGAHWXCdA==", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "license": "MIT" }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "license": "MIT" - }, - "node_modules/fast-text-encoding": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", - "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==", - "license": "Apache-2.0" - }, "node_modules/fast-url-parser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", @@ -5815,7 +5049,9 @@ "license": "MIT" }, "node_modules/fast-xml-parser": { - "version": "4.3.2", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.0.tgz", + "integrity": "sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==", "funding": [ { "type": "github", @@ -5826,7 +5062,6 @@ "url": "https://paypal.me/naturalintelligence" } ], - "license": "MIT", "optional": true, "dependencies": { "strnum": "^1.0.5" @@ -5947,85 +5182,89 @@ } }, "node_modules/firebase": { - "version": "10.12.4", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.12.4.tgz", - "integrity": "sha512-SQz49NMpwG4MLTPZ9C8jBp7IyS2haTvsIvjclgu+v/jvzNtjZoxIcoF6A13EIfBHmJ5eiuVlvttxElOf7LnJew==", - "dependencies": { - "@firebase/analytics": "0.10.6", - "@firebase/analytics-compat": "0.2.12", - "@firebase/app": "0.10.7", - "@firebase/app-check": "0.8.6", - "@firebase/app-check-compat": "0.3.13", - "@firebase/app-compat": "0.2.37", + "version": "10.14.0", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.14.0.tgz", + "integrity": "sha512-/yB/OE4bfBbmtfku0DCdW6nWMHYVayN6xWKw68ztedxqGevfYDoPoygBXiLmvBHdWdBa+IlhJDkdUUiEEpcAUw==", + "dependencies": { + "@firebase/analytics": "0.10.8", + "@firebase/analytics-compat": "0.2.14", + "@firebase/app": "0.10.12", + "@firebase/app-check": "0.8.8", + "@firebase/app-check-compat": "0.3.15", + "@firebase/app-compat": "0.2.42", "@firebase/app-types": "0.9.2", - "@firebase/auth": "1.7.5", - "@firebase/auth-compat": "0.5.10", - "@firebase/database": "1.0.6", - "@firebase/database-compat": "1.0.6", - "@firebase/firestore": "4.6.4", - "@firebase/firestore-compat": "0.3.33", - "@firebase/functions": "0.11.6", - "@firebase/functions-compat": "0.3.12", - "@firebase/installations": "0.6.8", - "@firebase/installations-compat": "0.2.8", - "@firebase/messaging": "0.12.10", - "@firebase/messaging-compat": "0.2.10", - "@firebase/performance": "0.6.8", - "@firebase/performance-compat": "0.2.8", - "@firebase/remote-config": "0.4.8", - "@firebase/remote-config-compat": "0.2.8", - "@firebase/storage": "0.12.6", - "@firebase/storage-compat": "0.3.9", - "@firebase/util": "1.9.7", - "@firebase/vertexai-preview": "0.0.3" + "@firebase/auth": "1.7.9", + "@firebase/auth-compat": "0.5.14", + "@firebase/data-connect": "0.1.0", + "@firebase/database": "1.0.8", + "@firebase/database-compat": "1.0.8", + "@firebase/firestore": "4.7.3", + "@firebase/firestore-compat": "0.3.38", + "@firebase/functions": "0.11.8", + "@firebase/functions-compat": "0.3.14", + "@firebase/installations": "0.6.9", + "@firebase/installations-compat": "0.2.9", + "@firebase/messaging": "0.12.11", + "@firebase/messaging-compat": "0.2.11", + "@firebase/performance": "0.6.9", + "@firebase/performance-compat": "0.2.9", + "@firebase/remote-config": "0.4.9", + "@firebase/remote-config-compat": "0.2.9", + "@firebase/storage": "0.13.2", + "@firebase/storage-compat": "0.3.12", + "@firebase/util": "1.10.0", + "@firebase/vertexai-preview": "0.0.4" } }, "node_modules/firebase-admin": { - "version": "11.11.0", - "license": "Apache-2.0", - "dependencies": { - "@fastify/busboy": "^1.2.1", - "@firebase/database-compat": "^0.3.4", - "@firebase/database-types": "^0.10.4", - "@types/node": ">=12.12.47", + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-12.6.0.tgz", + "integrity": "sha512-gc0pDiUmxscxBhcjMcttmjvExJmnQdVRb+IIth95CvMm7F9rLdabrQZThW2mK02HR696P+rzd6NqkdUA3URu4w==", + "dependencies": { + "@fastify/busboy": "^3.0.0", + "@firebase/database-compat": "^1.0.2", + "@firebase/database-types": "^1.0.0", + "@types/node": "^22.0.1", + "farmhash-modern": "^1.1.0", "jsonwebtoken": "^9.0.0", - "jwks-rsa": "^3.0.1", + "jwks-rsa": "^3.1.0", "node-forge": "^1.3.1", - "uuid": "^9.0.0" + "uuid": "^10.0.0" }, "engines": { "node": ">=14" }, "optionalDependencies": { - "@google-cloud/firestore": "^6.6.0", - "@google-cloud/storage": "^6.9.5" + "@google-cloud/firestore": "^7.7.0", + "@google-cloud/storage": "^7.7.0" } }, "node_modules/firebase-admin/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], - "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/firebase-tools": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/firebase-tools/-/firebase-tools-13.3.0.tgz", - "integrity": "sha512-WooMk02Wucre63XGHNOopwRp/FFCL/zjq1Jz0itZ6fDeytdTxZabhlcvnX+HMCyccPhuwbs3extIEh/T6SFWtA==", + "version": "13.20.2", + "resolved": "https://registry.npmjs.org/firebase-tools/-/firebase-tools-13.20.2.tgz", + "integrity": "sha512-lhJ8C/hNtNyG57IIWZ+j+0JaiB3A/wo7c/LFouRigE+/IRo13le2uotBAFI7XjTOgxelxs8wGA6u/4fgQAz8Zw==", "dependencies": { - "@google-cloud/pubsub": "^3.0.1", + "@electric-sql/pglite": "^0.2.0", + "@google-cloud/cloud-sql-connector": "^1.3.3", + "@google-cloud/pubsub": "^4.5.0", "abort-controller": "^3.0.0", "ajv": "^6.12.6", - "archiver": "^5.0.0", - "async-lock": "1.3.2", + "archiver": "^7.0.0", + "async-lock": "1.4.1", "body-parser": "^1.19.0", - "chokidar": "^3.0.2", + "chokidar": "^3.6.0", "cjson": "^0.3.1", "cli-table": "0.3.11", "colorette": "^2.0.19", @@ -6035,22 +5274,26 @@ "cross-env": "^5.1.3", "cross-spawn": "^7.0.3", "csv-parse": "^5.0.4", - "exegesis": "^4.1.0", + "deep-equal-in-any-order": "^2.0.6", + "exegesis": "^4.2.0", "exegesis-express": "^4.0.0", "express": "^4.16.4", "filesize": "^6.1.0", "form-data": "^4.0.0", "fs-extra": "^10.1.0", - "glob": "^7.1.2", - "google-auth-library": "^7.11.0", - "inquirer": "^8.2.0", - "js-yaml": "^3.13.1", + "fuzzy": "^0.1.3", + "gaxios": "^6.7.0", + "glob": "^10.4.1", + "google-auth-library": "^9.11.0", + "inquirer": "^8.2.6", + "inquirer-autocomplete-prompt": "^2.0.1", "jsonwebtoken": "^9.0.0", "leven": "^3.1.0", "libsodium-wrappers": "^0.7.10", "lodash": "^4.17.21", - "marked": "^4.0.14", - "marked-terminal": "^5.1.1", + "lsofi": "1.0.0", + "marked": "^13.0.2", + "marked-terminal": "^7.0.0", "mime": "^2.5.2", "minimatch": "^3.0.4", "morgan": "^1.10.0", @@ -6058,26 +5301,29 @@ "open": "^6.3.0", "ora": "^5.4.1", "p-limit": "^3.0.1", + "pg": "^8.11.3", "portfinder": "^1.0.32", "progress": "^2.0.3", "proxy-agent": "^6.3.0", "retry": "^0.13.1", - "rimraf": "^3.0.0", + "rimraf": "^5.0.0", "semver": "^7.5.2", + "sql-formatter": "^15.3.0", "stream-chain": "^2.2.4", "stream-json": "^1.7.3", "strip-ansi": "^6.0.1", "superstatic": "^9.0.3", "tar": "^6.1.11", "tcp-port-used": "^1.0.2", - "tmp": "^0.2.1", + "tmp": "^0.2.3", "triple-beam": "^1.3.0", "universal-analytics": "^0.5.3", "update-notifier-cjs": "^5.1.6", "uuid": "^8.3.2", "winston": "^3.0.0", "winston-transport": "^4.4.0", - "ws": "^7.2.3" + "ws": "^7.5.10", + "yaml": "^2.4.1" }, "bin": { "firebase": "lib/bin/firebase.js" @@ -6086,186 +5332,83 @@ "node": ">=18.0.0 || >=20.0.0" } }, - "node_modules/firebase-tools/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/firebase-tools/node_modules/gaxios": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", - "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", - "license": "Apache-2.0", - "dependencies": { - "abort-controller": "^3.0.0", - "extend": "^3.0.2", - "https-proxy-agent": "^5.0.0", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.7" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/firebase-tools/node_modules/gcp-metadata": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", - "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", - "license": "Apache-2.0", - "dependencies": { - "gaxios": "^4.0.0", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/firebase-tools/node_modules/google-auth-library": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", - "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", - "license": "Apache-2.0", - "dependencies": { - "arrify": "^2.0.0", - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "fast-text-encoding": "^1.0.0", - "gaxios": "^4.0.0", - "gcp-metadata": "^4.2.0", - "gtoken": "^5.0.4", - "jws": "^4.0.0", - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/firebase-tools/node_modules/google-p12-pem": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", - "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", - "license": "MIT", + "node_modules/firebase-tools/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dependencies": { - "node-forge": "^1.3.1" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { - "gp12-pem": "build/src/bin/gp12-pem.js" + "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/firebase-tools/node_modules/gtoken": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", - "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", - "license": "MIT", + "node_modules/firebase-tools/node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dependencies": { - "gaxios": "^4.0.0", - "google-p12-pem": "^3.1.3", - "jws": "^4.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" - } - }, - "node_modules/firebase-tools/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "node": ">=16 || 14 >=14.17" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/firebase-tools/node_modules/semver": { - "version": "7.5.4", - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "node_modules/firebase-tools/node_modules/marked": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz", + "integrity": "sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==", "bin": { - "semver": "bin/semver.js" + "marked": "bin/marked.js" }, "engines": { - "node": ">=10" - } - }, - "node_modules/firebase/node_modules/@firebase/app-types": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz", - "integrity": "sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==" - }, - "node_modules/firebase/node_modules/@firebase/auth-interop-types": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz", - "integrity": "sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==" - }, - "node_modules/firebase/node_modules/@firebase/component": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.8.tgz", - "integrity": "sha512-LcNvxGLLGjBwB0dJUsBGCej2fqAepWyBubs4jt1Tiuns7QLbXHuyObZ4aMeBjZjWx4m8g1LoVI9QFpSaq/k4/g==", - "dependencies": { - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/firebase/node_modules/@firebase/database": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.6.tgz", - "integrity": "sha512-nrexUEG/fpVlHtWKkyfhTC3834kZ1WS7voNyqbBsBCqHXQOvznN5Z0L3nxBqdXSJyltNAf4ndFlQqm5gZiEczQ==", - "dependencies": { - "@firebase/app-check-interop-types": "0.3.2", - "@firebase/auth-interop-types": "0.2.3", - "@firebase/component": "0.6.8", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.9.7", - "faye-websocket": "0.11.4", - "tslib": "^2.1.0" - } - }, - "node_modules/firebase/node_modules/@firebase/database-compat": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.6.tgz", - "integrity": "sha512-1OGA0sLY47mkXjhICCrUTXEYFnSSXoiXWm1SHsN62b+Lzs5aKA3aWTjTUmYIoK93kDAMPkYpulSv8jcbH4Hwew==", - "dependencies": { - "@firebase/component": "0.6.8", - "@firebase/database": "1.0.6", - "@firebase/database-types": "1.0.4", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.9.7", - "tslib": "^2.1.0" - } - }, - "node_modules/firebase/node_modules/@firebase/database-types": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.4.tgz", - "integrity": "sha512-mz9ZzbH6euFXbcBo+enuJ36I5dR5w+enJHHjy9Y5ThCdKUseqfDjW3vCp1YxE9zygFCSjJJ/z1cQ+zodvUcwPQ==", - "dependencies": { - "@firebase/app-types": "0.9.2", - "@firebase/util": "1.9.7" + "node": ">= 18" } }, - "node_modules/firebase/node_modules/@firebase/logger": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "node_modules/firebase-tools/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/firebase-tools/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", "dependencies": { - "tslib": "^2.1.0" + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/firebase/node_modules/@firebase/util": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.7.tgz", - "integrity": "sha512-fBVNH/8bRbYjqlbIhZ+lBtdAAS4WqZumx03K06/u7fJSpz1TGjEMm1ImvKD47w+xaFKIP2ori6z8BrbakRfjJA==", + "node_modules/firebase-tools/node_modules/semver": { + "version": "7.5.4", + "license": "ISC", "dependencies": { - "tslib": "^2.1.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/fn.name": { @@ -6274,6 +5417,32 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", "license": "MIT" }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -6306,12 +5475,6 @@ "node": ">= 0.6" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "license": "MIT" - }, "node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -6342,6 +5505,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "devOptional": true, "license": "ISC" }, "node_modules/fsevents": { @@ -6370,9 +5534,16 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "license": "MIT", "optional": true }, + "node_modules/fuzzy": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/fuzzy/-/fuzzy-0.1.3.tgz", + "integrity": "sha512-/gZffu4ykarLrCiP3Ygsa86UAo1E5vEVlvTrpkKywXSbP9Xhln3oSp9QSV57gEq3JFFpGJ4GZ+5zdEp3FcUh4w==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/gauge": { "version": "4.0.4", "license": "ISC", @@ -6392,31 +5563,54 @@ } }, "node_modules/gaxios": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz", - "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==", - "license": "Apache-2.0", + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", + "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", "dependencies": { "extend": "^3.0.2", - "https-proxy-agent": "^5.0.0", + "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", - "node-fetch": "^2.6.9" + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" }, "engines": { - "node": ">=12" + "node": ">=14" + } + }, + "node_modules/gaxios/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/gaxios/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" } }, "node_modules/gcp-metadata": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz", - "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==", - "license": "Apache-2.0", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", + "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", "dependencies": { - "gaxios": "^5.0.0", + "gaxios": "^6.0.0", "json-bigint": "^1.0.0" }, "engines": { - "node": ">=12" + "node": ">=14" } }, "node_modules/gensync": { @@ -6461,6 +5655,17 @@ "node": ">=8.0.0" } }, + "node_modules/get-stdin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -6517,6 +5722,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "devOptional": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -6537,7 +5743,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -6597,68 +5802,81 @@ } }, "node_modules/google-auth-library": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.9.0.tgz", - "integrity": "sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg==", - "license": "Apache-2.0", + "version": "9.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.14.1.tgz", + "integrity": "sha512-Rj+PMjoNFGFTmtItH7gHfbHpGVSb3vmnGK3nwNBqxQF9NoBpttSZI/rc0WiM63ma2uGDQtYEkMHkK9U6937NiA==", "dependencies": { - "arrify": "^2.0.0", "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", - "fast-text-encoding": "^1.0.0", - "gaxios": "^5.0.0", - "gcp-metadata": "^5.3.0", - "gtoken": "^6.1.0", - "jws": "^4.0.0", - "lru-cache": "^6.0.0" + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" }, "engines": { - "node": ">=12" + "node": ">=14" } }, "node_modules/google-gax": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-3.6.1.tgz", - "integrity": "sha512-g/lcUjGcB6DSw2HxgEmCDOrI/CByOwqRvsuUvNalHUK2iPPPlmAIpbMbl62u0YufGMr8zgE3JL7th6dCb1Ry+w==", - "license": "Apache-2.0", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.4.1.tgz", + "integrity": "sha512-Phyp9fMfA00J3sZbJxbbB4jC55b7DBjE3F6poyL3wKMEBVKA79q6BGuHcTiM28yOzVql0NDbRL8MLLh8Iwk9Dg==", "dependencies": { - "@grpc/grpc-js": "~1.8.0", - "@grpc/proto-loader": "^0.7.0", + "@grpc/grpc-js": "^1.10.9", + "@grpc/proto-loader": "^0.7.13", "@types/long": "^4.0.0", - "@types/rimraf": "^3.0.2", "abort-controller": "^3.0.0", "duplexify": "^4.0.0", - "fast-text-encoding": "^1.0.3", - "google-auth-library": "^8.0.2", - "is-stream-ended": "^0.1.4", - "node-fetch": "^2.6.1", + "google-auth-library": "^9.3.0", + "node-fetch": "^2.7.0", "object-hash": "^3.0.0", - "proto3-json-serializer": "^1.0.0", - "protobufjs": "7.2.4", - "protobufjs-cli": "1.1.1", - "retry-request": "^5.0.0" - }, - "bin": { - "compileProtos": "build/tools/compileProtos.js", - "minifyProtoJson": "build/tools/minify.js" + "proto3-json-serializer": "^2.0.2", + "protobufjs": "^7.3.2", + "retry-request": "^7.0.0", + "uuid": "^9.0.1" }, "engines": { - "node": ">=12" + "node": ">=14" } }, - "node_modules/google-p12-pem": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-4.0.1.tgz", - "integrity": "sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ==", - "license": "MIT", - "dependencies": { - "node-forge": "^1.3.1" - }, + "node_modules/google-gax/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { - "gp12-pem": "build/src/bin/gp12-pem.js" + "uuid": "dist/bin/uuid" + } + }, + "node_modules/googleapis-common": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-7.2.0.tgz", + "integrity": "sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA==", + "dependencies": { + "extend": "^3.0.2", + "gaxios": "^6.0.3", + "google-auth-library": "^9.7.0", + "qs": "^6.7.0", + "url-template": "^2.0.8", + "uuid": "^9.0.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" + } + }, + "node_modules/googleapis-common/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" } }, "node_modules/gopd": { @@ -6680,17 +5898,15 @@ "license": "ISC" }, "node_modules/gtoken": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-6.1.2.tgz", - "integrity": "sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ==", - "license": "MIT", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", + "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", "dependencies": { - "gaxios": "^5.0.1", - "google-p12-pem": "^4.0.0", + "gaxios": "^6.0.0", "jws": "^4.0.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" } }, "node_modules/has-flag": { @@ -6761,14 +5977,37 @@ } }, "node_modules/heap-js": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/heap-js/-/heap-js-2.3.0.tgz", - "integrity": "sha512-E5303mzwQ+4j/n2J0rDvEPBN7GKjhis10oHiYOgjxsmxYgqG++hz9NyLLOXttzH8as/DyiBHYpUrJTZWYaMo8Q==", - "license": "BSD-3-Clause", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/heap-js/-/heap-js-2.5.0.tgz", + "integrity": "sha512-kUGoI3p7u6B41z/dp33G6OaL7J4DRqRYwVmeIlwLClx7yaaAy7hoDExnuejTKtuDwfcatGmddHDEOjf6EyIxtQ==", "engines": { "node": ">=10.0.0" } }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "engines": { + "node": "*" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "optional": true + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -6966,6 +6205,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "devOptional": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -7010,6 +6250,24 @@ "node": ">=12.0.0" } }, + "node_modules/inquirer-autocomplete-prompt": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inquirer-autocomplete-prompt/-/inquirer-autocomplete-prompt-2.0.1.tgz", + "integrity": "sha512-jUHrH0btO7j5r8DTQgANf2CBkTZChoVySD8zF/wp5fZCOLIuUbleXhf4ZY5jNBOc1owA3gdfWtfZuppfYBhcUg==", + "dependencies": { + "ansi-escapes": "^4.3.2", + "figures": "^3.2.0", + "picocolors": "^1.0.0", + "run-async": "^2.4.1", + "rxjs": "^7.5.4" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "inquirer": "^8.0.0" + } + }, "node_modules/inquirer/node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -7066,7 +6324,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -7074,6 +6331,11 @@ "node": ">=8" } }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "node_modules/is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -7109,7 +6371,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7137,7 +6398,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -7410,6 +6670,20 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -8038,63 +7312,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/js2xmlparser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", - "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", - "license": "Apache-2.0", - "dependencies": { - "xmlcreate": "^2.0.4" - } - }, - "node_modules/jsdoc": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", - "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", - "license": "Apache-2.0", - "dependencies": { - "@babel/parser": "^7.20.15", - "@jsdoc/salty": "^0.2.1", - "@types/markdown-it": "^12.2.3", - "bluebird": "^3.7.2", - "catharsis": "^0.9.0", - "escape-string-regexp": "^2.0.0", - "js2xmlparser": "^4.0.2", - "klaw": "^3.0.0", - "markdown-it": "^12.3.2", - "markdown-it-anchor": "^8.4.1", - "marked": "^4.0.10", - "mkdirp": "^1.0.4", - "requizzle": "^0.2.3", - "strip-json-comments": "^3.1.0", - "underscore": "~1.13.2" - }, - "bin": { - "jsdoc": "jsdoc.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/jsdoc/node_modules/@babel/parser": { - "version": "7.23.0", - "license": "MIT", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/jsdoc/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -8112,7 +7329,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "license": "MIT", "dependencies": { "bignumber.js": "^9.0.0" } @@ -8264,13 +7480,15 @@ "safe-buffer": "^5.0.1" } }, - "node_modules/klaw": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", - "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", - "license": "MIT", + "node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "dependencies": { - "graceful-fs": "^4.1.9" + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, "node_modules/kleur": { @@ -8293,7 +7511,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "license": "MIT", "dependencies": { "readable-stream": "^2.0.5" }, @@ -8304,14 +7521,12 @@ "node_modules/lazystream/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, "node_modules/lazystream/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -8325,14 +7540,12 @@ "node_modules/lazystream/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/lazystream/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } @@ -8346,19 +7559,6 @@ "node": ">=6" } }, - "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/libsodium": { "version": "0.7.13", "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.13.tgz", @@ -8383,17 +7583,8 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", - "license": "MIT", - "dependencies": { - "uc.micro": "^1.0.1" - } + "dev": true, + "license": "MIT" }, "node_modules/locate-path": { "version": "5.0.0", @@ -8432,24 +7623,6 @@ "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", "license": "MIT" }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "license": "MIT" - }, - "node_modules/lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", - "license": "MIT" - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "license": "MIT" - }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -8495,6 +7668,11 @@ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "license": "MIT" }, + "node_modules/lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==" + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -8510,14 +7688,7 @@ "node_modules/lodash.snakecase": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "license": "MIT" - }, - "node_modules/lodash.union": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", - "license": "MIT" + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" }, "node_modules/log-symbols": { "version": "4.1.0", @@ -8596,6 +7767,26 @@ "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", "license": "ISC" }, + "node_modules/lsofi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lsofi/-/lsofi-1.0.0.tgz", + "integrity": "sha512-MKr9vM1MSm+TSKfI05IYxpKV1NCxpJaBLnELyIf784zYJ5KV9lGCE1EvpA2DtXDNM3fCuFeCwXUzim/fyQRi+A==", + "dependencies": { + "is-number": "^2.1.0", + "through2": "^2.0.1" + } + }, + "node_modules/lsofi/node_modules/is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -8685,37 +7876,12 @@ "tmpl": "1.0.5" } }, - "node_modules/markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it-anchor": { - "version": "8.6.7", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", - "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", - "license": "Unlicense", - "peerDependencies": { - "@types/markdown-it": "*", - "markdown-it": "*" - } - }, "node_modules/marked": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "license": "MIT", + "peer": true, "bin": { "marked": "bin/marked.js" }, @@ -8724,35 +7890,33 @@ } }, "node_modules/marked-terminal": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.2.0.tgz", - "integrity": "sha512-Piv6yNwAQXGFjZSaiNljyNFw7jKDdGrw70FSbtxEyldLsyeuV5ZHm/1wW++kWbrOF1VPnUgYOhB2oLL0ZpnekA==", - "license": "MIT", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.1.0.tgz", + "integrity": "sha512-+pvwa14KZL74MVXjYdPR3nSInhGhNvPce/3mqLVZT2oUvt654sL1XImFuLZ1pkA866IYZ3ikDTOFUIC7XzpZZg==", "dependencies": { - "ansi-escapes": "^6.2.0", - "cardinal": "^2.1.1", - "chalk": "^5.2.0", - "cli-table3": "^0.6.3", - "node-emoji": "^1.11.0", - "supports-hyperlinks": "^2.3.0" + "ansi-escapes": "^7.0.0", + "chalk": "^5.3.0", + "cli-highlight": "^2.1.11", + "cli-table3": "^0.6.5", + "node-emoji": "^2.1.3", + "supports-hyperlinks": "^3.0.0" }, "engines": { - "node": ">=14.13.1 || >=16.0.0" + "node": ">=16.0.0" }, "peerDependencies": { - "marked": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" + "marked": ">=1 <14" } }, "node_modules/marked-terminal/node_modules/ansi-escapes": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", - "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", - "license": "MIT", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dependencies": { - "type-fest": "^3.0.0" + "environment": "^1.0.0" }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8762,7 +7926,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -8770,24 +7933,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/marked-terminal/node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "license": "MIT" - }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -9009,6 +8154,11 @@ "node": ">=10" } }, + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" + }, "node_modules/morgan": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", @@ -9064,6 +8214,16 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "license": "ISC" }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nan": { "version": "2.18.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", @@ -9078,6 +8238,32 @@ "dev": true, "license": "MIT" }, + "node_modules/nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", + "dependencies": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" + }, + "bin": { + "nearley-railroad": "bin/nearley-railroad.js", + "nearley-test": "bin/nearley-test.js", + "nearley-unparse": "bin/nearley-unparse.js", + "nearleyc": "bin/nearleyc.js" + }, + "funding": { + "type": "individual", + "url": "https://nearley.js.org/#give-to-nearley" + } + }, + "node_modules/nearley/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -9103,12 +8289,17 @@ "license": "MIT" }, "node_modules/node-emoji": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", - "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", - "license": "MIT", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", + "integrity": "sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==", "dependencies": { - "lodash": "^4.17.21" + "@sindresorhus/is": "^4.6.0", + "char-regex": "^1.0.2", + "emojilib": "^2.4.0", + "skin-tone": "^2.0.0" + }, + "engines": { + "node": ">=18" } }, "node_modules/node-fetch": { @@ -9135,7 +8326,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" } @@ -9340,23 +8530,6 @@ "yaml": "^2.2.1" } }, - "node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "license": "MIT", - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -9393,7 +8566,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-3.0.0.tgz", "integrity": "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==", - "license": "MIT", "engines": { "node": ">=8" } @@ -9458,6 +8630,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-throttle": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/p-throttle/-/p-throttle-5.1.0.tgz", + "integrity": "sha512-+N+s2g01w1Zch4D0K3OpnPDqLOKmLcQ4BvIFq3JC0K29R28vUOjWpO+OJZBNt8X9i3pFCksZJZ0YXkUGjaFE6g==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -9525,6 +8708,11 @@ "version": "1.1.8", "license": "MIT" }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -9544,6 +8732,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -9567,6 +8773,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9588,17 +8795,125 @@ "dev": true, "license": "MIT" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", "license": "MIT" }, + "node_modules/pg": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.0.tgz", + "integrity": "sha512-34wkUTh3SxTClfoHB3pQ7bIMvw9dpFU1audQQeZG837fmHfHpr14n/AELVDoOYVDW2h5RDWU78tFjkD+erSBsw==", + "dependencies": { + "pg-connection-string": "^2.7.0", + "pg-pool": "^3.7.0", + "pg-protocol": "^1.7.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz", + "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.7.0.tgz", + "integrity": "sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.7.0.tgz", + "integrity": "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "^4.1.0" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -9680,12 +8995,39 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", "engines": { - "node": ">= 0.8.0" + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, "node_modules/pretty-format": { @@ -9716,11 +9058,18 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "license": "MIT" + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "node_modules/progress": { "version": "2.0.3", @@ -9787,23 +9136,21 @@ "license": "ISC" }, "node_modules/proto3-json-serializer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-1.1.1.tgz", - "integrity": "sha512-AwAuY4g9nxx0u52DnSMkqqgyLHaW/XaPLtaAo3y/ZCfeaQB/g4YDH4kb8Wc/mWzWvu0YjOznVnfn373MVZZrgw==", - "license": "Apache-2.0", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz", + "integrity": "sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ==", "dependencies": { - "protobufjs": "^7.0.0" + "protobufjs": "^7.2.5" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" } }, "node_modules/protobufjs": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", - "integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", "hasInstallScript": true, - "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -9822,78 +9169,6 @@ "node": ">=12.0.0" } }, - "node_modules/protobufjs-cli": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.1.tgz", - "integrity": "sha512-VPWMgIcRNyQwWUv8OLPyGQ/0lQY/QTQAVN5fh+XzfDwsVw1FZ2L3DM/bcBf8WPiRz2tNpaov9lPZfNcmNo6LXA==", - "license": "BSD-3-Clause", - "dependencies": { - "chalk": "^4.0.0", - "escodegen": "^1.13.0", - "espree": "^9.0.0", - "estraverse": "^5.1.0", - "glob": "^8.0.0", - "jsdoc": "^4.0.0", - "minimist": "^1.2.0", - "semver": "^7.1.2", - "tmp": "^0.2.1", - "uglify-js": "^3.7.7" - }, - "bin": { - "pbjs": "bin/pbjs", - "pbts": "bin/pbts" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "protobufjs": "^7.0.0" - } - }, - "node_modules/protobufjs-cli/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/protobufjs-cli/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/protobufjs-cli/node_modules/semver": { - "version": "7.5.4", - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -10021,13 +9296,35 @@ "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" + }, + "node_modules/railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" + }, + "node_modules/randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "dependencies": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" }, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.12" } }, "node_modules/range-parser": { @@ -10114,7 +9411,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", - "license": "Apache-2.0", "dependencies": { "minimatch": "^5.1.0" } @@ -10123,7 +9419,6 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -10135,7 +9430,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -10143,15 +9437,6 @@ "node": ">=8.10.0" } }, - "node_modules/redeyed": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", - "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", - "license": "MIT", - "dependencies": { - "esprima": "~4.0.0" - } - }, "node_modules/registry-auth-token": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", @@ -10194,15 +9479,6 @@ "node": ">=0.10.0" } }, - "node_modules/requizzle": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", - "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", - "license": "MIT", - "dependencies": { - "lodash": "^4.17.21" - } - }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -10267,6 +9543,14 @@ "node": ">=8" } }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "engines": { + "node": ">=0.12" + } + }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -10277,16 +9561,16 @@ } }, "node_modules/retry-request": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-5.0.2.tgz", - "integrity": "sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ==", - "license": "MIT", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", + "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", "dependencies": { - "debug": "^4.1.1", - "extend": "^3.0.2" + "@types/request": "^2.48.8", + "extend": "^3.0.2", + "teeny-request": "^9.0.0" }, "engines": { - "node": ">=12" + "node": ">=14" } }, "node_modules/rimraf": { @@ -10294,6 +9578,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "license": "ISC", + "optional": true, "dependencies": { "glob": "^7.1.3" }, @@ -10396,11 +9681,6 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, - "node_modules/safevalues": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/safevalues/-/safevalues-0.6.0.tgz", - "integrity": "sha512-MZ7DcTOcIoPXN36/UONVE9BT0pmwlCr9WcS7Pj/q4FxOwr33FkWC0CUWj/THQXYWxf/F7urbhaHaOeFPSqGqHA==" - }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -10573,6 +9853,17 @@ "dev": true, "license": "MIT" }, + "node_modules/skin-tone": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", + "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", + "dependencies": { + "unicode-emoji-modifier-base": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -10619,6 +9910,14 @@ "node": ">= 14" } }, + "node_modules/sort-any": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-any/-/sort-any-2.0.0.tgz", + "integrity": "sha512-T9JoiDewQEmWcnmPn/s9h/PH9t3d/LSWi0RgVmXSuDYeZXTZOZ1/wrK2PHaptuR1VXe3clLLt0pD6sgVOwjNEA==", + "dependencies": { + "lodash": "^4.17.21" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -10640,10 +9939,32 @@ "source-map": "^0.6.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/sql-formatter": { + "version": "15.4.2", + "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.4.2.tgz", + "integrity": "sha512-Pw4aAgfuyml/SHMlhbJhyOv+GR+Z1HNb9sgX3CVBVdN5YNM+v2VWkYJ3NNbYS7cu37GY3vP/PgnwoVynCuXRxg==", + "dependencies": { + "argparse": "^2.0.1", + "get-stdin": "=8.0.0", + "nearley": "^2.20.1" + }, + "bin": { + "sql-formatter": "bin/sql-formatter-cli.cjs" + } }, "node_modules/ssri": { "version": "9.0.1", @@ -10707,7 +10028,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", - "license": "MIT", "dependencies": { "stubs": "^3.0.0" } @@ -10722,8 +10042,22 @@ } }, "node_modules/stream-shift": { - "version": "1.0.1", - "license": "MIT" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" + }, + "node_modules/streamx": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz", + "integrity": "sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==", + "dependencies": { + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } }, "node_modules/string_decoder": { "version": "1.3.0", @@ -10762,6 +10096,20 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "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" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -10774,6 +10122,18 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -10798,6 +10158,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10810,14 +10171,12 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", - "license": "MIT", "optional": true }, "node_modules/stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", - "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", - "license": "MIT" + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==" }, "node_modules/superstatic": { "version": "9.0.3", @@ -10900,16 +10259,18 @@ } }, "node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "license": "MIT", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz", + "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==", "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -10943,19 +10304,13 @@ } }, "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "license": "MIT", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" } }, "node_modules/tar/node_modules/minipass": { @@ -11001,20 +10356,18 @@ "license": "MIT" }, "node_modules/teeny-request": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-8.0.3.tgz", - "integrity": "sha512-jJZpA5He2y52yUhA7pyAGZlgQpcB+xLjcN0eUFxr9c8hP/H7uOXbBNVo/O0C/xVfJLJs680jvkFgVJEEvk9+ww==", - "license": "Apache-2.0", - "optional": true, + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", + "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", "dependencies": { "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.1", + "node-fetch": "^2.6.9", "stream-events": "^1.0.5", "uuid": "^9.0.0" }, "engines": { - "node": ">=12" + "node": ">=14" } }, "node_modules/teeny-request/node_modules/uuid": { @@ -11025,8 +10378,6 @@ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], - "license": "MIT", - "optional": true, "bin": { "uuid": "dist/bin/uuid" } @@ -11046,11 +10397,13 @@ "node": ">=8" } }, - "node_modules/text-decoding": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz", - "integrity": "sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==", - "license": "MIT" + "node_modules/text-decoder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.0.tgz", + "integrity": "sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg==", + "dependencies": { + "b4a": "^1.6.4" + } }, "node_modules/text-hex": { "version": "1.0.0", @@ -11058,22 +10411,78 @@ "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", "license": "MIT" }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "license": "MIT" }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "license": "MIT", + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dependencies": { - "rimraf": "^3.0.0" - }, + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "engines": { - "node": ">=8.17.0" + "node": ">=14.14" } }, "node_modules/tmpl": { @@ -11202,18 +10611,6 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "license": "0BSD" }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -11272,53 +10669,25 @@ "node": ">=14.17" } }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "license": "MIT" - }, - "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "license": "BSD-2-Clause", - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", - "license": "MIT" - }, "node_modules/undici": { - "version": "5.28.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", - "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", - "dependencies": { - "@fastify/busboy": "^2.0.0" - }, + "version": "6.19.7", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.7.tgz", + "integrity": "sha512-HR3W/bMGPSr90i8AAp2C4DM3wChFdJPLrWYpIS++LxS8K+W535qftjt+4MyjNYHeWabMj1nvtmLIi7l++iq91A==", "engines": { - "node": ">=14.0" + "node": ">=18.17" } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "license": "MIT" + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" }, - "node_modules/undici/node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "node_modules/unicode-emoji-modifier-base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", + "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", "engines": { - "node": ">=14" + "node": ">=4" } }, "node_modules/unique-filename": { @@ -11472,6 +10841,11 @@ "integrity": "sha512-H6dnQ/yPAAVzMQRvEvyz01hhfQL5qRWSEt7BX8t9DqnPw9BjMb64fjIRq76Uvf1hkHp+mTZvEVJ5guXOT0Xqaw==", "license": "MIT" }, + "node_modules/url-template": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", + "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==" + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -11656,20 +11030,28 @@ "node": ">= 12.0.0" } }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi": { + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -11701,10 +11083,9 @@ } }, "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "license": "MIT", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "engines": { "node": ">=8.3.0" }, @@ -11730,11 +11111,13 @@ "node": ">=8" } }, - "node_modules/xmlcreate": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", - "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", - "license": "Apache-2.0" + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } }, "node_modules/y18n": { "version": "5.0.8", @@ -11752,10 +11135,12 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", - "license": "ISC", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "bin": { + "yaml": "bin.mjs" + }, "engines": { "node": ">= 14" } @@ -11800,38 +11185,54 @@ } }, "node_modules/zip-stream": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", - "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", - "license": "MIT", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", + "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", "dependencies": { - "archiver-utils": "^3.0.4", - "compress-commons": "^4.1.2", - "readable-stream": "^3.6.0" + "archiver-utils": "^5.0.0", + "compress-commons": "^6.0.2", + "readable-stream": "^4.0.0" }, "engines": { - "node": ">= 10" + "node": ">= 14" } }, - "node_modules/zip-stream/node_modules/archiver-utils": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", - "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", - "license": "MIT", + "node_modules/zip-stream/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "glob": "^7.2.3", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/zip-stream/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { - "node": ">= 10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } } } diff --git a/integration_test/package.json b/integration_test/package.json index bb584a13a..7b87c90a9 100644 --- a/integration_test/package.json +++ b/integration_test/package.json @@ -5,23 +5,20 @@ "dependencies": { "@google-cloud/eventarc": "^3.1.0", "@google-cloud/tasks": "^5.1.0", - "firebase": "^10.8.0", - "firebase-admin": "^11.11.0", - "firebase-tools": "^13.3.0", + "firebase": "^10.14.0", + "firebase-admin": "^12.6.0", + "firebase-tools": "^13.20.2", "js-yaml": "^4.1.0", "node-fetch": "2" }, "scripts": { - "copyfiles": "cp ./serviceAccount.json ./dist/serviceAccount.json", - "build": "tsc && npm run copyfiles", + "build": "tsc -p ./tsconfig.build.json", "test": "jest --detectOpenHandles", "start": "npm run build && node dist/run.js" }, "devDependencies": { - "@types/firebase": "^3.2.1", "@types/jest": "^29.5.11", "@types/js-yaml": "^4.0.9", - "@types/node-fetch": "2", "jest": "^29.7.0", "ts-jest": "^29.1.1" } diff --git a/integration_test/run.ts b/integration_test/run.ts index 236d1850a..e2bc8a4c1 100644 --- a/integration_test/run.ts +++ b/integration_test/run.ts @@ -1,35 +1,18 @@ -import path from "path"; import fs from "fs"; import yaml from "js-yaml"; import { spawn } from "child_process"; -import { fileURLToPath } from "url"; import portfinder from "portfinder"; import client from "firebase-tools"; import { getRuntimeDelegate } from "firebase-tools/lib/deploy/functions/runtimes/index.js"; import { detectFromPort } from "firebase-tools/lib/deploy/functions/runtimes/discovery/index.js"; import setup from "./setup.js"; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -function loadEnv(): void { - try { - const envPath = path.resolve(process.cwd(), ".env"); - console.log("Loading .env file from", envPath); - const envFileContent = fs.readFileSync(envPath, "utf-8"); - envFileContent.split("\n").forEach((variable) => { - const [key, value] = variable.split("="); - if (key && value) process.env[key.trim()] = value.trim(); - }); - } catch (error: any) { - console.error("Error loading .env file:", error.message); - } -} +import { loadEnv } from "./utils.js"; loadEnv(); -const { +let { NODE_VERSION = "18", - FIREBASE_ADMIN = "^10.0.0", + FIREBASE_ADMIN, PROJECT_ID, DATABASE_URL, STORAGE_BUCKET, @@ -38,6 +21,10 @@ const { FIREBASE_AUTH_DOMAIN, FIREBASE_API_KEY, GOOGLE_ANALYTICS_API_SECRET, + TEST_RUNTIME, + REGION = "us-central1", + FIRESTORE_REGION = "us-central1", + STORAGE_REGION = "us-central1", } = process.env; const TEST_RUN_ID = `t${Date.now()}`; @@ -49,30 +36,51 @@ if ( !FIREBASE_MEASUREMENT_ID || !FIREBASE_AUTH_DOMAIN || !FIREBASE_API_KEY || - !GOOGLE_ANALYTICS_API_SECRET + !GOOGLE_ANALYTICS_API_SECRET || + !TEST_RUNTIME ) { console.error("Required environment variables are not set. Exiting..."); process.exit(1); } -setup(TEST_RUN_ID, NODE_VERSION, FIREBASE_ADMIN); +if (!["node", "python"].includes(TEST_RUNTIME)) { + console.error("Invalid TEST_RUNTIME. Must be either 'node' or 'python'. Exiting..."); + process.exit(1); +} + +if (!FIREBASE_ADMIN && TEST_RUNTIME === "node") { + FIREBASE_ADMIN = "^12.0.0"; +} + +if (!FIREBASE_ADMIN && TEST_RUNTIME === "python") { + FIREBASE_ADMIN = "6.5.0"; +} + +setup(TEST_RUNTIME as "node" | "python", TEST_RUN_ID, NODE_VERSION, FIREBASE_ADMIN!); const config = { projectId: PROJECT_ID, projectDir: process.cwd(), sourceDir: `${process.cwd()}/functions`, - runtime: "nodejs18", + runtime: TEST_RUNTIME === "node" ? "nodejs18" : "python", }; +console.log("Firebase config created: "); +console.log(JSON.stringify(config, null, 2)); + const firebaseConfig = { databaseURL: DATABASE_URL, projectId: PROJECT_ID, storageBucket: STORAGE_BUCKET, }; + const env = { FIRESTORE_PREFER_REST: "true", GCLOUD_PROJECT: config.projectId, FIREBASE_CONFIG: JSON.stringify(firebaseConfig), + REGION, + FIRESTORE_REGION, + STORAGE_REGION, }; let modifiedYaml: any; @@ -185,12 +193,20 @@ function cleanFiles(): void { try { const files = fs.readdirSync("."); files.forEach((file) => { + // For Node if (file.match(`firebase-functions-${TEST_RUN_ID}.tgz`)) { fs.rmSync(file); } + // For Python + if (file.match(`firebase_functions.tar.gz`)) { + fs.rmSync(file); + } if (file.match("package.json")) { fs.rmSync(file); } + if (file.match("requirements.txt")) { + fs.rmSync(file); + } if (file.match("firebase-debug.log")) { fs.rmSync(file); } @@ -199,8 +215,8 @@ function cleanFiles(): void { } }); - fs.rmSync("lib", { recursive: true }); - // fs.existsSync("node_modules") && fs.rmSync("node_modules", { recursive: true }); + fs.rmSync("lib", { recursive: true, force: true }); + fs.rmSync("venv", { recursive: true, force: true }); } catch (error) { console.error("Error occurred while cleaning files:", error); } @@ -232,20 +248,21 @@ const spawnAsync = (command: string, args: string[], options: any): Promise { + const humanReadableRuntime = TEST_RUNTIME === "node" ? "Node.js" : "Python"; try { - console.log("Starting Node.js Tests..."); + console.log(`Starting ${humanReadableRuntime} Tests...`); const output = await spawnAsync("npm", ["test"], { env: { ...process.env, - GOOGLE_APPLICATION_CREDENTIALS: path.join(__dirname, "serviceAccount.json"), TEST_RUN_ID, }, stdio: "inherit", }); console.log(output); - console.log("Node.js Tests Completed."); + console.log(`${humanReadableRuntime} Tests Completed.`); } catch (error) { console.error("Error during testing:", error); + throw error; } } @@ -274,6 +291,7 @@ async function runIntegrationTests(): Promise { await runTests(); } catch (err) { console.error("Error occurred during integration tests", err); + throw new Error("Integration tests failed"); } finally { await handleCleanUp(); } @@ -284,4 +302,7 @@ runIntegrationTests() console.log("Integration tests completed"); process.exit(0); }) - .catch((error) => console.error("An error occurred during integration tests", error)); + .catch((error) => { + console.error("An error occurred during integration tests", error); + process.exit(1); + }); diff --git a/integration_test/setup-local.ts b/integration_test/setup-local.ts new file mode 100644 index 000000000..1ca037f40 --- /dev/null +++ b/integration_test/setup-local.ts @@ -0,0 +1,6 @@ +import setup from "./setup"; +import { loadEnv } from "./utils"; + +loadEnv(); + +setup("node", "local", "18", "^12.0.0"); diff --git a/integration_test/setup.ts b/integration_test/setup.ts index 95a0876e7..a00417f98 100644 --- a/integration_test/setup.ts +++ b/integration_test/setup.ts @@ -7,14 +7,27 @@ const DIR = process.cwd(); /** * Build SDK, and Functions */ -export default function setup(testRunId: string, nodeVersion: string, firebaseAdmin: string) { - buildSdk(testRunId); - createPackageJson(testRunId, nodeVersion, firebaseAdmin); - installDependencies(); - buildFunctions(); +export default function setup( + testRuntime: "node" | "python", + testRunId: string, + nodeVersion: string, + firebaseAdmin: string +) { + if (testRuntime === "node") { + buildNodeSdk(testRunId); + createPackageJson(testRunId, nodeVersion, firebaseAdmin); + installNodeDependencies(); + buildNodeFunctions(); + } + + if (testRuntime === "python") { + buildPythonSdk(); + createRequirementsTxt(firebaseAdmin); + installPythonDependencies(); + } } -function buildSdk(testRunId: string) { +function buildNodeSdk(testRunId: string) { console.log("Building SDK..."); process.chdir(path.join(DIR, "..")); // go up to root @@ -46,6 +59,60 @@ function buildSdk(testRunId: string) { process.chdir(DIR); // go back to integration_test } +function buildPythonSdk() { + console.log("Building SDK..."); + + process.chdir(path.join(DIR, "..")); // go up to root + + // remove existing build + + fs.rmSync("dist", { recursive: true, force: true }); + + // remove existing venv + + fs.rmSync("venv", { recursive: true, force: true }); + + // make virtual environment for building + + execSync("python3 -m venv venv", { stdio: "inherit" }); + + // build the package + + execSync( + "source venv/bin/activate && python -m pip install --upgrade build", + + { stdio: "inherit" } + ); + + execSync("source venv/bin/activate && python -m build -s", { + stdio: "inherit", + }); + + // move the generated tarball package to functions + + const generatedFile = fs + + .readdirSync("dist") + + .find((file) => file.match(/^firebase_functions-.*\.tar\.gz$/)); + + if (generatedFile) { + const targetPath = path.join( + "integration_tests", + + "functions", + + `firebase_functions.tar.gz` + ); + + fs.renameSync(path.join("dist", generatedFile), targetPath); + + console.log("SDK moved to", targetPath); + } + + process.chdir(DIR); // go back to integration_test +} + function createPackageJson(testRunId: string, nodeVersion: string, firebaseAdmin: string) { console.log("Creating package.json..."); const packageJsonTemplatePath = `${DIR}/package.json.template`; @@ -64,7 +131,33 @@ function createPackageJson(testRunId: string, nodeVersion: string, firebaseAdmin fs.writeFileSync(packageJsonPath, packageJsonContent); } -function installDependencies() { +function createRequirementsTxt(firebaseAdmin: string) { + console.log("Creating requirements.txt..."); + + const requirementsTemplatePath = `${DIR}/requirements.txt.template`; + + const requirementsPath = `${DIR}/functions/requirements.txt`; + + fs.copyFileSync(requirementsTemplatePath, requirementsPath); + + let requirementsContent = fs.readFileSync(requirementsPath, "utf8"); + + requirementsContent = requirementsContent.replace( + /__LOCAL_FIREBASE_FUNCTIONS__/g, + + `firebase_functions.tar.gz` + ); + + requirementsContent = requirementsContent.replace( + /__FIREBASE_ADMIN__/g, + + firebaseAdmin + ); + + fs.writeFileSync(requirementsPath, requirementsContent); +} + +function installNodeDependencies() { console.log("Installing dependencies..."); const functionsDir = "functions"; process.chdir(functionsDir); // go to functions @@ -78,7 +171,29 @@ function installDependencies() { process.chdir("../"); // go back to integration_test } -function buildFunctions() { +function installPythonDependencies() { + console.log("Installing dependencies..."); + + const functionsDir = "functions"; + + process.chdir(functionsDir); // go to functions + + const venvPath = path.join("venv"); + + if (fs.existsSync(venvPath)) { + execSync(`rm -rf ${venvPath}`, { stdio: "inherit" }); + } + + execSync("python3 -m venv venv", { stdio: "inherit" }); + + execSync("source venv/bin/activate && python3 -m pip install -r requirements.txt", { + stdio: "inherit", + }); + + process.chdir("../"); // go back to integration_test +} + +function buildNodeFunctions() { console.log("Building functions..."); process.chdir(path.join(DIR, "functions")); // go to functions diff --git a/integration_test/tests/firebaseSetup.ts b/integration_test/tests/firebaseSetup.ts index d6c898f2a..89d43d339 100644 --- a/integration_test/tests/firebaseSetup.ts +++ b/integration_test/tests/firebaseSetup.ts @@ -1,5 +1,4 @@ import * as admin from "firebase-admin"; -import { cert } from "firebase-admin/app"; /** * Initializes Firebase Admin SDK. @@ -7,18 +6,17 @@ import { cert } from "firebase-admin/app"; export async function initializeFirebase(): Promise { if (admin.apps.length === 0) { try { - const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; - if (!serviceAccountPath) { - throw new Error("Environment configured incorrectly."); - } - const serviceAccount = await import(serviceAccountPath); - const app = admin.initializeApp({ - credential: cert(serviceAccount), + // const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; + // if (!serviceAccountPath) { + // throw new Error("Environment configured incorrectly."); + // } + // const serviceAccount = await import(serviceAccountPath); + return admin.initializeApp({ + credential: admin.credential.applicationDefault(), databaseURL: process.env.DATABASE_URL, storageBucket: process.env.STORAGE_BUCKET, projectId: process.env.PROJECT_ID, }); - return app; } catch (error) { console.error("Error initializing Firebase:", error); } diff --git a/integration_test/tests/utils.ts b/integration_test/tests/utils.ts index 6750852cd..bbe94a693 100644 --- a/integration_test/tests/utils.ts +++ b/integration_test/tests/utils.ts @@ -155,3 +155,27 @@ export async function createTask( throw new Error("Unable to create task"); } } + +export async function retry(fn: () => Promise, maxReties: number = 10): Promise { + let count = 0; + let lastError: Error | undefined; + + while (count < maxReties) { + try { + const result = await fn(); + if (result) { + return result; + } + } catch (e) { + lastError = e; + } + await timeout(5000); + count++; + } + + if (lastError) { + throw lastError; + } + + throw new Error("Max retries exceeded"); +} diff --git a/integration_test/tests/v1/auth.test.ts b/integration_test/tests/v1/auth.test.ts index 277df3d51..c615cb94f 100644 --- a/integration_test/tests/v1/auth.test.ts +++ b/integration_test/tests/v1/auth.test.ts @@ -1,9 +1,9 @@ -import admin from "firebase-admin"; -import { timeout } from "../utils"; -import { initializeFirebase } from "../firebaseSetup"; +import * as admin from "firebase-admin"; import { UserRecord } from "firebase-admin/lib/auth/user-record"; import { initializeApp } from "firebase/app"; -import { getAuth, createUserWithEmailAndPassword, UserCredential } from "firebase/auth"; +import { createUserWithEmailAndPassword, getAuth, UserCredential } from "firebase/auth"; +import { initializeFirebase } from "../firebaseSetup"; +import { retry } from "../utils"; describe("Firebase Auth (v1)", () => { let userIds: string[] = []; @@ -49,21 +49,16 @@ describe("Firebase Auth (v1)", () => { displayName: `${testId}`, }); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("authUserOnCreateTests") - .doc(userRecord.uid) - .get(); - - loggedContext = logSnapshot.data(); + loggedContext = await retry(() => + admin + .firestore() + .collection("authUserOnCreateTests") + .doc(userRecord.uid) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); userIds.push(userRecord.uid); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } }); afterAll(async () => { @@ -124,7 +119,6 @@ describe("Firebase Auth (v1)", () => { describe("user onDelete trigger", () => { let userRecord: UserRecord; - let logSnapshot; let loggedContext: admin.firestore.DocumentData | undefined; beforeAll(async () => { @@ -136,20 +130,16 @@ describe("Firebase Auth (v1)", () => { await admin.auth().deleteUser(userRecord.uid); - await timeout(20000); - - logSnapshot = await admin - .firestore() - .collection("authUserOnDeleteTests") - .doc(userRecord.uid) - .get(); - loggedContext = logSnapshot.data(); + loggedContext = await retry(() => + admin + .firestore() + .collection("authUserOnDeleteTests") + .doc(userRecord.uid) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); userIds.push(userRecord.uid); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } }); it("should have a project as resource", () => { @@ -192,21 +182,16 @@ describe("Firebase Auth (v1)", () => { "secret" ); - await timeout(15000); - - const logSnapshot = await admin - .firestore() - .collection("authBeforeCreateTests") - .doc(userRecord.user.uid) - .get(); - - loggedContext = logSnapshot.data(); + loggedContext = await retry(() => + admin + .firestore() + .collection("authBeforeCreateTests") + .doc(userRecord.user.uid) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); userIds.push(userRecord.user.uid); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } }); afterAll(async () => { @@ -243,15 +228,14 @@ describe("Firebase Auth (v1)", () => { "secret" ); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("authBeforeSignInTests") - .doc(userRecord.user.uid) - .get(); - - loggedContext = logSnapshot.data(); + loggedContext = await retry(() => + admin + .firestore() + .collection("authBeforeSignInTests") + .doc(userRecord.user.uid) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); userIds.push(userRecord.user.uid); diff --git a/integration_test/tests/v1/database.test.ts b/integration_test/tests/v1/database.test.ts index 0f767dc0d..35f05d948 100644 --- a/integration_test/tests/v1/database.test.ts +++ b/integration_test/tests/v1/database.test.ts @@ -1,5 +1,5 @@ -import admin from "firebase-admin"; -import { timeout } from "../utils"; +import * as admin from "firebase-admin"; +import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; import { Reference } from "@firebase/database-types"; @@ -53,11 +53,7 @@ describe("Firebase Database (v1)", () => { beforeAll(async () => { ref = await setupRef(`dbTests/${testId}/start`); - await timeout(20000); - loggedContext = await getLoggedContext("databaseRefOnCreateTests", testId); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => getLoggedContext("databaseRefOnCreateTests", testId)); }); afterAll(async () => { @@ -123,11 +119,7 @@ describe("Firebase Database (v1)", () => { beforeAll(async () => { ref = await setupRef(`dbTests/${testId}/start`); await ref.remove(); - await timeout(20000); - loggedContext = await getLoggedContext("databaseRefOnDeleteTests", testId); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => getLoggedContext("databaseRefOnDeleteTests", testId)); }); it("should not have event.app", () => { @@ -180,11 +172,7 @@ describe("Firebase Database (v1)", () => { beforeAll(async () => { ref = await setupRef(`dbTests/${testId}/start`); await ref.update({ updated: true }); - await timeout(20000); - loggedContext = await getLoggedContext("databaseRefOnUpdateTests", testId); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => getLoggedContext("databaseRefOnUpdateTests", testId)); }); afterAll(async () => { @@ -255,13 +243,7 @@ describe("Firebase Database (v1)", () => { beforeAll(async () => { ref = await setupRef(`dbTests/${testId}/start`); - await timeout(20000); - - loggedContext = await getLoggedContext("databaseRefOnWriteTests", testId); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => getLoggedContext("databaseRefOnWriteTests", testId)); }); afterAll(async () => { diff --git a/integration_test/tests/v1/firestore.test.ts b/integration_test/tests/v1/firestore.test.ts index a986523b2..17622fd43 100644 --- a/integration_test/tests/v1/firestore.test.ts +++ b/integration_test/tests/v1/firestore.test.ts @@ -1,6 +1,6 @@ -import admin from "firebase-admin"; -import { timeout } from "../utils"; +import * as admin from "firebase-admin"; import { initializeFirebase } from "../firebaseSetup"; +import { retry } from "../utils"; describe("Cloud Firestore (v1)", () => { const projectId = process.env.PROJECT_ID; @@ -31,18 +31,14 @@ describe("Cloud Firestore (v1)", () => { await docRef.set({ test: testId }); dataSnapshot = await docRef.get(); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("firestoreDocumentOnCreateTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreDocumentOnCreateTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); afterAll(async () => { @@ -93,21 +89,17 @@ describe("Cloud Firestore (v1)", () => { await docRef.delete(); - await timeout(20000); - // Refresh snapshot dataSnapshot = await docRef.get(); - const logSnapshot = await admin - .firestore() - .collection("firestoreDocumentOnDeleteTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreDocumentOnDeleteTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); afterAll(async () => { @@ -153,21 +145,17 @@ describe("Cloud Firestore (v1)", () => { await docRef.update({ test: testId }); - await timeout(20000); - // Refresh snapshot dataSnapshot = await docRef.get(); - const logSnapshot = await admin - .firestore() - .collection("firestoreDocumentOnUpdateTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreDocumentOnUpdateTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); afterAll(async () => { @@ -211,18 +199,14 @@ describe("Cloud Firestore (v1)", () => { await docRef.set({ test: testId }); dataSnapshot = await docRef.get(); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("firestoreDocumentOnWriteTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreDocumentOnWriteTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); afterAll(async () => { diff --git a/integration_test/tests/v1/pubsub.test.ts b/integration_test/tests/v1/pubsub.test.ts index af1a5f29b..aecc71835 100644 --- a/integration_test/tests/v1/pubsub.test.ts +++ b/integration_test/tests/v1/pubsub.test.ts @@ -1,7 +1,7 @@ -import admin from "firebase-admin"; -import { timeout } from "../utils"; import { PubSub } from "@google-cloud/pubsub"; +import * as admin from "firebase-admin"; import { initializeFirebase } from "../firebaseSetup"; +import { retry } from "../utils"; describe("Pub/Sub (v1)", () => { const projectId = process.env.PROJECT_ID; @@ -35,17 +35,14 @@ describe("Pub/Sub (v1)", () => { await topic.publish(Buffer.from(JSON.stringify({ testId }))); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("pubsubOnPublishTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("pubsubOnPublishTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should have a topic as resource", () => { @@ -96,14 +93,14 @@ describe("Pub/Sub (v1)", () => { await pubsub.topic(topicName).publish(message); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("pubsubScheduleTests") - .doc(topicName) - .get(); - loggedContext = logSnapshot.data(); + loggedContext = await retry(() => + admin + .firestore() + .collection("pubsubScheduleTests") + .doc(topicName) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); if (!loggedContext) { throw new Error("loggedContext is undefined"); } diff --git a/integration_test/tests/v1/remoteConfig.test.ts b/integration_test/tests/v1/remoteConfig.test.ts index c05bb5da1..fde362ee4 100644 --- a/integration_test/tests/v1/remoteConfig.test.ts +++ b/integration_test/tests/v1/remoteConfig.test.ts @@ -1,5 +1,5 @@ import admin from "firebase-admin"; -import { timeout } from "../utils"; +import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; import fetch from "node-fetch"; @@ -40,16 +40,14 @@ describe("Firebase Remote Config (v1)", () => { if (!resp.ok) { throw new Error(resp.statusText); } - await timeout(20000); - const logSnapshot = await admin - .firestore() - .collection("remoteConfigOnUpdateTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("remoteConfigOnUpdateTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should have refs resources", () => diff --git a/integration_test/tests/v1/storage.test.ts b/integration_test/tests/v1/storage.test.ts index 4d8e251c6..159e9e317 100644 --- a/integration_test/tests/v1/storage.test.ts +++ b/integration_test/tests/v1/storage.test.ts @@ -1,5 +1,5 @@ import * as admin from "firebase-admin"; -import { timeout } from "../utils"; +import { retry, timeout } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { @@ -29,7 +29,8 @@ describe("Firebase Storage", () => { await admin.firestore().collection("storageOnMetadataUpdateTests").doc(testId).delete(); }); - describe("object onFinalize trigger", () => { + // FIXME: Re-enable after fix + describe.skip("object onFinalize trigger", () => { let loggedContext: admin.firestore.DocumentData | undefined; beforeAll(async () => { @@ -38,16 +39,14 @@ describe("Firebase Storage", () => { await uploadBufferToFirebase(buffer, testId + ".txt"); - await timeout(20000); - const logSnapshot = await admin - .firestore() - .collection("storageOnFinalizeTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("storageOnFinalizeTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); afterAll(async () => { @@ -79,7 +78,8 @@ describe("Firebase Storage", () => { }); }); - describe("object onDelete trigger", () => { + // FIXME: Re-enable after fix + describe.skip("object onDelete trigger", () => { let loggedContext: admin.firestore.DocumentData | undefined; beforeAll(async () => { @@ -96,17 +96,14 @@ describe("Firebase Storage", () => { .file(testId + ".txt"); await file.delete(); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("storageOnDeleteTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + const loggedContext = await retry(() => + admin + .firestore() + .collection("storageOnDeleteTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should not have event.app", () => { @@ -142,17 +139,14 @@ describe("Firebase Storage", () => { .file(testId + ".txt"); await file.setMetadata({ contentType: "application/json" }); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("storageOnMetadataUpdateTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("storageOnMetadataUpdateTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); afterAll(async () => { diff --git a/integration_test/tests/v1/tasks.test.ts b/integration_test/tests/v1/tasks.test.ts index 2b985ba59..3677adf51 100644 --- a/integration_test/tests/v1/tasks.test.ts +++ b/integration_test/tests/v1/tasks.test.ts @@ -1,6 +1,6 @@ import * as admin from "firebase-admin"; import { initializeFirebase } from "../firebaseSetup"; -import { createTask, timeout } from "../utils"; +import { createTask, retry } from "../utils"; describe("Cloud Tasks (v1)", () => { const region = process.env.REGION; @@ -27,16 +27,14 @@ describe("Cloud Tasks (v1)", () => { const url = `https://${region}-${projectId}.cloudfunctions.net/${testId}-v1-tasksOnDispatchTests`; await createTask(projectId, queueName, region, url, { data: { testId } }); - await timeout(20000); - const logSnapshot = await admin - .firestore() - .collection("tasksOnDispatchTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("tasksOnDispatchTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should have correct event id", () => { diff --git a/integration_test/tests/v1/testLab.test.ts b/integration_test/tests/v1/testLab.test.ts index b6a7e5d07..dc042ac4b 100644 --- a/integration_test/tests/v1/testLab.test.ts +++ b/integration_test/tests/v1/testLab.test.ts @@ -1,5 +1,5 @@ import admin from "firebase-admin"; -import { startTestRun, timeout } from "../utils"; +import { retry, startTestRun } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; describe("TestLab (v1)", () => { @@ -24,16 +24,15 @@ describe("TestLab (v1)", () => { beforeAll(async () => { const accessToken = await admin.credential.applicationDefault().getAccessToken(); await startTestRun(projectId, testId, accessToken.access_token); - await timeout(20000); - const logSnapshot = await admin - .firestore() - .collection("testLabOnCompleteTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + + loggedContext = await retry(() => + admin + .firestore() + .collection("testLabOnCompleteTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should have eventId", () => { diff --git a/integration_test/tests/v2/database.test.ts b/integration_test/tests/v2/database.test.ts index 79b9cd521..c36e54bf7 100644 --- a/integration_test/tests/v2/database.test.ts +++ b/integration_test/tests/v2/database.test.ts @@ -1,5 +1,5 @@ import admin from "firebase-admin"; -import { timeout } from "../utils"; +import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; import { Reference } from "@firebase/database-types"; @@ -38,13 +38,15 @@ describe("Firebase Database (v2)", () => { } } - function getLoggedContext(collectionName: string, testId: string) { - return admin - .firestore() - .collection(collectionName) - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()); + async function getLoggedContext(collectionName: string, testId: string) { + return retry(() => + admin + .firestore() + .collection(collectionName) + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); } describe("created trigger", () => { @@ -53,11 +55,7 @@ describe("Firebase Database (v2)", () => { beforeAll(async () => { ref = await setupRef(`databaseCreatedTests/${testId}/start`); - await timeout(20000); loggedContext = await getLoggedContext("databaseCreatedTests", testId); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } }); afterAll(async () => { @@ -97,11 +95,7 @@ describe("Firebase Database (v2)", () => { beforeAll(async () => { ref = await setupRef(`databaseDeletedTests/${testId}/start`); await teardownRef(ref); - await timeout(20000); loggedContext = await getLoggedContext("databaseDeletedTests", testId); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } }); it("should have a correct ref url", () => { @@ -128,11 +122,7 @@ describe("Firebase Database (v2)", () => { beforeAll(async () => { ref = await setupRef(`databaseUpdatedTests/${testId}/start`); await ref.update({ updated: true }); - await timeout(20000); loggedContext = await getLoggedContext("databaseUpdatedTests", testId); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } }); afterAll(async () => { @@ -176,11 +166,7 @@ describe("Firebase Database (v2)", () => { beforeAll(async () => { ref = await setupRef(`databaseWrittenTests/${testId}/start`); - await timeout(20000); loggedContext = await getLoggedContext("databaseWrittenTests", testId); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } }); afterAll(async () => { diff --git a/integration_test/tests/v2/eventarc.test.ts b/integration_test/tests/v2/eventarc.test.ts index de1ab3b08..d11901aec 100644 --- a/integration_test/tests/v2/eventarc.test.ts +++ b/integration_test/tests/v2/eventarc.test.ts @@ -1,7 +1,7 @@ import admin from "firebase-admin"; import { initializeFirebase } from "../firebaseSetup"; import { CloudEvent, getEventarc } from "firebase-admin/eventarc"; -import { timeout } from "../utils"; +import { retry } from "../utils"; describe("Eventarc (v2)", () => { const projectId = process.env.PROJECT_ID; @@ -35,18 +35,14 @@ describe("Eventarc (v2)", () => { }; await getEventarc().channel(`locations/${region}/channels/firebase`).publish(cloudEvent); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("eventarcOnCustomEventPublishedTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("eventarcOnCustomEventPublishedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should have well-formed source", () => { diff --git a/integration_test/tests/v2/firestore.test.ts b/integration_test/tests/v2/firestore.test.ts index 7d2efac5e..47d6d7ee6 100644 --- a/integration_test/tests/v2/firestore.test.ts +++ b/integration_test/tests/v2/firestore.test.ts @@ -1,5 +1,5 @@ import admin from "firebase-admin"; -import { timeout } from "../utils"; +import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; describe("Cloud Firestore (v2)", () => { @@ -31,18 +31,14 @@ describe("Cloud Firestore (v2)", () => { await docRef.set({ test: testId }); dataSnapshot = await docRef.get(); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("firestoreOnDocumentCreatedTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreOnDocumentCreatedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should not have event.app", () => { @@ -89,21 +85,17 @@ describe("Cloud Firestore (v2)", () => { await docRef.delete(); - await timeout(20000); - // Refresh snapshot dataSnapshot = await docRef.get(); - const logSnapshot = await admin - .firestore() - .collection("firestoreOnDocumentDeletedTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreOnDocumentDeletedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should not have event.app", () => { @@ -145,21 +137,17 @@ describe("Cloud Firestore (v2)", () => { await docRef.update({ test: testId }); - await timeout(20000); - // Refresh snapshot dataSnapshot = await docRef.get(); - const logSnapshot = await admin - .firestore() - .collection("firestoreOnDocumentUpdatedTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreOnDocumentUpdatedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should not have event.app", () => { @@ -199,18 +187,14 @@ describe("Cloud Firestore (v2)", () => { await docRef.set({ test: testId }); dataSnapshot = await docRef.get(); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("firestoreOnDocumentWrittenTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreOnDocumentWrittenTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should not have event.app", () => { diff --git a/integration_test/tests/v2/identity.test.ts b/integration_test/tests/v2/identity.test.ts index 760a57430..711ab735b 100644 --- a/integration_test/tests/v2/identity.test.ts +++ b/integration_test/tests/v2/identity.test.ts @@ -1,5 +1,5 @@ import admin from "firebase-admin"; -import { timeout } from "../utils"; +import { retry } from "../utils"; import { initializeApp } from "firebase/app"; import { initializeFirebase } from "../firebaseSetup"; import { getAuth, createUserWithEmailAndPassword, UserCredential } from "firebase/auth"; @@ -49,19 +49,14 @@ describe("Firebase Identity (v2)", () => { userIds.push(userRecord.user.uid); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("identityBeforeUserCreatedTests") - .doc(userRecord.user.uid) - .get(); - - loggedContext = logSnapshot.data(); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("identityBeforeUserCreatedTests") + .doc(userRecord.user.uid) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); afterAll(async () => { @@ -100,19 +95,14 @@ describe("Firebase Identity (v2)", () => { userIds.push(userRecord.user.uid); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("identityBeforeUserSignedInTests") - .doc(userRecord.user.uid) - .get(); - - loggedContext = logSnapshot.data(); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("identityBeforeUserSignedInTests") + .doc(userRecord.user.uid) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); afterAll(async () => { diff --git a/integration_test/tests/v2/pubsub.test.ts b/integration_test/tests/v2/pubsub.test.ts index 05fd00b18..396d7219f 100644 --- a/integration_test/tests/v2/pubsub.test.ts +++ b/integration_test/tests/v2/pubsub.test.ts @@ -1,5 +1,5 @@ import admin from "firebase-admin"; -import { timeout } from "../utils"; +import { retry, timeout } from "../utils"; import { PubSub } from "@google-cloud/pubsub"; import { initializeFirebase } from "../firebaseSetup"; @@ -33,17 +33,14 @@ describe("Pub/Sub (v2)", () => { await topic.publish(Buffer.from(JSON.stringify({ testId }))); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("pubsubOnMessagePublishedTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("pubsubOnMessagePublishedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should have a topic as source", () => { diff --git a/integration_test/tests/v2/remoteConfig.test.ts b/integration_test/tests/v2/remoteConfig.test.ts index 25a97147b..b04c498fe 100644 --- a/integration_test/tests/v2/remoteConfig.test.ts +++ b/integration_test/tests/v2/remoteConfig.test.ts @@ -1,5 +1,5 @@ import admin from "firebase-admin"; -import { timeout } from "../utils"; +import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; import fetch from "node-fetch"; @@ -40,16 +40,15 @@ describe("Firebase Remote Config (v2)", () => { if (!resp.ok) { throw new Error(resp.statusText); } - await timeout(20000); - const logSnapshot = await admin - .firestore() - .collection("remoteConfigOnConfigUpdatedTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + + loggedContext = await retry(() => + admin + .firestore() + .collection("remoteConfigOnConfigUpdatedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should have the right event type", () => { diff --git a/integration_test/tests/v2/scheduler.test.ts b/integration_test/tests/v2/scheduler.test.ts index c27275c3f..1ed110b83 100644 --- a/integration_test/tests/v2/scheduler.test.ts +++ b/integration_test/tests/v2/scheduler.test.ts @@ -1,5 +1,5 @@ import admin from "firebase-admin"; -import { timeout } from "../utils"; +import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; describe("Scheduler", () => { @@ -39,18 +39,14 @@ describe("Scheduler", () => { throw new Error(`Failed request with status ${response.status}!`); } - await timeout(15000); - - const logSnapshot = await admin - .firestore() - .collection("schedulerOnScheduleV2Tests") - .doc(jobName) - .get(); - loggedContext = logSnapshot.data(); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("schedulerOnScheduleV2Tests") + .doc(jobName) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should trigger when the scheduler fires", () => { diff --git a/integration_test/tests/v2/storage.test.ts b/integration_test/tests/v2/storage.test.ts index 4280497c6..341b6ea7d 100644 --- a/integration_test/tests/v2/storage.test.ts +++ b/integration_test/tests/v2/storage.test.ts @@ -1,6 +1,6 @@ import * as admin from "firebase-admin"; -import { timeout } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; +import { retry, timeout } from "../utils"; async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { const bucket = admin.storage().bucket(); @@ -39,16 +39,14 @@ describe("Firebase Storage (v2)", () => { await uploadBufferToFirebase(buffer, testId + ".txt"); - await timeout(20000); - const logSnapshot = await admin - .firestore() - .collection("storageOnObjectFinalizedTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("storageOnObjectFinalizedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); afterAll(async () => { @@ -93,17 +91,14 @@ describe("Firebase Storage (v2)", () => { .file(testId + ".txt"); await file.delete(); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("storageOnObjectDeletedTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("storageOnObjectDeletedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should have the right event type", () => { @@ -135,17 +130,14 @@ describe("Firebase Storage (v2)", () => { .file(testId + ".txt"); await file.setMetadata({ contentType: "application/json" }); - await timeout(20000); - - const logSnapshot = await admin - .firestore() - .collection("storageOnObjectMetadataUpdatedTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + loggedContext = await retry(() => + admin + .firestore() + .collection("storageOnObjectMetadataUpdatedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); afterAll(async () => { diff --git a/integration_test/tests/v2/tasks.test.ts b/integration_test/tests/v2/tasks.test.ts index cb3d9954a..8384735c8 100644 --- a/integration_test/tests/v2/tasks.test.ts +++ b/integration_test/tests/v2/tasks.test.ts @@ -1,6 +1,6 @@ import * as admin from "firebase-admin"; import { initializeFirebase } from "../firebaseSetup"; -import { createTask, timeout } from "../utils"; +import { createTask, retry } from "../utils"; describe("Cloud Tasks (v2)", () => { const region = process.env.REGION; @@ -26,16 +26,15 @@ describe("Cloud Tasks (v2)", () => { beforeAll(async () => { const url = `https://${region}-${projectId}.cloudfunctions.net/${testId}-v2-tasksOnTaskDispatchedTests`; await createTask(projectId, queueName, region, url, { data: { testId } }); - await timeout(20000); - const logSnapshot = await admin - .firestore() - .collection("tasksOnTaskDispatchedTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + + loggedContext = await retry(() => + admin + .firestore() + .collection("tasksOnTaskDispatchedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should have correct event id", () => { diff --git a/integration_test/tests/v2/testLab.test.ts b/integration_test/tests/v2/testLab.test.ts index 58a6c8149..f9b5b5618 100644 --- a/integration_test/tests/v2/testLab.test.ts +++ b/integration_test/tests/v2/testLab.test.ts @@ -1,5 +1,5 @@ import admin from "firebase-admin"; -import { startTestRun, timeout } from "../utils"; +import { retry, startTestRun } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; describe("TestLab (v2)", () => { @@ -24,16 +24,15 @@ describe("TestLab (v2)", () => { beforeAll(async () => { const accessToken = await admin.credential.applicationDefault().getAccessToken(); await startTestRun(projectId, testId, accessToken.access_token); - await timeout(20000); - const logSnapshot = await admin - .firestore() - .collection("testLabOnTestMatrixCompletedTests") - .doc(testId) - .get(); - loggedContext = logSnapshot.data(); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } + + loggedContext = await retry(() => + admin + .firestore() + .collection("testLabOnTestMatrixCompletedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); }); it("should have event id", () => { diff --git a/integration_test/tsconfig.build.json b/integration_test/tsconfig.build.json new file mode 100644 index 000000000..0aa0e8b37 --- /dev/null +++ b/integration_test/tsconfig.build.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "es2020", + "outDir": "./dist", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node" + }, + "include": ["**/*.ts"], + "exclude": ["node_modules", "functions/*", "tests/*"] +} diff --git a/integration_test/tsconfig.json b/integration_test/tsconfig.json index 0aa0e8b37..3c00e953d 100644 --- a/integration_test/tsconfig.json +++ b/integration_test/tsconfig.json @@ -1,14 +1,8 @@ { + "extends": "./tsconfig.build.json", "compilerOptions": { - "target": "es2020", - "module": "es2020", - "outDir": "./dist", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "moduleResolution": "node" + "module": "commonjs", + "resolveJsonModule": true }, - "include": ["**/*.ts"], - "exclude": ["node_modules", "functions/*", "tests/*"] + "include": ["tests/**/*.test.ts"] } diff --git a/integration_test/tsconfig.test.json b/integration_test/tsconfig.test.json deleted file mode 100644 index 681998ce1..000000000 --- a/integration_test/tsconfig.test.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "module": "commonjs", - "resolveJsonModule": true - }, - "include": ["**/*.test.ts"] -} diff --git a/integration_test/utils.ts b/integration_test/utils.ts new file mode 100644 index 000000000..f9d7ff173 --- /dev/null +++ b/integration_test/utils.ts @@ -0,0 +1,17 @@ +import path from "path"; +import fs from "fs"; + +export function loadEnv(): void { + try { + const envPath = path.resolve(process.cwd(), ".env"); + console.log("Loading .env file from", envPath); + const envFileContent = fs.readFileSync(envPath, "utf-8"); + envFileContent.split("\n").forEach((variable) => { + const [key, value] = variable.split("="); + if (key && value) process.env[key.trim()] = value.trim(); + }); + } catch (error: any) { + console.error("Error loading .env file:", error.message); + } +} + From b01e064dddc856b1a5cb045ece36a2504c2e2f89 Mon Sep 17 00:00:00 2001 From: exaby73 Date: Mon, 7 Oct 2024 11:36:30 +0530 Subject: [PATCH 07/25] wip(integration-tests): Update .env.example --- integration_test/.env.example | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/integration_test/.env.example b/integration_test/.env.example index 2eadc6dfd..e6caa79e7 100644 --- a/integration_test/.env.example +++ b/integration_test/.env.example @@ -1,12 +1,13 @@ +DEBUG=true +TEST_RUNTIME=node REGION=us-central1 PROJECT_ID= DATABASE_URL= STORAGE_BUCKET= NODE_VERSION=18 -FIREBASE_ADMIN=^12.3.0 +FIREBASE_ADMIN=^12.6.0 FIREBASE_APP_ID= FIREBASE_MEASUREMENT_ID= FIREBASE_AUTH_DOMAIN= FIREBASE_API_KEY= -GOOGLE_APPLICATION_CREDENTIALS=./serviceAccount.json GOOGLE_ANALYTICS_API_SECRET= From 2270dffdaa6976cd0ae22380aa56018bda620b47 Mon Sep 17 00:00:00 2001 From: exaby73 Date: Mon, 7 Oct 2024 11:36:45 +0530 Subject: [PATCH 08/25] wip(integration-tests): Remove FIRESTORE_REGION --- integration_test/functions/src/v2/firestore-tests.ts | 10 +++++----- integration_test/run.ts | 2 -- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/integration_test/functions/src/v2/firestore-tests.ts b/integration_test/functions/src/v2/firestore-tests.ts index e0a863dc2..4857cb896 100644 --- a/integration_test/functions/src/v2/firestore-tests.ts +++ b/integration_test/functions/src/v2/firestore-tests.ts @@ -7,12 +7,12 @@ import { onDocumentWritten, } from "firebase-functions/v2/firestore"; import { sanitizeData } from "../utils"; -import { FIRESTORE_REGION } from "../region"; +import { REGION } from "../region"; export const firestoreOnDocumentCreatedTests = onDocumentCreated( { document: "tests/{documentId}", - region: FIRESTORE_REGION, + region: REGION, timeoutSeconds: 540, }, async (event) => { @@ -37,7 +37,7 @@ export const firestoreOnDocumentCreatedTests = onDocumentCreated( export const firestoreOnDocumentDeletedTests = onDocumentDeleted( { document: "tests/{documentId}", - region: FIRESTORE_REGION, + region: REGION, timeoutSeconds: 540, }, async (event) => { @@ -62,7 +62,7 @@ export const firestoreOnDocumentDeletedTests = onDocumentDeleted( export const firestoreOnDocumentUpdatedTests = onDocumentUpdated( { document: "tests/{documentId}", - region: FIRESTORE_REGION, + region: REGION, timeoutSeconds: 540, }, async (event) => { @@ -87,7 +87,7 @@ export const firestoreOnDocumentUpdatedTests = onDocumentUpdated( export const firestoreOnDocumentWrittenTests = onDocumentWritten( { document: "tests/{documentId}", - region: FIRESTORE_REGION, + region: REGION, timeoutSeconds: 540, }, async (event) => { diff --git a/integration_test/run.ts b/integration_test/run.ts index e2bc8a4c1..102903cf4 100644 --- a/integration_test/run.ts +++ b/integration_test/run.ts @@ -23,7 +23,6 @@ let { GOOGLE_ANALYTICS_API_SECRET, TEST_RUNTIME, REGION = "us-central1", - FIRESTORE_REGION = "us-central1", STORAGE_REGION = "us-central1", } = process.env; const TEST_RUN_ID = `t${Date.now()}`; @@ -79,7 +78,6 @@ const env = { GCLOUD_PROJECT: config.projectId, FIREBASE_CONFIG: JSON.stringify(firebaseConfig), REGION, - FIRESTORE_REGION, STORAGE_REGION, }; From 7909e426be0876c756210b37ce43b1597920eebd Mon Sep 17 00:00:00 2001 From: exaby73 Date: Thu, 10 Oct 2024 17:10:49 +0530 Subject: [PATCH 09/25] remove(integration_test): Storage V1 delete tests --- integration_test/.env.example | 2 +- .../functions/src/v1/storage-tests.ts | 41 ++++++++++--------- integration_test/package.json.template | 1 - integration_test/tests/v1/storage.test.ts | 5 +-- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/integration_test/.env.example b/integration_test/.env.example index e6caa79e7..3063c9209 100644 --- a/integration_test/.env.example +++ b/integration_test/.env.example @@ -10,4 +10,4 @@ FIREBASE_APP_ID= FIREBASE_MEASUREMENT_ID= FIREBASE_AUTH_DOMAIN= FIREBASE_API_KEY= -GOOGLE_ANALYTICS_API_SECRET= +GOOGLE_ANALYTICS_API_SECRET= \ No newline at end of file diff --git a/integration_test/functions/src/v1/storage-tests.ts b/integration_test/functions/src/v1/storage-tests.ts index 21a75998d..ed909942b 100644 --- a/integration_test/functions/src/v1/storage-tests.ts +++ b/integration_test/functions/src/v1/storage-tests.ts @@ -3,6 +3,7 @@ import * as functions from "firebase-functions"; import { REGION } from "../region"; import { sanitizeData } from "../utils"; +// TODO: (b/372315689) Re-enable function once bug is fixed // export const storageOnDeleteTests: any = functions // .runWith({ // timeoutSeconds: 540, @@ -24,26 +25,26 @@ import { sanitizeData } from "../utils"; // .set(sanitizeData(context)); // }); -// export const storageOnFinalizeTests: any = functions -// .runWith({ -// timeoutSeconds: 540, -// }) -// .region(REGION) -// .storage.bucket() -// .object() -// .onFinalize(async (object, context) => { -// const testId = object.name?.split(".")[0]; -// if (!testId) { -// functions.logger.error("TestId not found for storage object finalize"); -// return; -// } -// -// await admin -// .firestore() -// .collection("storageOnFinalizeTests") -// .doc(testId) -// .set(sanitizeData(context)); -// }); +export const storageOnFinalizeTests: any = functions + .runWith({ + timeoutSeconds: 540, + }) + .region(REGION) + .storage.bucket() + .object() + .onFinalize(async (object, context) => { + const testId = object.name?.split(".")[0]; + if (!testId) { + functions.logger.error("TestId not found for storage object finalize"); + return; + } + + await admin + .firestore() + .collection("storageOnFinalizeTests") + .doc(testId) + .set(sanitizeData(context)); + }); export const storageOnMetadataUpdateTests: any = functions .runWith({ diff --git a/integration_test/package.json.template b/integration_test/package.json.template index 67e55974c..6e18f7437 100644 --- a/integration_test/package.json.template +++ b/integration_test/package.json.template @@ -10,7 +10,6 @@ }, "main": "lib/index.js", "devDependencies": { - "@types/node-fetch": "^2.6.1", "typescript": "^5.3.3" }, "engines": { diff --git a/integration_test/tests/v1/storage.test.ts b/integration_test/tests/v1/storage.test.ts index 159e9e317..7f74d41af 100644 --- a/integration_test/tests/v1/storage.test.ts +++ b/integration_test/tests/v1/storage.test.ts @@ -29,8 +29,7 @@ describe("Firebase Storage", () => { await admin.firestore().collection("storageOnMetadataUpdateTests").doc(testId).delete(); }); - // FIXME: Re-enable after fix - describe.skip("object onFinalize trigger", () => { + describe("object onFinalize trigger", () => { let loggedContext: admin.firestore.DocumentData | undefined; beforeAll(async () => { @@ -78,7 +77,7 @@ describe("Firebase Storage", () => { }); }); - // FIXME: Re-enable after fix + // TODO: (b/372315689) Re-enable function once bug is fixed describe.skip("object onDelete trigger", () => { let loggedContext: admin.firestore.DocumentData | undefined; From bbf153279cebe957cfce1a7a86960757082eb2f3 Mon Sep 17 00:00:00 2001 From: exaby73 Date: Thu, 10 Oct 2024 19:26:48 +0530 Subject: [PATCH 10/25] fix(integration_test): Multiple fixes for tests --- integration_test/jest.config.js | 7 +++++-- integration_test/package-lock.json | 11 ++++++++++ integration_test/package.json | 3 ++- integration_test/tests/utils.ts | 18 +++++++++++++---- integration_test/tests/v1/auth.test.ts | 20 +++++++++---------- integration_test/tests/v1/firestore.test.ts | 15 +++++++------- .../tests/v1/remoteConfig.test.ts | 2 +- integration_test/tests/v1/testLab.test.ts | 2 +- integration_test/tests/v2/database.test.ts | 2 +- integration_test/tests/v2/eventarc.test.ts | 2 +- integration_test/tests/v2/firestore.test.ts | 2 +- integration_test/tests/v2/identity.test.ts | 2 +- integration_test/tests/v2/pubsub.test.ts | 2 +- .../tests/v2/remoteConfig.test.ts | 2 +- integration_test/tests/v2/scheduler.test.ts | 2 +- integration_test/tests/v2/testLab.test.ts | 2 +- integration_test/tsconfig.build.json | 14 ------------- integration_test/tsconfig.json | 16 ++++++++++----- integration_test/tsconfig.test.json | 10 ++++++++++ 19 files changed, 81 insertions(+), 53 deletions(-) delete mode 100644 integration_test/tsconfig.build.json create mode 100644 integration_test/tsconfig.test.json diff --git a/integration_test/jest.config.js b/integration_test/jest.config.js index 7421b956c..4f9eb9e46 100644 --- a/integration_test/jest.config.js +++ b/integration_test/jest.config.js @@ -1,9 +1,12 @@ -export default { +/** @type {import('jest').Config} */ +const config = { preset: "ts-jest", testEnvironment: "node", testMatch: ["**/tests/**/*.test.ts"], - testTimeout: 30000, + testTimeout: 120_000, transform: { "^.+\\.(t|j)s$": ["ts-jest", { tsconfig: "tsconfig.test.json" }], }, }; + +export default config; diff --git a/integration_test/package-lock.json b/integration_test/package-lock.json index c417d2bb2..bcebe4e7e 100644 --- a/integration_test/package-lock.json +++ b/integration_test/package-lock.json @@ -17,6 +17,7 @@ "devDependencies": { "@types/jest": "^29.5.11", "@types/js-yaml": "^4.0.9", + "@types/node-fetch": "^2.6.11", "jest": "^29.7.0", "ts-jest": "^29.1.1" } @@ -2366,6 +2367,16 @@ "undici-types": "~6.19.2" } }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "dev": true, + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, "node_modules/@types/qs": { "version": "6.9.10", "license": "MIT" diff --git a/integration_test/package.json b/integration_test/package.json index 7b87c90a9..0de81843e 100644 --- a/integration_test/package.json +++ b/integration_test/package.json @@ -12,13 +12,14 @@ "node-fetch": "2" }, "scripts": { - "build": "tsc -p ./tsconfig.build.json", + "build": "tsc -p tsconfig.test.json", "test": "jest --detectOpenHandles", "start": "npm run build && node dist/run.js" }, "devDependencies": { "@types/jest": "^29.5.11", "@types/js-yaml": "^4.0.9", + "@types/node-fetch": "^2.6.11", "jest": "^29.7.0", "ts-jest": "^29.1.1" } diff --git a/integration_test/tests/utils.ts b/integration_test/tests/utils.ts index bbe94a693..19f695116 100644 --- a/integration_test/tests/utils.ts +++ b/integration_test/tests/utils.ts @@ -156,18 +156,28 @@ export async function createTask( } } -export async function retry(fn: () => Promise, maxReties: number = 10): Promise { +type RetryOptions = { maxRetries?: number; checkForUndefined?: boolean }; + +/** + * @template T + * @param {() => Promise} fn + * @param {RetryOptions | undefined} [options={ maxRetries: 10, checkForUndefined: true }] + * + * @returns {Promise} + */ +export async function retry(fn: () => Promise, options?: RetryOptions): Promise { let count = 0; let lastError: Error | undefined; + const { maxRetries = 20, checkForUndefined = true } = options ?? {}; - while (count < maxReties) { + while (count < maxRetries) { try { const result = await fn(); - if (result) { + if (!checkForUndefined || result) { return result; } } catch (e) { - lastError = e; + lastError = e as Error; } await timeout(5000); count++; diff --git a/integration_test/tests/v1/auth.test.ts b/integration_test/tests/v1/auth.test.ts index c615cb94f..3312198b6 100644 --- a/integration_test/tests/v1/auth.test.ts +++ b/integration_test/tests/v1/auth.test.ts @@ -1,5 +1,4 @@ import * as admin from "firebase-admin"; -import { UserRecord } from "firebase-admin/lib/auth/user-record"; import { initializeApp } from "firebase/app"; import { createUserWithEmailAndPassword, getAuth, UserCredential } from "firebase/auth"; import { initializeFirebase } from "../firebaseSetup"; @@ -39,7 +38,7 @@ describe("Firebase Auth (v1)", () => { }); describe("user onCreate trigger", () => { - let userRecord: UserRecord; + let userRecord: admin.auth.UserRecord; let loggedContext: admin.firestore.DocumentData | undefined; beforeAll(async () => { @@ -118,7 +117,7 @@ describe("Firebase Auth (v1)", () => { }); describe("user onDelete trigger", () => { - let userRecord: UserRecord; + let userRecord: admin.auth.UserRecord; let loggedContext: admin.firestore.DocumentData | undefined; beforeAll(async () => { @@ -130,13 +129,14 @@ describe("Firebase Auth (v1)", () => { await admin.auth().deleteUser(userRecord.uid); - loggedContext = await retry(() => - admin - .firestore() - .collection("authUserOnDeleteTests") - .doc(userRecord.uid) - .get() - .then((logSnapshot) => logSnapshot.data()) + loggedContext = await retry( + () => + admin + .firestore() + .collection("authUserOnDeleteTests") + .doc(userRecord.uid) + .get() + .then((logSnapshot) => logSnapshot.data()), ); userIds.push(userRecord.uid); diff --git a/integration_test/tests/v1/firestore.test.ts b/integration_test/tests/v1/firestore.test.ts index 17622fd43..1e3e77c40 100644 --- a/integration_test/tests/v1/firestore.test.ts +++ b/integration_test/tests/v1/firestore.test.ts @@ -199,13 +199,14 @@ describe("Cloud Firestore (v1)", () => { await docRef.set({ test: testId }); dataSnapshot = await docRef.get(); - loggedContext = await retry(() => - admin - .firestore() - .collection("firestoreDocumentOnWriteTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) + loggedContext = await retry( + () => + admin + .firestore() + .collection("firestoreDocumentOnWriteTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()), ); }); diff --git a/integration_test/tests/v1/remoteConfig.test.ts b/integration_test/tests/v1/remoteConfig.test.ts index fde362ee4..e2e06b404 100644 --- a/integration_test/tests/v1/remoteConfig.test.ts +++ b/integration_test/tests/v1/remoteConfig.test.ts @@ -1,4 +1,4 @@ -import admin from "firebase-admin"; +import * as admin from "firebase-admin"; import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; import fetch from "node-fetch"; diff --git a/integration_test/tests/v1/testLab.test.ts b/integration_test/tests/v1/testLab.test.ts index dc042ac4b..92a1cab52 100644 --- a/integration_test/tests/v1/testLab.test.ts +++ b/integration_test/tests/v1/testLab.test.ts @@ -1,4 +1,4 @@ -import admin from "firebase-admin"; +import * as admin from "firebase-admin"; import { retry, startTestRun } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; diff --git a/integration_test/tests/v2/database.test.ts b/integration_test/tests/v2/database.test.ts index c36e54bf7..557ad05cf 100644 --- a/integration_test/tests/v2/database.test.ts +++ b/integration_test/tests/v2/database.test.ts @@ -1,4 +1,4 @@ -import admin from "firebase-admin"; +import * as admin from "firebase-admin"; import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; import { Reference } from "@firebase/database-types"; diff --git a/integration_test/tests/v2/eventarc.test.ts b/integration_test/tests/v2/eventarc.test.ts index d11901aec..950f80ff5 100644 --- a/integration_test/tests/v2/eventarc.test.ts +++ b/integration_test/tests/v2/eventarc.test.ts @@ -1,4 +1,4 @@ -import admin from "firebase-admin"; +import * as admin from "firebase-admin"; import { initializeFirebase } from "../firebaseSetup"; import { CloudEvent, getEventarc } from "firebase-admin/eventarc"; import { retry } from "../utils"; diff --git a/integration_test/tests/v2/firestore.test.ts b/integration_test/tests/v2/firestore.test.ts index 47d6d7ee6..e982b89d4 100644 --- a/integration_test/tests/v2/firestore.test.ts +++ b/integration_test/tests/v2/firestore.test.ts @@ -1,4 +1,4 @@ -import admin from "firebase-admin"; +import * as admin from "firebase-admin"; import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; diff --git a/integration_test/tests/v2/identity.test.ts b/integration_test/tests/v2/identity.test.ts index 711ab735b..86edbd879 100644 --- a/integration_test/tests/v2/identity.test.ts +++ b/integration_test/tests/v2/identity.test.ts @@ -1,4 +1,4 @@ -import admin from "firebase-admin"; +import * as admin from "firebase-admin"; import { retry } from "../utils"; import { initializeApp } from "firebase/app"; import { initializeFirebase } from "../firebaseSetup"; diff --git a/integration_test/tests/v2/pubsub.test.ts b/integration_test/tests/v2/pubsub.test.ts index 396d7219f..6cba45cd1 100644 --- a/integration_test/tests/v2/pubsub.test.ts +++ b/integration_test/tests/v2/pubsub.test.ts @@ -1,4 +1,4 @@ -import admin from "firebase-admin"; +import * as admin from "firebase-admin"; import { retry, timeout } from "../utils"; import { PubSub } from "@google-cloud/pubsub"; import { initializeFirebase } from "../firebaseSetup"; diff --git a/integration_test/tests/v2/remoteConfig.test.ts b/integration_test/tests/v2/remoteConfig.test.ts index b04c498fe..4d17e3573 100644 --- a/integration_test/tests/v2/remoteConfig.test.ts +++ b/integration_test/tests/v2/remoteConfig.test.ts @@ -1,4 +1,4 @@ -import admin from "firebase-admin"; +import * as admin from "firebase-admin"; import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; import fetch from "node-fetch"; diff --git a/integration_test/tests/v2/scheduler.test.ts b/integration_test/tests/v2/scheduler.test.ts index 1ed110b83..0e81c3003 100644 --- a/integration_test/tests/v2/scheduler.test.ts +++ b/integration_test/tests/v2/scheduler.test.ts @@ -1,4 +1,4 @@ -import admin from "firebase-admin"; +import * as admin from "firebase-admin"; import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; diff --git a/integration_test/tests/v2/testLab.test.ts b/integration_test/tests/v2/testLab.test.ts index f9b5b5618..a2686156e 100644 --- a/integration_test/tests/v2/testLab.test.ts +++ b/integration_test/tests/v2/testLab.test.ts @@ -1,4 +1,4 @@ -import admin from "firebase-admin"; +import * as admin from "firebase-admin"; import { retry, startTestRun } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; diff --git a/integration_test/tsconfig.build.json b/integration_test/tsconfig.build.json deleted file mode 100644 index 0aa0e8b37..000000000 --- a/integration_test/tsconfig.build.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "compilerOptions": { - "target": "es2020", - "module": "es2020", - "outDir": "./dist", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "moduleResolution": "node" - }, - "include": ["**/*.ts"], - "exclude": ["node_modules", "functions/*", "tests/*"] -} diff --git a/integration_test/tsconfig.json b/integration_test/tsconfig.json index 3c00e953d..9e53c8d71 100644 --- a/integration_test/tsconfig.json +++ b/integration_test/tsconfig.json @@ -1,8 +1,14 @@ { - "extends": "./tsconfig.build.json", "compilerOptions": { - "module": "commonjs", - "resolveJsonModule": true + "target": "ES2020", + "module": "ES2020", + "outDir": "./dist", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node" }, - "include": ["tests/**/*.test.ts"] -} + "include": ["**/*.ts"], + "exclude": ["node_modules", "functions/*", "tests/*"] +} \ No newline at end of file diff --git a/integration_test/tsconfig.test.json b/integration_test/tsconfig.test.json new file mode 100644 index 000000000..e11b8b9bb --- /dev/null +++ b/integration_test/tsconfig.test.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "ES2020", + "moduleResolution": "Bundler", + "resolveJsonModule": true + }, + "include": ["**/*.ts"], + "exclude": ["node_modules", "functions/*"] +} \ No newline at end of file From ae15e04410157019b076e3a75f1fc95546656602 Mon Sep 17 00:00:00 2001 From: exaby73 Date: Thu, 31 Oct 2024 18:08:26 +0530 Subject: [PATCH 11/25] fix(integration_test): Use bash for source command --- cloudbuild.yaml | 9 ++++++--- integration_test/setup.ts | 11 +++-------- integration_test/tests/utils.ts | 7 ++++--- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/cloudbuild.yaml b/cloudbuild.yaml index b86f7b8a7..3a7d278c0 100644 --- a/cloudbuild.yaml +++ b/cloudbuild.yaml @@ -1,15 +1,18 @@ steps: - name: "node:18" - entrypoint: "npm" + id: "Install dependencies" dir: "integration_test" + entrypoint: "npm" args: ["install"] - name: "node:18" - entrypoint: "npx" + id: "Set Project ID" dir: "integration_test" + entrypoint: "npx" args: ["firebase", "use", "cf3-integration-tests-d7be6"] - name: "node:18" - entrypoint: "npm" + id: "Run tests" dir: "integration_test" + entrypoint: "npm" args: ["start"] options: diff --git a/integration_test/setup.ts b/integration_test/setup.ts index a00417f98..94f446ff3 100644 --- a/integration_test/setup.ts +++ b/integration_test/setup.ts @@ -81,11 +81,12 @@ function buildPythonSdk() { execSync( "source venv/bin/activate && python -m pip install --upgrade build", - { stdio: "inherit" } + { stdio: "inherit", shell: "bash" } ); execSync("source venv/bin/activate && python -m build -s", { stdio: "inherit", + shell: "bash", }); // move the generated tarball package to functions @@ -97,13 +98,7 @@ function buildPythonSdk() { .find((file) => file.match(/^firebase_functions-.*\.tar\.gz$/)); if (generatedFile) { - const targetPath = path.join( - "integration_tests", - - "functions", - - `firebase_functions.tar.gz` - ); + const targetPath = path.join("integration_tests", "functions", `firebase_functions.tar.gz`); fs.renameSync(path.join("dist", generatedFile), targetPath); diff --git a/integration_test/tests/utils.ts b/integration_test/tests/utils.ts index 19f695116..b807d181f 100644 --- a/integration_test/tests/utils.ts +++ b/integration_test/tests/utils.ts @@ -114,7 +114,7 @@ export async function createTask( payload: Record ) { const client = new CloudTasksClient(); - const queuePath = client.queuePath(project, location, queue); + // const queuePath = client.queuePath(project, location, queue); // try { // await client.getQueue({ name: queuePath }); // } catch (err: any) { @@ -169,10 +169,11 @@ export async function retry(fn: () => Promise, options?: RetryOptions): Pr let count = 0; let lastError: Error | undefined; const { maxRetries = 20, checkForUndefined = true } = options ?? {}; + let result: Awaited | null = null; while (count < maxRetries) { try { - const result = await fn(); + result = await fn(); if (!checkForUndefined || result) { return result; } @@ -187,5 +188,5 @@ export async function retry(fn: () => Promise, options?: RetryOptions): Pr throw lastError; } - throw new Error("Max retries exceeded"); + throw new Error(`Max retries exceeded: result = ${result}`); } From 28495ec9aaa3677d780b5ba0476fb15618aeb60a Mon Sep 17 00:00:00 2001 From: exaby73 Date: Thu, 31 Oct 2024 18:10:51 +0530 Subject: [PATCH 12/25] fix(integration_test): Rename integration_tests to integration_test --- integration_test/setup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration_test/setup.ts b/integration_test/setup.ts index 94f446ff3..3238d9710 100644 --- a/integration_test/setup.ts +++ b/integration_test/setup.ts @@ -98,7 +98,7 @@ function buildPythonSdk() { .find((file) => file.match(/^firebase_functions-.*\.tar\.gz$/)); if (generatedFile) { - const targetPath = path.join("integration_tests", "functions", `firebase_functions.tar.gz`); + const targetPath = path.join("integration_test", "functions", `firebase_functions.tar.gz`); fs.renameSync(path.join("dist", generatedFile), targetPath); From 747e0c6937a0987c8fa14014847e35c0c44a51e7 Mon Sep 17 00:00:00 2001 From: exaby73 Date: Thu, 31 Oct 2024 18:51:07 +0530 Subject: [PATCH 13/25] fix(integration_test): Use bash for missed source command --- integration_test/setup.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/integration_test/setup.ts b/integration_test/setup.ts index 3238d9710..dba7e8b6f 100644 --- a/integration_test/setup.ts +++ b/integration_test/setup.ts @@ -183,6 +183,7 @@ function installPythonDependencies() { execSync("source venv/bin/activate && python3 -m pip install -r requirements.txt", { stdio: "inherit", + shell: "bash", }); process.chdir("../"); // go back to integration_test From 8360ae8adf3a4b4f7dfa211f049fd1e99e224595 Mon Sep 17 00:00:00 2001 From: exaby73 Date: Thu, 31 Oct 2024 18:54:21 +0530 Subject: [PATCH 14/25] fix(integration_test): Runtime for Python --- integration_test/run.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration_test/run.ts b/integration_test/run.ts index 102903cf4..0b27b68d8 100644 --- a/integration_test/run.ts +++ b/integration_test/run.ts @@ -61,7 +61,7 @@ const config = { projectId: PROJECT_ID, projectDir: process.cwd(), sourceDir: `${process.cwd()}/functions`, - runtime: TEST_RUNTIME === "node" ? "nodejs18" : "python", + runtime: TEST_RUNTIME === "node" ? "nodejs18" : "python311", }; console.log("Firebase config created: "); From 32aeadf76ccd7032a48fd57654ed53d8203ddf24 Mon Sep 17 00:00:00 2001 From: exaby73 Date: Thu, 31 Oct 2024 19:05:01 +0530 Subject: [PATCH 15/25] fix(integration_test): Pass DEBUG to CLI env --- integration_test/database.rules.json | 14 ++++-------- integration_test/firebase.json | 3 +-- .../functions/src/v1/analytics-tests.ts | 8 ++++--- .../functions/src/v1/database-tests.ts | 12 +++++----- .../functions/src/v1/firestore-tests.ts | 18 +++++++-------- .../functions/src/v1/pubsub-tests.ts | 8 +++---- .../functions/src/v1/remoteConfig-tests.ts | 4 ++-- .../functions/src/v1/storage-tests.ts | 19 ++++++++++------ .../functions/src/v1/tasks-tests.ts | 12 +++++----- .../functions/src/v1/testLab-tests.ts | 22 ++++++++++++++----- integration_test/run.ts | 2 ++ integration_test/setup.ts | 3 --- 12 files changed, 67 insertions(+), 58 deletions(-) diff --git a/integration_test/database.rules.json b/integration_test/database.rules.json index 2ad59a69c..f54493dbd 100644 --- a/integration_test/database.rules.json +++ b/integration_test/database.rules.json @@ -1,13 +1,7 @@ { + /* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */ "rules": { - "dbTests": { - "$testId": { - "adminOnly": { - ".validate": false - } - } - }, - ".read": "auth != null", - ".write": true + ".read": false, + ".write": false } -} +} \ No newline at end of file diff --git a/integration_test/firebase.json b/integration_test/firebase.json index 9662aef03..5ab884ea2 100644 --- a/integration_test/firebase.json +++ b/integration_test/firebase.json @@ -8,7 +8,6 @@ }, "functions": { "source": "functions", - "codebase": "integration-tests", - "predeploy": ["npm --prefix \"$RESOURCE_DIR\" run build"] + "codebase": "integration-tests" } } diff --git a/integration_test/functions/src/v1/analytics-tests.ts b/integration_test/functions/src/v1/analytics-tests.ts index 1b7cc35ca..c902c8c0c 100644 --- a/integration_test/functions/src/v1/analytics-tests.ts +++ b/integration_test/functions/src/v1/analytics-tests.ts @@ -1,7 +1,9 @@ -import * as functions from "firebase-functions"; +import * as functions from "firebase-functions/v1"; import { REGION } from "../region"; -export const analyticsEventTests: any = functions +export const analyticsEventTests = functions .region(REGION) .analytics.event("in_app_purchase") - .onLog(async () => {}); + .onLog(async () => { + // Test function - intentionally empty + }); diff --git a/integration_test/functions/src/v1/database-tests.ts b/integration_test/functions/src/v1/database-tests.ts index 0bb65cd42..7ca41d046 100644 --- a/integration_test/functions/src/v1/database-tests.ts +++ b/integration_test/functions/src/v1/database-tests.ts @@ -1,9 +1,9 @@ import * as admin from "firebase-admin"; -import * as functions from "firebase-functions"; +import * as functions from "firebase-functions/v1"; import { REGION } from "../region"; import { sanitizeData } from "../utils"; -export const databaseRefOnCreateTests: any = functions +export const databaseRefOnCreateTests = functions .region(REGION) .database.ref("dbTests/{testId}/start") .onCreate(async (snapshot, context) => { @@ -21,7 +21,7 @@ export const databaseRefOnCreateTests: any = functions ); }); -export const databaseRefOnDeleteTests: any = functions +export const databaseRefOnDeleteTests = functions .region(REGION) .database.ref("dbTests/{testId}/start") .onDelete(async (snapshot, context) => { @@ -39,12 +39,12 @@ export const databaseRefOnDeleteTests: any = functions ); }); -export const databaseRefOnUpdateTests: any = functions +export const databaseRefOnUpdateTests = functions .region(REGION) .database.ref("dbTests/{testId}/start") .onUpdate(async (change, context) => { const testId = context.params.testId; - const data = change.after.val(); + const data = change.after.val() as unknown; await admin .firestore() @@ -59,7 +59,7 @@ export const databaseRefOnUpdateTests: any = functions ); }); -export const databaseRefOnWriteTests: any = functions +export const databaseRefOnWriteTests = functions .region(REGION) .database.ref("dbTests/{testId}/start") .onWrite(async (change, context) => { diff --git a/integration_test/functions/src/v1/firestore-tests.ts b/integration_test/functions/src/v1/firestore-tests.ts index a075f18aa..56a107937 100644 --- a/integration_test/functions/src/v1/firestore-tests.ts +++ b/integration_test/functions/src/v1/firestore-tests.ts @@ -1,15 +1,15 @@ import * as admin from "firebase-admin"; -import * as functions from "firebase-functions"; +import * as functions from "firebase-functions/v1"; import { REGION } from "../region"; import { sanitizeData } from "../utils"; -export const firestoreDocumentOnCreateTests: any = functions +export const firestoreDocumentOnCreateTests = functions .runWith({ timeoutSeconds: 540, }) .region(REGION) .firestore.document("tests/{testId}") - .onCreate(async (snapshot, context) => { + .onCreate(async (_snapshot, context) => { const testId = context.params.testId; await admin .firestore() @@ -18,13 +18,13 @@ export const firestoreDocumentOnCreateTests: any = functions .set(sanitizeData(context)); }); -export const firestoreDocumentOnDeleteTests: any = functions +export const firestoreDocumentOnDeleteTests = functions .runWith({ timeoutSeconds: 540, }) .region(REGION) .firestore.document("tests/{testId}") - .onDelete(async (snapshot, context) => { + .onDelete(async (_snapshot, context) => { const testId = context.params.testId; await admin .firestore() @@ -33,13 +33,13 @@ export const firestoreDocumentOnDeleteTests: any = functions .set(sanitizeData(context)); }); -export const firestoreDocumentOnUpdateTests: any = functions +export const firestoreDocumentOnUpdateTests = functions .runWith({ timeoutSeconds: 540, }) .region(REGION) .firestore.document("tests/{testId}") - .onUpdate(async (change, context) => { + .onUpdate(async (_change, context) => { const testId = context.params.testId; await admin .firestore() @@ -48,13 +48,13 @@ export const firestoreDocumentOnUpdateTests: any = functions .set(sanitizeData(context)); }); -export const firestoreDocumentOnWriteTests: any = functions +export const firestoreDocumentOnWriteTests = functions .runWith({ timeoutSeconds: 540, }) .region(REGION) .firestore.document("tests/{testId}") - .onWrite(async (change, context) => { + .onWrite(async (_change, context) => { const testId = context.params.testId; await admin .firestore() diff --git a/integration_test/functions/src/v1/pubsub-tests.ts b/integration_test/functions/src/v1/pubsub-tests.ts index 6bb556f0e..1ea56979e 100644 --- a/integration_test/functions/src/v1/pubsub-tests.ts +++ b/integration_test/functions/src/v1/pubsub-tests.ts @@ -1,13 +1,13 @@ import * as admin from "firebase-admin"; -import * as functions from "firebase-functions"; +import * as functions from "firebase-functions/v1"; import { REGION } from "../region"; import { sanitizeData } from "../utils"; -export const pubsubOnPublishTests: any = functions +export const pubsubOnPublishTests = functions .region(REGION) .pubsub.topic("pubsubTests") .onPublish(async (message, context) => { - let testId = message.json?.testId; + const testId = (message.json as { testId?: string })?.testId; await admin .firestore() .collection("pubsubOnPublishTests") @@ -20,7 +20,7 @@ export const pubsubOnPublishTests: any = functions ); }); -export const pubsubScheduleTests: any = functions +export const pubsubScheduleTests = functions .region(REGION) .pubsub.schedule("every 10 hours") // This is a dummy schedule, since we need to put a valid one in. // For the test, the job is triggered by the jobs:run api diff --git a/integration_test/functions/src/v1/remoteConfig-tests.ts b/integration_test/functions/src/v1/remoteConfig-tests.ts index 1418a5c97..9df0edcb9 100644 --- a/integration_test/functions/src/v1/remoteConfig-tests.ts +++ b/integration_test/functions/src/v1/remoteConfig-tests.ts @@ -1,9 +1,9 @@ -import * as functions from "firebase-functions"; +import * as functions from "firebase-functions/v1"; import * as admin from "firebase-admin"; import { REGION } from "../region"; import { sanitizeData } from "../utils"; -export const remoteConfigOnUpdateTests: any = functions +export const remoteConfigOnUpdateTests = functions .region(REGION) .remoteConfig.onUpdate(async (version, context) => { const testId = version.description; diff --git a/integration_test/functions/src/v1/storage-tests.ts b/integration_test/functions/src/v1/storage-tests.ts index ed909942b..4d9d1442d 100644 --- a/integration_test/functions/src/v1/storage-tests.ts +++ b/integration_test/functions/src/v1/storage-tests.ts @@ -1,5 +1,5 @@ import * as admin from "firebase-admin"; -import * as functions from "firebase-functions"; +import * as functions from "firebase-functions/v1"; import { REGION } from "../region"; import { sanitizeData } from "../utils"; @@ -25,19 +25,24 @@ import { sanitizeData } from "../utils"; // .set(sanitizeData(context)); // }); -export const storageOnFinalizeTests: any = functions +export const storageOnFinalizeTests = functions .runWith({ timeoutSeconds: 540, }) .region(REGION) .storage.bucket() .object() - .onFinalize(async (object, context) => { - const testId = object.name?.split(".")[0]; - if (!testId) { - functions.logger.error("TestId not found for storage object finalize"); + .onFinalize(async (object: unknown, context) => { + if (!object || typeof object !== "object" || !("name" in object)) { + functions.logger.error("Invalid object structure for storage object finalize"); + return; + } + const name = (object as { name: string }).name; + if (!name || typeof name !== "string") { + functions.logger.error("Invalid name property for storage object finalize"); return; } + const testId = name.split(".")[0]; await admin .firestore() @@ -46,7 +51,7 @@ export const storageOnFinalizeTests: any = functions .set(sanitizeData(context)); }); -export const storageOnMetadataUpdateTests: any = functions +export const storageOnMetadataUpdateTests = functions .runWith({ timeoutSeconds: 540, }) diff --git a/integration_test/functions/src/v1/tasks-tests.ts b/integration_test/functions/src/v1/tasks-tests.ts index d06dcd35e..6d1a0a8c2 100644 --- a/integration_test/functions/src/v1/tasks-tests.ts +++ b/integration_test/functions/src/v1/tasks-tests.ts @@ -1,20 +1,20 @@ import * as admin from "firebase-admin"; -import * as functions from "firebase-functions"; +import * as functions from "firebase-functions/v1"; import { REGION } from "../region"; import { sanitizeData } from "../utils"; -export const tasksOnDispatchTests: any = functions +export const tasksOnDispatchTests = functions .runWith({ timeoutSeconds: 540, }) .region(REGION) .tasks.taskQueue() - .onDispatch(async (data, context) => { - const testId = data.testId; - if (!testId) { - functions.logger.error("TestId not found for tasks onDispatch"); + .onDispatch(async (data: unknown, context) => { + if (!data || typeof data !== "object" || !("testId" in data)) { + functions.logger.error("Invalid data structure for tasks onDispatch"); return; } + const testId = (data as { testId: string }).testId; await admin .firestore() diff --git a/integration_test/functions/src/v1/testLab-tests.ts b/integration_test/functions/src/v1/testLab-tests.ts index 755136247..f25ba819f 100644 --- a/integration_test/functions/src/v1/testLab-tests.ts +++ b/integration_test/functions/src/v1/testLab-tests.ts @@ -1,20 +1,30 @@ import * as admin from "firebase-admin"; -import * as functions from "firebase-functions"; +import * as functions from "firebase-functions/v1"; import { REGION } from "../region"; import { sanitizeData } from "../utils"; -export const testLabOnCompleteTests: any = functions +export const testLabOnCompleteTests = functions .runWith({ timeoutSeconds: 540, }) .region(REGION) .testLab.testMatrix() - .onComplete(async (matrix, context) => { - const testId = matrix?.clientInfo?.details?.testId; - if (!testId) { - functions.logger.error("TestId not found for test matrix completion"); + .onComplete(async (matrix: unknown, context) => { + if (!matrix || typeof matrix !== "object" || !("clientInfo" in matrix)) { + functions.logger.error("Invalid matrix structure for test matrix completion"); return; } + const clientInfo = (matrix as { clientInfo: unknown }).clientInfo; + if (!clientInfo || typeof clientInfo !== "object" || !("details" in clientInfo)) { + functions.logger.error("Invalid clientInfo structure for test matrix completion"); + return; + } + const details = clientInfo.details; + if (!details || typeof details !== "object" || !("testId" in details)) { + functions.logger.error("Invalid details structure for test matrix completion"); + return; + } + const testId = details.testId as string; await admin .firestore() diff --git a/integration_test/run.ts b/integration_test/run.ts index 0b27b68d8..0759fff8e 100644 --- a/integration_test/run.ts +++ b/integration_test/run.ts @@ -11,6 +11,7 @@ import { loadEnv } from "./utils.js"; loadEnv(); let { + DEBUG, NODE_VERSION = "18", FIREBASE_ADMIN, PROJECT_ID, @@ -74,6 +75,7 @@ const firebaseConfig = { }; const env = { + DEBUG, FIRESTORE_PREFER_REST: "true", GCLOUD_PROJECT: config.projectId, FIREBASE_CONFIG: JSON.stringify(firebaseConfig), diff --git a/integration_test/setup.ts b/integration_test/setup.ts index dba7e8b6f..0dbc217be 100644 --- a/integration_test/setup.ts +++ b/integration_test/setup.ts @@ -136,16 +136,13 @@ function createRequirementsTxt(firebaseAdmin: string) { fs.copyFileSync(requirementsTemplatePath, requirementsPath); let requirementsContent = fs.readFileSync(requirementsPath, "utf8"); - requirementsContent = requirementsContent.replace( /__LOCAL_FIREBASE_FUNCTIONS__/g, - `firebase_functions.tar.gz` ); requirementsContent = requirementsContent.replace( /__FIREBASE_ADMIN__/g, - firebaseAdmin ); From fa98a7f09fc68f40e30651cd6ec9ef83f0be6f16 Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Wed, 6 Aug 2025 16:51:47 +0100 Subject: [PATCH 16/25] refactor: make integration tests more robust --- integration_test/deployment-utils.ts | 276 +++ integration_test/package-lock.json | 2888 ++++++++++++++++++-------- integration_test/package.json | 4 +- integration_test/run.ts | 83 +- 4 files changed, 2367 insertions(+), 884 deletions(-) create mode 100644 integration_test/deployment-utils.ts diff --git a/integration_test/deployment-utils.ts b/integration_test/deployment-utils.ts new file mode 100644 index 000000000..be4f4b90c --- /dev/null +++ b/integration_test/deployment-utils.ts @@ -0,0 +1,276 @@ +import pRetry from "p-retry"; +import pLimit from "p-limit"; + +interface FirebaseClient { + functions: { + list: () => Promise<{ name: string }[]>; + delete(names: string[], options: any): Promise; + }; + deploy: (options: { only: string; force: boolean }) => Promise; +} + +// Configuration constants +const BATCH_SIZE = 3; // Reduced to 3 functions at a time for better rate limiting +const DELAY_BETWEEN_BATCHES = 5000; // Increased from 2 to 5 seconds between batches +const MAX_RETRIES = 3; // Retry failed deployments +const CLEANUP_DELAY = 1000; // 1 second between cleanup operations +// Rate limiter for deployment operations +const deploymentLimiter = pLimit(1); // Only one deployment operation at a time +const cleanupLimiter = pLimit(2); // Allow 2 cleanup operations concurrently + +/** + * Sleep utility function + */ +const sleep = (ms: number): Promise => new Promise((resolve) => setTimeout(resolve, ms)); + +/** + * Get all deployed functions for the current project + */ +export async function getDeployedFunctions(client: FirebaseClient): Promise { + try { + const functions = await client.functions.list(); + return functions.map((fn: { name: string }) => fn.name); + } catch (error) { + console.log("Could not list functions, assuming none deployed:", error); + return []; + } +} + +/** + * Delete a single function with retry logic + */ +async function deleteFunctionWithRetry( + client: FirebaseClient, + functionName: string +): Promise { + return pRetry( + async () => { + try { + await client.functions.delete([functionName], { + force: true, + project: process.env.PROJECT_ID, + config: "./firebase.json", + debug: true, + nonInteractive: true, + }); + console.log(`✅ Deleted function: ${functionName}`); + } catch (error: unknown) { + if ( + error && + typeof error === "object" && + "message" in error && + typeof error.message === "string" && + error.message.includes("not found") + ) { + console.log(`ℹ️ Function not found (already deleted): ${functionName}`); + return; // Not an error, function was already deleted + } + throw error; + } + }, + { + retries: MAX_RETRIES, + onFailedAttempt: (error) => { + console.log( + `❌ Failed to delete ${functionName} (attempt ${error.attemptNumber}/${ + MAX_RETRIES + 1 + }):`, + error.message + ); + }, + } + ); +} + +/** + * Pre-cleanup: Remove all existing functions before deployment + */ +export async function preCleanup(client: FirebaseClient): Promise { + console.log("🧹 Starting pre-cleanup..."); + + try { + const deployedFunctions = await getDeployedFunctions(client); + + if (deployedFunctions.length === 0) { + console.log("ℹ️ No functions to clean up"); + return; + } + + console.log(`Found ${deployedFunctions.length} functions to clean up`); + + // Delete functions in batches with rate limiting + const batches: string[][] = []; + for (let i = 0; i < deployedFunctions.length; i += BATCH_SIZE) { + batches.push(deployedFunctions.slice(i, i + BATCH_SIZE)); + } + + for (let i = 0; i < batches.length; i++) { + const batch = batches[i]; + console.log(`Cleaning up batch ${i + 1}/${batches.length} (${batch.length} functions)`); + + // Delete functions in parallel within the batch + const deletePromises = batch.map((functionName) => + cleanupLimiter(() => deleteFunctionWithRetry(client, functionName)) + ); + + await Promise.all(deletePromises); + + // Add delay between batches + if (i < batches.length - 1) { + console.log(`Waiting ${CLEANUP_DELAY}ms before next batch...`); + await sleep(CLEANUP_DELAY); + } + } + + console.log("✅ Pre-cleanup completed"); + } catch (error) { + console.error("❌ Pre-cleanup failed:", error); + throw error; + } +} + +/** + * Deploy functions with rate limiting and retry logic + */ +export async function deployFunctionsWithRetry( + client: any, + functionsToDeploy: string[] +): Promise { + console.log(`🚀 Deploying ${functionsToDeploy.length} functions with rate limiting...`); + + // Deploy functions in batches + const batches = []; + for (let i = 0; i < functionsToDeploy.length; i += BATCH_SIZE) { + batches.push(functionsToDeploy.slice(i, i + BATCH_SIZE)); + } + + for (let i = 0; i < batches.length; i++) { + const batch = batches[i]; + console.log(`Deploying batch ${i + 1}/${batches.length} (${batch.length} functions)`); + + try { + await pRetry( + async () => { + await deploymentLimiter(async () => { + await client.deploy({ + only: "functions", + force: true, + }); + }); + }, + { + retries: MAX_RETRIES, + onFailedAttempt: (error: any) => { + console.log( + `❌ Deployment failed (attempt ${error.attemptNumber}/${MAX_RETRIES + 1}):`, + error.message + ); + // Log detailed error information during retries + if (error.children && error.children.length > 0) { + console.log("📋 Detailed deployment errors:"); + error.children.forEach((child: any, index: number) => { + console.log(` ${index + 1}. ${child.message || child}`); + if (child.original) { + console.log( + ` Original error message: ${child.original.message || "No message"}` + ); + console.log(` Original error code: ${child.original.code || "No code"}`); + console.log( + ` Original error status: ${child.original.status || "No status"}` + ); + } + }); + } + // Log the full error structure for debugging + console.log("🔍 Error details:"); + console.log(` - Message: ${error.message}`); + console.log(` - Status: ${error.status}`); + console.log(` - Exit code: ${error.exit}`); + console.log(` - Attempt: ${error.attemptNumber}`); + console.log(` - Retries left: ${error.retriesLeft}`); + }, + } + ); + + console.log(`✅ Batch ${i + 1} deployed successfully`); + + // Add delay between batches + if (i < batches.length - 1) { + console.log(`Waiting ${DELAY_BETWEEN_BATCHES}ms before next batch...`); + await sleep(DELAY_BETWEEN_BATCHES); + } + } catch (error: any) { + console.error(`❌ Failed to deploy batch ${i + 1}:`, error); + // Log detailed error information + if (error.children && error.children.length > 0) { + console.log("📋 Detailed deployment errors:"); + error.children.forEach((child: any, index: number) => { + console.log(` ${index + 1}. ${child.message || child}`); + if (child.original) { + console.log(` Original error message: ${child.original.message || "No message"}`); + console.log(` Original error code: ${child.original.code || "No code"}`); + console.log(` Original error status: ${child.original.status || "No status"}`); + } + }); + } + // Log the full error structure for debugging + console.log("🔍 Error details:"); + console.log(` - Message: ${error.message}`); + console.log(` - Status: ${error.status}`); + console.log(` - Exit code: ${error.exit}`); + console.log(` - Attempt: ${error.attemptNumber}`); + console.log(` - Retries left: ${error.retriesLeft}`); + throw error; + } + } + + console.log("✅ All functions deployed successfully"); +} + +/** + * Post-cleanup: Remove deployed functions after tests + */ +export async function postCleanup(client: any, testRunId: string): Promise { + console.log("🧹 Starting post-cleanup..."); + + try { + const deployedFunctions = await getDeployedFunctions(client); + const testFunctions = deployedFunctions.filter((name) => name && name.includes(testRunId)); + + if (testFunctions.length === 0) { + console.log("ℹ️ No test functions to clean up"); + return; + } + + console.log(`Found ${testFunctions.length} test functions to clean up`); + + // Delete test functions in batches with rate limiting + const batches = []; + for (let i = 0; i < testFunctions.length; i += BATCH_SIZE) { + batches.push(testFunctions.slice(i, i + BATCH_SIZE)); + } + + for (let i = 0; i < batches.length; i++) { + const batch = batches[i]; + console.log(`Cleaning up batch ${i + 1}/${batches.length} (${batch.length} functions)`); + + // Delete functions in parallel within the batch + const deletePromises = batch.map((functionName) => + cleanupLimiter(() => deleteFunctionWithRetry(client, functionName)) + ); + + await Promise.all(deletePromises); + + // Add delay between batches + if (i < batches.length - 1) { + console.log(`Waiting ${CLEANUP_DELAY}ms before next batch...`); + await sleep(CLEANUP_DELAY); + } + } + + console.log("✅ Post-cleanup completed"); + } catch (error) { + console.error("❌ Post-cleanup failed:", error); + throw error; + } +} diff --git a/integration_test/package-lock.json b/integration_test/package-lock.json index bcebe4e7e..15f704625 100644 --- a/integration_test/package-lock.json +++ b/integration_test/package-lock.json @@ -8,7 +8,7 @@ "dependencies": { "@google-cloud/eventarc": "^3.1.0", "@google-cloud/tasks": "^5.1.0", - "firebase": "^10.14.0", + "firebase": "^12.0.0", "firebase-admin": "^12.6.0", "firebase-tools": "^13.20.2", "js-yaml": "^4.1.0", @@ -19,6 +19,8 @@ "@types/js-yaml": "^4.0.9", "@types/node-fetch": "^2.6.11", "jest": "^29.7.0", + "p-limit": "^6.2.0", + "p-retry": "^6.2.1", "ts-jest": "^29.1.1" } }, @@ -49,70 +51,20 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { "version": "7.23.5", "dev": true, @@ -303,9 +255,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "license": "MIT", "engines": { @@ -313,9 +265,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "dev": true, "license": "MIT", "engines": { @@ -331,88 +283,28 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.5", - "@babel/types": "^7.23.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.2.tgz", + "integrity": "sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@babel/parser": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "@babel/types": "^7.28.0" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.5", - "dev": true, - "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -612,13 +504,15 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -645,13 +539,14 @@ } }, "node_modules/@babel/types": { - "version": "7.23.5", + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", + "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -694,536 +589,1405 @@ "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.0.0.tgz", "integrity": "sha512-83rnH2nCvclWaPQQKvkJ2pdOjG4TZyEVuFDnlOF6KP08lDaaceVyw/W63mDuafQT+MKHCvXIPpE5uYWeM0rT4w==" }, - "node_modules/@firebase/analytics": { - "version": "0.10.8", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.8.tgz", - "integrity": "sha512-CVnHcS4iRJPqtIDc411+UmFldk0ShSK3OB+D0bKD8Ck5Vro6dbK5+APZpkuWpbfdL359DIQUnAaMLE+zs/PVyA==", + "node_modules/@firebase/ai": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@firebase/ai/-/ai-2.0.0.tgz", + "integrity": "sha512-N/aSHjqOpU+KkYU3piMkbcuxzvqsOvxflLUXBAkYAPAz8wjE2Ye3BQDgKHEYuhMmEWqj6LFgEBUN8wwc6dfMTw==", + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, + "engines": { + "node": ">=20.0.0" + }, "peerDependencies": { - "@firebase/app": "0.x" + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" } }, - "node_modules/@firebase/analytics-compat": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.14.tgz", - "integrity": "sha512-unRVY6SvRqfNFIAA/kwl4vK+lvQAL2HVcgu9zTrUtTyYDmtIt/lOuHJynBMYEgLnKm39YKBDhtqdapP2e++ASw==", + "node_modules/@firebase/ai/node_modules/@firebase/app-check-interop-types": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz", + "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==", + "license": "Apache-2.0" + }, + "node_modules/@firebase/ai/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", "dependencies": { - "@firebase/analytics": "0.10.8", - "@firebase/analytics-types": "0.8.2", - "@firebase/component": "0.6.9", - "@firebase/util": "1.10.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/analytics-types": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.2.tgz", - "integrity": "sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw==" + "node_modules/@firebase/ai/node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } }, - "node_modules/@firebase/app": { - "version": "0.10.12", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.12.tgz", - "integrity": "sha512-fgBqe5j7GKv7/eMfyU4N1FdiW6O1EyrrVbMa8rJOT5MYNpCXqdL/5NNcLDStS1l6CN7h65a7jUNXmMnMSWo0sw==", + "node_modules/@firebase/ai/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", - "idb": "7.1.1", "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/app-check": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.8.tgz", - "integrity": "sha512-O49RGF1xj7k6BuhxGpHmqOW5hqBIAEbt2q6POW0lIywx7emYtzPDeQI+ryQpC4zbKX646SoVZ711TN1DBLNSOQ==", + "node_modules/@firebase/analytics": { + "version": "0.10.18", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.18.tgz", + "integrity": "sha512-iN7IgLvM06iFk8BeFoWqvVpRFW3Z70f+Qe2PfCJ7vPIgLPjHXDE774DhCT5Y2/ZU/ZbXPDPD60x/XPWEoZLNdg==", + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/component": "0.7.0", + "@firebase/installations": "0.6.19", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, - "node_modules/@firebase/app-check-compat": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.15.tgz", - "integrity": "sha512-zFIvIFFNqDXpOT2huorz9cwf56VT3oJYRFjSFYdSbGYEJYEaXjLJbfC79lx/zjx4Fh+yuN8pry3TtvwaevrGbg==", + "node_modules/@firebase/analytics-compat": { + "version": "0.2.24", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.24.tgz", + "integrity": "sha512-jE+kJnPG86XSqGQGhXXYt1tpTbCTED8OQJ/PQ90SEw14CuxRxx/H+lFbWA1rlFtFSsTCptAJtgyRBwr/f00vsw==", + "license": "Apache-2.0", "dependencies": { - "@firebase/app-check": "0.8.8", - "@firebase/app-check-types": "0.5.2", - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/analytics": "0.10.18", + "@firebase/analytics-types": "0.8.3", + "@firebase/component": "0.7.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/app-check-interop-types": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.2.tgz", - "integrity": "sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ==" - }, - "node_modules/@firebase/app-check-types": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.2.tgz", - "integrity": "sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA==" + "node_modules/@firebase/analytics-compat/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } }, - "node_modules/@firebase/app-compat": { - "version": "0.2.42", - "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.42.tgz", - "integrity": "sha512-vPI0Aksk8ZuHywigyTxrx/oWbuD41kHxajfxRly7urHOFRiXKxf/q2ftgmcMVPfIeg0K02LzYNBmoh2PWzERpg==", + "node_modules/@firebase/analytics-compat/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "@firebase/app": "0.10.12", - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/app-types": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz", - "integrity": "sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==" + "node_modules/@firebase/analytics-types": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.3.tgz", + "integrity": "sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg==", + "license": "Apache-2.0" }, - "node_modules/@firebase/auth": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.7.9.tgz", - "integrity": "sha512-yLD5095kVgDw965jepMyUrIgDklD6qH/BZNHeKOgvu7pchOKNjVM+zQoOVYJIKWMWOWBq8IRNVU6NXzBbozaJg==", + "node_modules/@firebase/analytics/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", - "tslib": "^2.1.0", - "undici": "6.19.7" - }, - "peerDependencies": { - "@firebase/app": "0.x", - "@react-native-async-storage/async-storage": "^1.18.1" + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" }, - "peerDependenciesMeta": { - "@react-native-async-storage/async-storage": { - "optional": true - } + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/auth-compat": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.14.tgz", - "integrity": "sha512-2eczCSqBl1KUPJacZlFpQayvpilg3dxXLy9cSMTKtQMTQSmondUtPI47P3ikH3bQAXhzKLOE+qVxJ3/IRtu9pw==", + "node_modules/@firebase/analytics/node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "license": "Apache-2.0", "dependencies": { - "@firebase/auth": "1.7.9", - "@firebase/auth-types": "0.12.2", - "@firebase/component": "0.6.9", - "@firebase/util": "1.10.0", - "tslib": "^2.1.0", - "undici": "6.19.7" + "tslib": "^2.1.0" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/auth-interop-types": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz", - "integrity": "sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==" - }, - "node_modules/@firebase/auth-types": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.2.tgz", - "integrity": "sha512-qsEBaRMoGvHO10unlDJhaKSuPn4pyoTtlQuP1ghZfzB6rNQPuhp/N/DcFZxm9i4v0SogjCbf9reWupwIvfmH6w==", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" + "node_modules/@firebase/analytics/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/component": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.9.tgz", - "integrity": "sha512-gm8EUEJE/fEac86AvHn8Z/QW8BvR56TBw3hMW0O838J/1mThYQXAIQBgUv75EqlCZfdawpWLrKt1uXvp9ciK3Q==", + "node_modules/@firebase/app": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.0.tgz", + "integrity": "sha512-APIAeKvRNFWKJLjIL8wLDjh7u8g6ZjaeVmItyqSjCdEkJj14UuVlus74D8ofsOMWh45HEwxwkd96GYbi+CImEg==", + "license": "Apache-2.0", "dependencies": { - "@firebase/util": "1.10.0", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "idb": "7.1.1", "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/data-connect": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.0.tgz", - "integrity": "sha512-vSe5s8dY13ilhLnfY0eYRmQsdTbH7PUFZtBbqU6JVX/j8Qp9A6G5gG6//ulbX9/1JFOF1IWNOne9c8S/DOCJaQ==", + "node_modules/@firebase/app-check": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.11.0.tgz", + "integrity": "sha512-XAvALQayUMBJo58U/rxW02IhsesaxxfWVmVkauZvGEz3vOAjMEQnzFlyblqkc2iAaO82uJ2ZVyZv9XzPfxjJ6w==", + "license": "Apache-2.0", "dependencies": { - "@firebase/auth-interop-types": "0.2.3", - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, + "engines": { + "node": ">=20.0.0" + }, "peerDependencies": { "@firebase/app": "0.x" } }, - "node_modules/@firebase/database": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.8.tgz", - "integrity": "sha512-dzXALZeBI1U5TXt6619cv0+tgEhJiwlUtQ55WNZY7vGAjv7Q1QioV969iYwt1AQQ0ovHnEW0YW9TiBfefLvErg==", + "node_modules/@firebase/app-check-compat": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.4.0.tgz", + "integrity": "sha512-UfK2Q8RJNjYM/8MFORltZRG9lJj11k0nW84rrffiKvcJxLf1jf6IEjCIkCamykHE73C6BwqhVfhIBs69GXQV0g==", + "license": "Apache-2.0", "dependencies": { - "@firebase/app-check-interop-types": "0.3.2", - "@firebase/auth-interop-types": "0.2.3", - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", - "faye-websocket": "0.11.4", + "@firebase/app-check": "0.11.0", + "@firebase/app-check-types": "0.5.3", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/database-compat": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.8.tgz", - "integrity": "sha512-OpeWZoPE3sGIRPBKYnW9wLad25RaWbGyk7fFQe4xnJQKRzlynWeFBSRRAoLE2Old01WXwskUiucNqUUVlFsceg==", + "node_modules/@firebase/app-check-compat/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/database": "1.0.8", - "@firebase/database-types": "1.0.5", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" - } + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/app-check-compat/node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/app-check-compat/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/app-check-interop-types": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.2.tgz", + "integrity": "sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ==" + }, + "node_modules/@firebase/app-check-types": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.3.tgz", + "integrity": "sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng==", + "license": "Apache-2.0" + }, + "node_modules/@firebase/app-check/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/app-check/node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/app-check/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/app-compat": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.0.tgz", + "integrity": "sha512-nUnNpOeRj0KZzVzHsyuyrmZKKHfykZ8mn40FtG28DeSTWeM5b/2P242Va4bmQpJsy5y32vfv50+jvdckrpzy7Q==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/app": "0.14.0", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/app-compat/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/app-compat/node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/app-compat/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/app-types": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz", + "integrity": "sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==" + }, + "node_modules/@firebase/app/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/app/node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/app/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/auth": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.11.0.tgz", + "integrity": "sha512-5j7+ua93X+IRcJ1oMDTClTo85l7Xe40WSkoJ+shzPrX7OISlVWLdE1mKC57PSD+/LfAbdhJmvKixINBw2ESK6w==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@react-native-async-storage/async-storage": "^1.18.1" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } + } + }, + "node_modules/@firebase/auth-compat": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.6.0.tgz", + "integrity": "sha512-J0lGSxXlG/lYVi45wbpPhcWiWUMXevY4fvLZsN1GHh+po7TZVng+figdHBVhFheaiipU8HZyc7ljw1jNojM2nw==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/auth": "1.11.0", + "@firebase/auth-types": "0.13.0", + "@firebase/component": "0.7.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/auth-compat/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/auth-compat/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz", + "integrity": "sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==" + }, + "node_modules/@firebase/auth-types": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.13.0.tgz", + "integrity": "sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg==", + "license": "Apache-2.0", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/auth/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/auth/node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/auth/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/component": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.9.tgz", + "integrity": "sha512-gm8EUEJE/fEac86AvHn8Z/QW8BvR56TBw3hMW0O838J/1mThYQXAIQBgUv75EqlCZfdawpWLrKt1uXvp9ciK3Q==", + "dependencies": { + "@firebase/util": "1.10.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/data-connect": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.3.11.tgz", + "integrity": "sha512-G258eLzAD6im9Bsw+Qm1Z+P4x0PGNQ45yeUuuqe5M9B1rn0RJvvsQCRHXgE52Z+n9+WX1OJd/crcuunvOGc7Vw==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/data-connect/node_modules/@firebase/auth-interop-types": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz", + "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==", + "license": "Apache-2.0" + }, + "node_modules/@firebase/data-connect/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/data-connect/node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/data-connect/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/database": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.8.tgz", + "integrity": "sha512-dzXALZeBI1U5TXt6619cv0+tgEhJiwlUtQ55WNZY7vGAjv7Q1QioV969iYwt1AQQ0ovHnEW0YW9TiBfefLvErg==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.2", + "@firebase/auth-interop-types": "0.2.3", + "@firebase/component": "0.6.9", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.10.0", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-compat": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.8.tgz", + "integrity": "sha512-OpeWZoPE3sGIRPBKYnW9wLad25RaWbGyk7fFQe4xnJQKRzlynWeFBSRRAoLE2Old01WXwskUiucNqUUVlFsceg==", + "dependencies": { + "@firebase/component": "0.6.9", + "@firebase/database": "1.0.8", + "@firebase/database-types": "1.0.5", + "@firebase/logger": "0.4.2", + "@firebase/util": "1.10.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-types": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.5.tgz", + "integrity": "sha512-fTlqCNwFYyq/C6W7AJ5OCuq5CeZuBEsEwptnVxlNPkWCo5cTTyukzAHRSO/jaQcItz33FfYrrFk1SJofcu2AaQ==", + "dependencies": { + "@firebase/app-types": "0.9.2", + "@firebase/util": "1.10.0" + } + }, + "node_modules/@firebase/firestore": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.9.0.tgz", + "integrity": "sha512-5zl0+/h1GvlCSLt06RMwqFsd7uqRtnNZt4sW99k2rKRd6k/ECObIWlEnvthm2cuOSnUmwZknFqtmd1qyYSLUuQ==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "@firebase/webchannel-wrapper": "1.0.4", + "@grpc/grpc-js": "~1.9.0", + "@grpc/proto-loader": "^0.7.8", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/firestore-compat": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.4.0.tgz", + "integrity": "sha512-4O7v4VFeSEwAZtLjsaj33YrMHMRjplOIYC2CiYsF6o/MboOhrhe01VrTt8iY9Y5EwjRHuRz4pS6jMBT8LfQYJA==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/firestore": "4.9.0", + "@firebase/firestore-types": "3.0.3", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/firestore-compat/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/firestore-compat/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/firestore-types": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.3.tgz", + "integrity": "sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==", + "license": "Apache-2.0", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/firestore/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } }, - "node_modules/@firebase/database-types": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.5.tgz", - "integrity": "sha512-fTlqCNwFYyq/C6W7AJ5OCuq5CeZuBEsEwptnVxlNPkWCo5cTTyukzAHRSO/jaQcItz33FfYrrFk1SJofcu2AaQ==", + "node_modules/@firebase/firestore/node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "license": "Apache-2.0", "dependencies": { - "@firebase/app-types": "0.9.2", - "@firebase/util": "1.10.0" + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/firestore": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.3.tgz", - "integrity": "sha512-NwVU+JPZ/3bhvNSJMCSzfcBZZg8SUGyzZ2T0EW3/bkUeefCyzMISSt/TTIfEHc8cdyXGlMqfGe3/62u9s74UEg==", + "node_modules/@firebase/firestore/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/firestore/node_modules/@grpc/grpc-js": { + "version": "1.9.15", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", + "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==", + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", - "@firebase/webchannel-wrapper": "1.0.1", - "@grpc/grpc-js": "~1.9.0", "@grpc/proto-loader": "^0.7.8", - "tslib": "^2.1.0", - "undici": "6.19.7" + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@firebase/functions": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.13.0.tgz", + "integrity": "sha512-2/LH5xIbD8aaLOWSFHAwwAybgSzHIM0dB5oVOL0zZnxFG1LctX2bc1NIAaPk1T+Zo9aVkLKUlB5fTXTkVUQprQ==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.7.0", + "@firebase/messaging-interop-types": "0.2.3", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=20.0.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, - "node_modules/@firebase/firestore-compat": { - "version": "0.3.38", - "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.38.tgz", - "integrity": "sha512-GoS0bIMMkjpLni6StSwRJarpu2+S5m346Na7gr9YZ/BZ/W3/8iHGNr9PxC+f0rNZXqS4fGRn88pICjrZEgbkqQ==", + "node_modules/@firebase/functions-compat": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.4.0.tgz", + "integrity": "sha512-VPgtvoGFywWbQqtvgJnVWIDFSHV1WE6Hmyi5EGI+P+56EskiGkmnw6lEqc/MEUfGpPGdvmc4I9XMU81uj766/g==", + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/firestore": "4.7.3", - "@firebase/firestore-types": "3.0.2", - "@firebase/util": "1.10.0", + "@firebase/component": "0.7.0", + "@firebase/functions": "0.13.0", + "@firebase/functions-types": "0.6.3", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, + "engines": { + "node": ">=20.0.0" + }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/firestore-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.2.tgz", - "integrity": "sha512-wp1A+t5rI2Qc/2q7r2ZpjUXkRVPtGMd6zCLsiWurjsQpqPgFin3AhNibKcIzoF2rnToNa/XYtyWXuifjOOwDgg==", + "node_modules/@firebase/functions-compat/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/functions-compat/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/functions-types": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.3.tgz", + "integrity": "sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg==", + "license": "Apache-2.0" + }, + "node_modules/@firebase/functions/node_modules/@firebase/app-check-interop-types": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz", + "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==", + "license": "Apache-2.0" + }, + "node_modules/@firebase/functions/node_modules/@firebase/auth-interop-types": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz", + "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==", + "license": "Apache-2.0" + }, + "node_modules/@firebase/functions/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/functions/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/installations": { + "version": "0.6.19", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.19.tgz", + "integrity": "sha512-nGDmiwKLI1lerhwfwSHvMR9RZuIH5/8E3kgUWnVRqqL7kGVSktjLTWEMva7oh5yxQ3zXfIlIwJwMcaM5bK5j8Q==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/util": "1.13.0", + "idb": "7.1.1", + "tslib": "^2.1.0" + }, "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/installations-compat": { + "version": "0.2.19", + "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.19.tgz", + "integrity": "sha512-khfzIY3EI5LePePo7vT19/VEIH1E3iYsHknI/6ek9T8QCozAZshWT9CjlwOzZrKvTHMeNcbpo/VSOSIWDSjWdQ==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/installations": "0.6.19", + "@firebase/installations-types": "0.5.3", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/installations-compat/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/installations-compat/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/installations-types": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.3.tgz", + "integrity": "sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==", + "license": "Apache-2.0", + "peerDependencies": { + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/installations/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/installations/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/logger": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", + "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/messaging": { + "version": "0.12.23", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.23.tgz", + "integrity": "sha512-cfuzv47XxqW4HH/OcR5rM+AlQd1xL/VhuaeW/wzMW1LFrsFcTn0GND/hak1vkQc2th8UisBcrkVcQAnOnKwYxg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/installations": "0.6.19", + "@firebase/messaging-interop-types": "0.2.3", + "@firebase/util": "1.13.0", + "idb": "7.1.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/messaging-compat": { + "version": "0.2.23", + "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.23.tgz", + "integrity": "sha512-SN857v/kBUvlQ9X/UjAqBoQ2FEaL1ZozpnmL1ByTe57iXkmnVVFm9KqAsTfmf+OEwWI4kJJe9NObtN/w22lUgg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/messaging": "0.12.23", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/messaging-compat/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/messaging-compat/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/messaging-interop-types": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz", + "integrity": "sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q==", + "license": "Apache-2.0" + }, + "node_modules/@firebase/messaging/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/messaging/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/performance": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.7.8.tgz", + "integrity": "sha512-k6xfNM/CdTl4RaV4gT/lH53NU+wP33JiN0pUeNBzGVNvfXZ3HbCkoISE3M/XaiOwHgded1l6XfLHa4zHgm0Wyg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/installations": "0.6.19", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0", + "web-vitals": "^4.2.4" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/performance-compat": { + "version": "0.2.21", + "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.21.tgz", + "integrity": "sha512-OQfYRsIQiEf9ez1SOMLb5TRevBHNIyA2x1GI1H10lZ432W96AK5r4LTM+SNApg84dxOuHt6RWSQWY7TPWffKXg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/performance": "0.7.8", + "@firebase/performance-types": "0.2.3", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/performance-compat/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/performance-compat/node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/performance-compat/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/firestore/node_modules/@grpc/grpc-js": { - "version": "1.9.15", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", - "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==", + "node_modules/@firebase/performance-types": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.3.tgz", + "integrity": "sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ==", + "license": "Apache-2.0" + }, + "node_modules/@firebase/performance/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", "dependencies": { - "@grpc/proto-loader": "^0.7.8", - "@types/node": ">=12.12.47" + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" }, "engines": { - "node": "^8.13.0 || >=10.10.0" + "node": ">=20.0.0" } }, - "node_modules/@firebase/functions": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.8.tgz", - "integrity": "sha512-Lo2rTPDn96naFIlSZKVd1yvRRqqqwiJk7cf9TZhUerwnPKgBzXy+aHE22ry+6EjCaQusUoNai6mU6p+G8QZT1g==", + "node_modules/@firebase/performance/node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "license": "Apache-2.0", "dependencies": { - "@firebase/app-check-interop-types": "0.3.2", - "@firebase/auth-interop-types": "0.2.3", - "@firebase/component": "0.6.9", - "@firebase/messaging-interop-types": "0.2.2", - "@firebase/util": "1.10.0", - "tslib": "^2.1.0", - "undici": "6.19.7" + "tslib": "^2.1.0" }, - "peerDependencies": { - "@firebase/app": "0.x" + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/functions-compat": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.14.tgz", - "integrity": "sha512-dZ0PKOKQFnOlMfcim39XzaXonSuPPAVuzpqA4ONTIdyaJK/OnBaIEVs/+BH4faa1a2tLeR+Jy15PKqDRQoNIJw==", + "node_modules/@firebase/performance/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/functions": "0.11.8", - "@firebase/functions-types": "0.6.2", - "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/functions-types": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.2.tgz", - "integrity": "sha512-0KiJ9lZ28nS2iJJvimpY4nNccV21rkQyor5Iheu/nq8aKXJqtJdeSlZDspjPSBBiHRzo7/GMUttegnsEITqR+w==" - }, - "node_modules/@firebase/installations": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.9.tgz", - "integrity": "sha512-hlT7AwCiKghOX3XizLxXOsTFiFCQnp/oj86zp1UxwDGmyzsyoxtX+UIZyVyH/oBF5+XtblFG9KZzZQ/h+dpy+Q==", + "node_modules/@firebase/remote-config": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.6.6.tgz", + "integrity": "sha512-Yelp5xd8hM4NO1G1SuWrIk4h5K42mNwC98eWZ9YLVu6Z0S6hFk1mxotAdCRmH2luH8FASlYgLLq6OQLZ4nbnCA==", + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/util": "1.10.0", - "idb": "7.1.1", + "@firebase/component": "0.7.0", + "@firebase/installations": "0.6.19", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, - "node_modules/@firebase/installations-compat": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.9.tgz", - "integrity": "sha512-2lfdc6kPXR7WaL4FCQSQUhXcPbI7ol3wF+vkgtU25r77OxPf8F/VmswQ7sgIkBBWtymn5ZF20TIKtnOj9rjb6w==", + "node_modules/@firebase/remote-config-compat": { + "version": "0.2.19", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.19.tgz", + "integrity": "sha512-y7PZAb0l5+5oIgLJr88TNSelxuASGlXyAKj+3pUc4fDuRIdPNBoONMHaIUa9rlffBR5dErmaD2wUBJ7Z1a513Q==", + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/installations-types": "0.5.2", - "@firebase/util": "1.10.0", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/remote-config": "0.6.6", + "@firebase/remote-config-types": "0.4.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/installations-types": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.2.tgz", - "integrity": "sha512-que84TqGRZJpJKHBlF2pkvc1YcXrtEDOVGiDjovP/a3s6W4nlbohGXEsBJo0JCeeg/UG9A+DEZVDUV9GpklUzA==", - "peerDependencies": { - "@firebase/app-types": "0.x" - } - }, - "node_modules/@firebase/logger": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "node_modules/@firebase/remote-config-compat/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", "dependencies": { + "@firebase/util": "1.13.0", "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/messaging": { - "version": "0.12.11", - "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.11.tgz", - "integrity": "sha512-zn5zGhF46BmiZ7W9yAUoHlqzJGakmWn1FNp//roXHN62dgdEFIKfXY7IODA2iQiXpmUO3sBdI/Tf+Hsft1mVkw==", + "node_modules/@firebase/remote-config-compat/node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/messaging-interop-types": "0.2.2", - "@firebase/util": "1.10.0", - "idb": "7.1.1", "tslib": "^2.1.0" }, - "peerDependencies": { - "@firebase/app": "0.x" + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/messaging-compat": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.11.tgz", - "integrity": "sha512-2NCkfE1L9jSn5OC+2n5rGAz5BEAQreK2lQGdPYQEJlAbKB2efoF+2FdiQ+LD8SlioSXz66REfeaEdesoLPFQcw==", + "node_modules/@firebase/remote-config-compat/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/messaging": "0.12.11", - "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/messaging-interop-types": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.2.tgz", - "integrity": "sha512-l68HXbuD2PPzDUOFb3aG+nZj5KA3INcPwlocwLZOzPp9rFM9yeuI9YLl6DQfguTX5eAGxO0doTR+rDLDvQb5tA==" + "node_modules/@firebase/remote-config-types": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.4.0.tgz", + "integrity": "sha512-7p3mRE/ldCNYt8fmWMQ/MSGRmXYlJ15Rvs9Rk17t8p0WwZDbeK7eRmoI1tvCPaDzn9Oqh+yD6Lw+sGLsLg4kKg==", + "license": "Apache-2.0" }, - "node_modules/@firebase/performance": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.9.tgz", - "integrity": "sha512-PnVaak5sqfz5ivhua+HserxTJHtCar/7zM0flCX6NkzBNzJzyzlH4Hs94h2Il0LQB99roBqoE5QT1JqWqcLJHQ==", + "node_modules/@firebase/remote-config/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, - "peerDependencies": { - "@firebase/app": "0.x" + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/performance-compat": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.9.tgz", - "integrity": "sha512-dNl95IUnpsu3fAfYBZDCVhXNkASE0uo4HYaEPd2/PKscfTvsgqFAOxfAXzBEDOnynDWiaGUnb5M1O00JQ+3FXA==", + "node_modules/@firebase/remote-config/node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/performance": "0.6.9", - "@firebase/performance-types": "0.2.2", - "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/performance-types": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.2.tgz", - "integrity": "sha512-gVq0/lAClVH5STrIdKnHnCo2UcPLjJlDUoEB/tB4KM+hAeHUxWKnpT0nemUPvxZ5nbdY/pybeyMe8Cs29gEcHA==" + "node_modules/@firebase/remote-config/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } }, - "node_modules/@firebase/remote-config": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.9.tgz", - "integrity": "sha512-EO1NLCWSPMHdDSRGwZ73kxEEcTopAxX1naqLJFNApp4hO8WfKfmEpmjxmP5TrrnypjIf2tUkYaKsfbEA7+AMmA==", + "node_modules/@firebase/storage": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.14.0.tgz", + "integrity": "sha512-xWWbb15o6/pWEw8H01UQ1dC5U3rf8QTAzOChYyCpafV6Xki7KVp3Yaw2nSklUwHEziSWE9KoZJS7iYeyqWnYFA==", + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/component": "0.7.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, + "engines": { + "node": ">=20.0.0" + }, "peerDependencies": { "@firebase/app": "0.x" } }, - "node_modules/@firebase/remote-config-compat": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.9.tgz", - "integrity": "sha512-AxzGpWfWFYejH2twxfdOJt5Cfh/ATHONegTd/a0p5flEzsD5JsxXgfkFToop+mypEL3gNwawxrxlZddmDoNxyA==", + "node_modules/@firebase/storage-compat": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.4.0.tgz", + "integrity": "sha512-vDzhgGczr1OfcOy285YAPur5pWDEvD67w4thyeCUh6Ys0izN9fNYtA1MJERmNBfqjqu0lg0FM5GLbw0Il21M+g==", + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/remote-config": "0.4.9", - "@firebase/remote-config-types": "0.3.2", - "@firebase/util": "1.10.0", + "@firebase/component": "0.7.0", + "@firebase/storage": "0.14.0", + "@firebase/storage-types": "0.8.3", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, + "engines": { + "node": ">=20.0.0" + }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/remote-config-types": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.2.tgz", - "integrity": "sha512-0BC4+Ud7y2aPTyhXJTMTFfrGGLqdYXrUB9sJVAB8NiqJswDTc4/2qrE/yfUbnQJhbSi6ZaTTBKyG3n1nplssaA==" - }, - "node_modules/@firebase/storage": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.2.tgz", - "integrity": "sha512-fxuJnHshbhVwuJ4FuISLu+/76Aby2sh+44ztjF2ppoe0TELIDxPW6/r1KGlWYt//AD0IodDYYA8ZTN89q8YqUw==", + "node_modules/@firebase/storage-compat/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/util": "1.10.0", - "tslib": "^2.1.0", - "undici": "6.19.7" + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" }, - "peerDependencies": { - "@firebase/app": "0.x" + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/storage-compat": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.12.tgz", - "integrity": "sha512-hA4VWKyGU5bWOll+uwzzhEMMYGu9PlKQc1w4DWxB3aIErWYzonrZjF0icqNQZbwKNIdh8SHjZlFeB2w6OSsjfg==", + "node_modules/@firebase/storage-compat/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/storage": "0.13.2", - "@firebase/storage-types": "0.8.2", - "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "engines": { + "node": ">=20.0.0" } }, "node_modules/@firebase/storage-types": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.2.tgz", - "integrity": "sha512-0vWu99rdey0g53lA7IShoA2Lol1jfnPovzLDUBuon65K7uKG9G+L5uO05brD9pMw+l4HRFw23ah3GwTGpEav6g==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.3.tgz", + "integrity": "sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==", + "license": "Apache-2.0", "peerDependencies": { "@firebase/app-types": "0.x", "@firebase/util": "1.x" } }, - "node_modules/@firebase/util": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.0.tgz", - "integrity": "sha512-xKtx4A668icQqoANRxyDLBLz51TAbDP9KRfpbKGxiCAW346d0BeJe5vN6/hKxxmWwnZ0mautyv39JxviwwQMOQ==", + "node_modules/@firebase/storage/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", "dependencies": { + "@firebase/util": "1.13.0", "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@firebase/vertexai-preview": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@firebase/vertexai-preview/-/vertexai-preview-0.0.4.tgz", - "integrity": "sha512-EBSqyu9eg8frQlVU9/HjKtHN7odqbh9MtAcVz3WwHj4gLCLOoN9F/o+oxlq3CxvFrd3CNTZwu6d2mZtVlEInng==", + "node_modules/@firebase/storage/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "@firebase/app-check-interop-types": "0.3.2", - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", "tslib": "^2.1.0" }, "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/util": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.0.tgz", + "integrity": "sha512-xKtx4A668icQqoANRxyDLBLz51TAbDP9KRfpbKGxiCAW346d0BeJe5vN6/hKxxmWwnZ0mautyv39JxviwwQMOQ==", + "dependencies": { + "tslib": "^2.1.0" } }, "node_modules/@firebase/webchannel-wrapper": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.1.tgz", - "integrity": "sha512-jmEnr/pk0yVkA7mIlHNnxCi+wWzOFUg0WyIotgkKAb2u1J7fAeDBcVNSTjTihbAYNusCLQdW5s9IJ5qwnEufcQ==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.4.tgz", + "integrity": "sha512-6m8+P+dE/RPl4OPzjTxcTbQ0rGeRyeTvAi9KwIffBVCiAMKrfXfLZaqD1F+m8t4B5/Q5aHsMozOgirkH1F5oMQ==", + "license": "Apache-2.0" }, "node_modules/@gar/promisify": { "version": "1.1.3", @@ -1369,6 +2133,35 @@ "node": ">=10.0.0" } }, + "node_modules/@google-cloud/storage/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@google-cloud/storage/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@google-cloud/tasks": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@google-cloud/tasks/-/tasks-5.1.0.tgz", @@ -2399,18 +3192,29 @@ } }, "node_modules/@types/request/node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.5.tgz", + "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35", + "safe-buffer": "^5.2.1" }, "engines": { "node": ">= 0.12" } }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", @@ -3013,10 +3817,13 @@ } }, "node_modules/basic-auth-connect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", - "integrity": "sha512-kiV+/DTgVro4aZifY/hwRwALBISViL5NP4aReaR2EVJEObpbUBHIkdJh/YpcoEiYt7nBodZ6U2ajZeZvSxUCCg==", - "license": "MIT" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.1.0.tgz", + "integrity": "sha512-rKcWjfiRZ3p5WS9e5q6msXa07s6DaFAMXoyowV+mb2xQG+oYdw2QEUyKi0Xp95JvXzShlM+oGy5QuqSK6TfC1Q==", + "license": "MIT", + "dependencies": { + "tsscmp": "^1.0.6" + } }, "node_modules/basic-auth/node_modules/safe-buffer": { "version": "5.1.2", @@ -3062,9 +3869,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -3075,7 +3882,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -3135,21 +3942,21 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -3329,13 +4136,30 @@ "node": ">=10" } }, - "node_modules/call-bind": { - "version": "1.0.5", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3830,30 +4654,21 @@ } }, "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "license": "MIT", "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", + "bytes": "3.1.2", + "compressible": "~2.0.18", "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "license": "MIT", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.8.0" } }, "node_modules/compression/node_modules/debug": { @@ -3871,11 +4686,14 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, "node_modules/concat-map": { "version": "0.0.1", @@ -4013,9 +4831,9 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -4145,9 +4963,9 @@ } }, "node_modules/cross-env/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", "license": "MIT", "dependencies": { "nice-try": "^1.0.4", @@ -4212,9 +5030,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -4246,12 +5064,12 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -4262,12 +5080,6 @@ } } }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "license": "MIT" - }, "node_modules/dedent": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", @@ -4335,18 +5147,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-data-property": { - "version": "1.1.1", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/degenerator": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", @@ -4452,6 +5252,20 @@ "node": ">=8" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/duplexify": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", @@ -4597,6 +5411,51 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escalade": { "version": "3.1.1", "license": "MIT", @@ -4830,21 +5689,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/exegesis/node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/exegesis/node_modules/semver": { "version": "7.5.4", "license": "ISC", @@ -4892,37 +5736,37 @@ "optional": true }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -4931,30 +5775,10 @@ }, "engines": { "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/debug": { @@ -4966,27 +5790,21 @@ "ms": "2.0.0" } }, - "node_modules/express/node_modules/ms": { + "node_modules/express/node_modules/encodeurl": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/express/node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, "engines": { "node": ">= 0.8" } }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -5044,21 +5862,6 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "license": "MIT" }, - "node_modules/fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", - "license": "MIT", - "dependencies": { - "punycode": "^1.3.2" - } - }, - "node_modules/fast-url-parser/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "license": "MIT" - }, "node_modules/fast-xml-parser": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.0.tgz", @@ -5134,9 +5937,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -5146,13 +5949,13 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -5172,6 +5975,15 @@ "ms": "2.0.0" } }, + "node_modules/finalhandler/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -5193,38 +6005,39 @@ } }, "node_modules/firebase": { - "version": "10.14.0", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.14.0.tgz", - "integrity": "sha512-/yB/OE4bfBbmtfku0DCdW6nWMHYVayN6xWKw68ztedxqGevfYDoPoygBXiLmvBHdWdBa+IlhJDkdUUiEEpcAUw==", - "dependencies": { - "@firebase/analytics": "0.10.8", - "@firebase/analytics-compat": "0.2.14", - "@firebase/app": "0.10.12", - "@firebase/app-check": "0.8.8", - "@firebase/app-check-compat": "0.3.15", - "@firebase/app-compat": "0.2.42", - "@firebase/app-types": "0.9.2", - "@firebase/auth": "1.7.9", - "@firebase/auth-compat": "0.5.14", - "@firebase/data-connect": "0.1.0", - "@firebase/database": "1.0.8", - "@firebase/database-compat": "1.0.8", - "@firebase/firestore": "4.7.3", - "@firebase/firestore-compat": "0.3.38", - "@firebase/functions": "0.11.8", - "@firebase/functions-compat": "0.3.14", - "@firebase/installations": "0.6.9", - "@firebase/installations-compat": "0.2.9", - "@firebase/messaging": "0.12.11", - "@firebase/messaging-compat": "0.2.11", - "@firebase/performance": "0.6.9", - "@firebase/performance-compat": "0.2.9", - "@firebase/remote-config": "0.4.9", - "@firebase/remote-config-compat": "0.2.9", - "@firebase/storage": "0.13.2", - "@firebase/storage-compat": "0.3.12", - "@firebase/util": "1.10.0", - "@firebase/vertexai-preview": "0.0.4" + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-12.0.0.tgz", + "integrity": "sha512-KV+OrMJpi2uXlqL2zaCcXb7YuQbY/gMIWT1hf8hKeTW1bSumWaHT5qfmn0WTpHwKQa3QEVOtZR2ta9EchcmYuw==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/ai": "2.0.0", + "@firebase/analytics": "0.10.18", + "@firebase/analytics-compat": "0.2.24", + "@firebase/app": "0.14.0", + "@firebase/app-check": "0.11.0", + "@firebase/app-check-compat": "0.4.0", + "@firebase/app-compat": "0.5.0", + "@firebase/app-types": "0.9.3", + "@firebase/auth": "1.11.0", + "@firebase/auth-compat": "0.6.0", + "@firebase/data-connect": "0.3.11", + "@firebase/database": "1.1.0", + "@firebase/database-compat": "2.1.0", + "@firebase/firestore": "4.9.0", + "@firebase/firestore-compat": "0.4.0", + "@firebase/functions": "0.13.0", + "@firebase/functions-compat": "0.4.0", + "@firebase/installations": "0.6.19", + "@firebase/installations-compat": "0.2.19", + "@firebase/messaging": "0.12.23", + "@firebase/messaging-compat": "0.2.23", + "@firebase/performance": "0.7.8", + "@firebase/performance-compat": "0.2.21", + "@firebase/remote-config": "0.6.6", + "@firebase/remote-config-compat": "0.2.19", + "@firebase/storage": "0.14.0", + "@firebase/storage-compat": "0.4.0", + "@firebase/util": "1.13.0" } }, "node_modules/firebase-admin": { @@ -5395,6 +6208,21 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/firebase-tools/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/firebase-tools/node_modules/rimraf": { "version": "5.0.10", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", @@ -5422,6 +6250,119 @@ "node": ">=10" } }, + "node_modules/firebase-tools/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/firebase/node_modules/@firebase/app-check-interop-types": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz", + "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==", + "license": "Apache-2.0" + }, + "node_modules/firebase/node_modules/@firebase/app-types": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz", + "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==", + "license": "Apache-2.0" + }, + "node_modules/firebase/node_modules/@firebase/auth-interop-types": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz", + "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==", + "license": "Apache-2.0" + }, + "node_modules/firebase/node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/firebase/node_modules/@firebase/database": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.1.0.tgz", + "integrity": "sha512-gM6MJFae3pTyNLoc9VcJNuaUDej0ctdjn3cVtILo3D5lpp0dmUHHLFN/pUKe7ImyeB1KAvRlEYxvIHNF04Filg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/firebase/node_modules/@firebase/database-compat": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.1.0.tgz", + "integrity": "sha512-8nYc43RqxScsePVd1qe1xxvWNf0OBnbwHxmXJ7MHSuuTVYFO3eLyLW3PiCKJ9fHnmIz4p4LbieXwz+qtr9PZDg==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/database": "1.1.0", + "@firebase/database-types": "1.0.16", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/firebase/node_modules/@firebase/database-types": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.16.tgz", + "integrity": "sha512-xkQLQfU5De7+SPhEGAXFBnDryUWhhlFXelEg2YeZOQMCdoe7dL64DDAd77SQsR+6uoXIZY5MB4y/inCs4GTfcw==", + "license": "Apache-2.0", + "dependencies": { + "@firebase/app-types": "0.9.3", + "@firebase/util": "1.13.0" + } + }, + "node_modules/firebase/node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/firebase/node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/fn.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", @@ -5455,13 +6396,15 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -5644,13 +6587,24 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5666,6 +6620,19 @@ "node": ">=8.0.0" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stdin": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", @@ -5891,12 +6858,12 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5929,20 +6896,10 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -5951,11 +6908,14 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, "engines": { "node": ">= 0.4" }, @@ -5978,7 +6938,9 @@ } }, "node_modules/hasown": { - "version": "2.0.0", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -6137,7 +7099,8 @@ "node_modules/idb": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", - "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", + "license": "ISC" }, "node_modules/ieee754": { "version": "1.2.1", @@ -6302,9 +7265,24 @@ "save-to-github-cache": "bin/save-to-github-cache.js" } }, - "node_modules/ip": { - "version": "2.0.0", - "license": "MIT" + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause" }, "node_modules/ip-regex": { "version": "4.3.0", @@ -6448,6 +7426,19 @@ "license": "MIT", "optional": true }, + "node_modules/is-network-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", + "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-npm": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", @@ -6487,6 +7478,12 @@ "node": ">=8" } }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -6737,6 +7734,35 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-changed-files/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-changed-files/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/jest-circus": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", @@ -6769,6 +7795,35 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-circus/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-circus/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/jest-cli": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", @@ -7111,6 +8166,35 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-runner/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-runner/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/jest-runtime": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", @@ -7297,9 +8381,9 @@ } }, "node_modules/jose": { - "version": "4.15.4", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz", - "integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==", + "version": "4.15.9", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", + "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" @@ -7323,6 +8407,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT" + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -7944,6 +9034,15 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -7954,10 +9053,13 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "license": "MIT" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -7976,13 +9078,13 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -8044,9 +9146,9 @@ } }, "node_modules/minimatch/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -8171,16 +9273,16 @@ "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" }, "node_modules/morgan": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", - "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz", + "integrity": "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==", "license": "MIT", "dependencies": { "basic-auth": "~2.0.1", "debug": "2.6.9", "depd": "~2.0.0", "on-finished": "~2.3.0", - "on-headers": "~1.0.2" + "on-headers": "~1.1.0" }, "engines": { "node": ">= 0.8.0" @@ -8460,8 +9562,13 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -8479,9 +9586,9 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -8582,15 +9689,16 @@ } }, "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz", + "integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==", + "dev": true, "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "yocto-queue": "^1.1.1" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8641,6 +9749,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-retry": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", + "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-throttle": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/p-throttle/-/p-throttle-5.1.0.tgz", @@ -8704,21 +9830,18 @@ } }, "node_modules/pac-resolver": { - "version": "7.0.0", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", "license": "MIT", "dependencies": { "degenerator": "^5.0.0", - "ip": "^1.1.8", "netmask": "^2.0.2" }, "engines": { "node": ">= 14" } }, - "node_modules/pac-resolver/node_modules/ip": { - "version": "1.1.8", - "license": "MIT" - }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -8835,9 +9958,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, "node_modules/pg": { @@ -8922,9 +10045,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { @@ -9302,12 +10425,12 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -9601,44 +10724,30 @@ } }, "node_modules/router": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/router/-/router-1.3.8.tgz", - "integrity": "sha512-461UFH44NtSfIlS83PUg2N7OZo86BC/kB3dY77gJdsODsBhhw7+2uE0tzTINxrY9CahCUVk1VhpWCA5i1yoIEg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", "license": "MIT", "dependencies": { - "array-flatten": "3.0.0", - "debug": "2.6.9", - "methods": "~1.1.2", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "setprototypeof": "1.2.0", - "utils-merge": "1.0.1" + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 18" } }, - "node_modules/router/node_modules/array-flatten": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-3.0.0.tgz", - "integrity": "sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==", - "license": "MIT" - }, - "node_modules/router/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/router/node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">=16" } }, - "node_modules/router/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -9714,9 +10823,9 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -9765,38 +10874,34 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/set-blocking": { + "node_modules/serve-static/node_modules/encodeurl": { "version": "2.0.0", - "license": "ISC", - "optional": true - }, - "node_modules/set-function-length": { - "version": "1.1.1", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, "engines": { - "node": ">= 0.4" + "node": ">= 0.8" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "license": "ISC", + "optional": true + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -9825,12 +10930,72 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9896,14 +11061,16 @@ } }, "node_modules/socks": { - "version": "2.7.1", + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.6.tgz", + "integrity": "sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA==", "license": "MIT", "dependencies": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, @@ -10190,17 +11357,16 @@ "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==" }, "node_modules/superstatic": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/superstatic/-/superstatic-9.0.3.tgz", - "integrity": "sha512-e/tmW0bsnQ/33ivK6y3CapJT0Ovy4pk/ohNPGhIAGU2oasoNLRQ1cv6enua09NU9w6Y0H/fBu07cjzuiWvLXxw==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/superstatic/-/superstatic-9.2.0.tgz", + "integrity": "sha512-QrJAJIpAij0jJT1nEwYTB0SzDi4k0wYygu6GxK0ko8twiQgfgaOAZ7Hu99p02MTAsGho753zhzSvsw8We4PBEQ==", "license": "MIT", "dependencies": { - "basic-auth-connect": "^1.0.0", + "basic-auth-connect": "^1.1.0", "commander": "^10.0.0", "compression": "^1.7.0", "connect": "^3.7.0", "destroy": "^1.0.4", - "fast-url-parser": "^1.1.3", "glob-slasher": "^1.0.1", "is-url": "^1.2.2", "join-path": "^1.1.1", @@ -10210,15 +11376,15 @@ "morgan": "^1.8.2", "on-finished": "^2.2.0", "on-headers": "^1.0.0", - "path-to-regexp": "^1.8.0", - "router": "^1.3.1", + "path-to-regexp": "^1.9.0", + "router": "^2.0.0", "update-notifier-cjs": "^5.1.6" }, "bin": { "superstatic": "lib/bin/server.js" }, "engines": { - "node": "^14.18.0 || >=16.4.0" + "node": "18 || 20 || 22" }, "optionalDependencies": { "re2": "^1.17.7" @@ -10249,9 +11415,9 @@ } }, "node_modules/superstatic/node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", "license": "MIT", "dependencies": { "isarray": "0.0.1" @@ -10298,9 +11464,9 @@ } }, "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "license": "ISC", "dependencies": { "chownr": "^2.0.0", @@ -10503,16 +11669,6 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -10622,6 +11778,15 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "license": "0BSD" }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "license": "MIT", + "engines": { + "node": ">=0.6.x" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -10680,14 +11845,6 @@ "node": ">=14.17" } }, - "node_modules/undici": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.7.tgz", - "integrity": "sha512-HR3W/bMGPSr90i8AAp2C4DM3wChFdJPLrWYpIS++LxS8K+W535qftjt+4MyjNYHeWabMj1nvtmLIi7l++iq91A==", - "engines": { - "node": ">=18.17" - } - }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", @@ -10929,6 +12086,12 @@ "defaults": "^1.0.3" } }, + "node_modules/web-vitals": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz", + "integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==", + "license": "Apache-2.0" + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -11184,12 +12347,13 @@ } }, "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", + "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", + "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" diff --git a/integration_test/package.json b/integration_test/package.json index 0de81843e..85eb6a0d1 100644 --- a/integration_test/package.json +++ b/integration_test/package.json @@ -5,7 +5,7 @@ "dependencies": { "@google-cloud/eventarc": "^3.1.0", "@google-cloud/tasks": "^5.1.0", - "firebase": "^10.14.0", + "firebase": "^12.0.0", "firebase-admin": "^12.6.0", "firebase-tools": "^13.20.2", "js-yaml": "^4.1.0", @@ -21,6 +21,8 @@ "@types/js-yaml": "^4.0.9", "@types/node-fetch": "^2.6.11", "jest": "^29.7.0", + "p-limit": "^6.2.0", + "p-retry": "^6.2.1", "ts-jest": "^29.1.1" } } diff --git a/integration_test/run.ts b/integration_test/run.ts index 0759fff8e..217c717b4 100644 --- a/integration_test/run.ts +++ b/integration_test/run.ts @@ -7,6 +7,7 @@ import { getRuntimeDelegate } from "firebase-tools/lib/deploy/functions/runtimes import { detectFromPort } from "firebase-tools/lib/deploy/functions/runtimes/discovery/index.js"; import setup from "./setup.js"; import { loadEnv } from "./utils.js"; +import { deployFunctionsWithRetry, postCleanup } from "./deployment-utils.js"; loadEnv(); @@ -83,7 +84,18 @@ const env = { STORAGE_REGION, }; -let modifiedYaml: any; +interface EndpointConfig { + project?: string; + runtime?: string; + [key: string]: unknown; +} + +interface ModifiedYaml { + endpoints: Record; + specVersion: string; +} + +let modifiedYaml: ModifiedYaml | undefined; function generateUniqueHash(originalName: string): string { // Function name can only contain letters, numbers and hyphens and be less than 100 chars. @@ -108,14 +120,19 @@ async function discoverAndModifyEndpoints() { const killServer = await delegate.serveAdmin(port.toString(), {}, env); console.log("Started on port", port); - const originalYaml = await detectFromPort(port, config.projectId, config.runtime, 10000); + const originalYaml = (await detectFromPort( + port, + config.projectId, + config.runtime, + 10000 + )) as ModifiedYaml; modifiedYaml = { ...originalYaml, endpoints: Object.fromEntries( Object.entries(originalYaml.endpoints).map(([key, value]) => { const modifiedKey = generateUniqueHash(key); - const modifiedValue: any = value; + const modifiedValue: EndpointConfig = { ...value }; delete modifiedValue.project; delete modifiedValue.runtime; return [modifiedKey, modifiedValue]; @@ -145,17 +162,11 @@ function writeFunctionsYaml(filePath: string, data: any): void { async function deployModifiedFunctions(): Promise { console.log("Deploying functions with id:", TEST_RUN_ID); try { - const targetNames = ["functions", "database", "firestore"]; - const options = { - targetNames, - project: config.projectId, - config: "./firebase.json", - debug: true, - nonInteractive: true, - force: true, - }; + // Get the function names that will be deployed + const functionNames = modifiedYaml ? Object.keys(modifiedYaml.endpoints) : []; - await client.deploy(options); + // Deploy with rate limiting and retry logic + await deployFunctionsWithRetry(client, functionNames); console.log("Functions have been deployed successfully."); } catch (err) { @@ -229,21 +240,41 @@ const spawnAsync = (command: string, args: string[], options: any): Promise { output += data.toString(); }); } + if (child.stderr) { + child.stderr.on("data", (data) => { + errorOutput += data.toString(); + }); + } + child.on("error", reject); child.on("close", (code) => { if (code === 0) { resolve(output); } else { - reject(new Error(`Command failed with exit code ${code}`)); + const errorMessage = `Command failed with exit code ${code}`; + const fullError = errorOutput ? `${errorMessage}\n\nSTDERR:\n${errorOutput}` : errorMessage; + reject(new Error(fullError)); } }); + + // Add timeout to prevent hanging + const timeout = setTimeout(() => { + child.kill(); + reject(new Error(`Command timed out after 5 minutes: ${command} ${args.join(" ")}`)); + }, 5 * 60 * 1000); // 5 minutes + + child.on("close", () => { + clearTimeout(timeout); + }); }); }; @@ -251,26 +282,32 @@ async function runTests(): Promise { const humanReadableRuntime = TEST_RUNTIME === "node" ? "Node.js" : "Python"; try { console.log(`Starting ${humanReadableRuntime} Tests...`); + console.log("🔍 About to run: npm test"); + const output = await spawnAsync("npm", ["test"], { env: { ...process.env, TEST_RUN_ID, }, - stdio: "inherit", }); + + console.log("📋 Test output received:"); console.log(output); console.log(`${humanReadableRuntime} Tests Completed.`); } catch (error) { - console.error("Error during testing:", error); + console.error("❌ Error during testing:", error); throw error; } } async function handleCleanUp(): Promise { console.log("Cleaning up..."); - if (modifiedYaml) { - const endpoints = Object.keys(modifiedYaml.endpoints); - await removeDeployedFunctions(endpoints); + try { + // Use our new post-cleanup utility with rate limiting + await postCleanup(client, TEST_RUN_ID); + } catch (err) { + console.error("Error during post-cleanup:", err); + // Don't throw here to ensure files are still cleaned } cleanFiles(); } @@ -285,13 +322,17 @@ async function runIntegrationTests(): Promise { process.on("SIGINT", gracefulShutdown); try { + // Skip pre-cleanup for now to test if the main flow works + console.log("⏭️ Skipping pre-cleanup for testing..."); + const killServer = await discoverAndModifyEndpoints(); await deployModifiedFunctions(); await killServer(); await runTests(); } catch (err) { - console.error("Error occurred during integration tests", err); - throw new Error("Integration tests failed"); + console.error("Error occurred during integration tests:", err); + // Re-throw the original error instead of wrapping it + throw err; } finally { await handleCleanUp(); } From 05fd26b04972e2dfaed0c770e6dae0858c50d2fd Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Mon, 11 Aug 2025 14:29:44 +0100 Subject: [PATCH 17/25] refactor: add initial refactor work --- integration_test/package-lock.json | 580 ++++++++++++++++++++++++++--- integration_test/package.json | 5 +- integration_test/run.ts | 43 +-- integration_test/setup-local.ts | 4 +- integration_test/src/cleanup.ts | 65 ++++ integration_test/src/config.ts | 142 +++++++ integration_test/src/deployment.ts | 107 ++++++ integration_test/src/index.ts | 61 +++ integration_test/src/logger.ts | 165 ++++++++ integration_test/src/process.ts | 67 ++++ integration_test/src/run.ts | 6 + integration_test/utils.ts | 17 - 12 files changed, 1151 insertions(+), 111 deletions(-) create mode 100644 integration_test/src/cleanup.ts create mode 100644 integration_test/src/config.ts create mode 100644 integration_test/src/deployment.ts create mode 100644 integration_test/src/index.ts create mode 100644 integration_test/src/logger.ts create mode 100644 integration_test/src/process.ts create mode 100644 integration_test/src/run.ts delete mode 100644 integration_test/utils.ts diff --git a/integration_test/package-lock.json b/integration_test/package-lock.json index 15f704625..6ce6319d6 100644 --- a/integration_test/package-lock.json +++ b/integration_test/package-lock.json @@ -18,10 +18,13 @@ "@types/jest": "^29.5.11", "@types/js-yaml": "^4.0.9", "@types/node-fetch": "^2.6.11", + "chalk": "^5.5.0", + "dotenv": "^17.2.1", "jest": "^29.7.0", "p-limit": "^6.2.0", "p-retry": "^6.2.1", - "ts-jest": "^29.1.1" + "ts-jest": "^29.1.1", + "zod": "^4.0.17" } }, "node_modules/@ampproject/remapping": { @@ -2213,6 +2216,34 @@ "node": ">=6" } }, + "node_modules/@inquirer/external-editor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.0.tgz", + "integrity": "sha512-5v3YXc5ZMfL6OJqXPrX9csb4l7NlQA2doO1yynUjpUChT9hg4JcuBVP0RbsEJ/3SL/sxWEyFjT2W69ZhtoBWqg==", + "license": "MIT", + "dependencies": { + "chardet": "^2.1.0", + "iconv-lite": "^0.6.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/external-editor/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -2379,6 +2410,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/@jest/core": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", @@ -2427,6 +2475,23 @@ } } }, + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/@jest/environment": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", @@ -2548,6 +2613,23 @@ } } }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", @@ -2666,6 +2748,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/@jest/transform/node_modules/write-file-atomic": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", @@ -2698,6 +2797,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -3698,6 +3814,23 @@ "@babel/core": "^7.8.0" } }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/babel-plugin-istanbul": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", @@ -3929,6 +4062,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/boxen/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/boxen/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -4213,16 +4362,12 @@ "license": "CC-BY-4.0" }, "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz", + "integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==", "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" @@ -4238,9 +4383,9 @@ } }, "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.0.tgz", + "integrity": "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==", "license": "MIT" }, "node_modules/chokidar": { @@ -4364,6 +4509,22 @@ "npm": ">=5.0.0" } }, + "node_modules/cli-highlight/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/cli-highlight/node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -4946,6 +5107,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/create-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/cross-env": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.1.tgz", @@ -5252,6 +5430,19 @@ "node": ">=8" } }, + "node_modules/dotenv": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz", + "integrity": "sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -5811,32 +6002,6 @@ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "license": "MIT" }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "license": "MIT", - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/external-editor/node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/farmhash-modern": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/farmhash-modern/-/farmhash-modern-1.1.0.tgz", @@ -7199,16 +7364,16 @@ "license": "ISC" }, "node_modules/inquirer": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", - "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "version": "8.2.7", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.7.tgz", + "integrity": "sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA==", "license": "MIT", "dependencies": { + "@inquirer/external-editor": "^1.0.0", "ansi-escapes": "^4.2.1", "chalk": "^4.1.1", "cli-cursor": "^3.1.0", "cli-width": "^3.0.0", - "external-editor": "^3.0.3", "figures": "^3.0.0", "lodash": "^4.17.21", "mute-stream": "0.0.8", @@ -7242,6 +7407,22 @@ "inquirer": "^8.0.0" } }, + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/inquirer/node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -7795,6 +7976,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jest-circus/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -7858,6 +8056,23 @@ } } }, + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jest-config": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", @@ -7904,6 +8119,23 @@ } } }, + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -7920,6 +8152,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jest-docblock": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", @@ -7950,6 +8199,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jest-environment-node": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", @@ -8034,6 +8300,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jest-message-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", @@ -8055,6 +8338,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jest-mock": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", @@ -8133,6 +8433,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jest-runner": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", @@ -8166,6 +8483,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jest-runner/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -8229,6 +8563,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jest-snapshot": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", @@ -8261,6 +8612,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jest-snapshot/node_modules/semver": { "version": "7.5.4", "dev": true, @@ -8293,6 +8661,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jest-validate": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", @@ -8311,6 +8696,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jest-watcher": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", @@ -8331,6 +8733,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jest-worker": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", @@ -8807,6 +9226,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/logform": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", @@ -9023,17 +9458,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/marked-terminal/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -9671,13 +10095,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/p-defer": { @@ -11655,9 +12086,10 @@ } }, "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "license": "MIT", "engines": { "node": ">=14.14" } @@ -11981,6 +12413,22 @@ "node": ">=14" } }, + "node_modules/update-notifier-cjs/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/update-notifier-cjs/node_modules/semver": { "version": "7.5.4", "license": "ISC", @@ -12409,6 +12857,16 @@ "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } + }, + "node_modules/zod": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.17.tgz", + "integrity": "sha512-1PHjlYRevNxxdy2JZ8JcNAw7rX8V9P1AKkP+x/xZfxB0K5FYfuV+Ug6P/6NVSR2jHQ+FzDDoDHS04nYUsOIyLQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/integration_test/package.json b/integration_test/package.json index 85eb6a0d1..c439fa323 100644 --- a/integration_test/package.json +++ b/integration_test/package.json @@ -20,9 +20,12 @@ "@types/jest": "^29.5.11", "@types/js-yaml": "^4.0.9", "@types/node-fetch": "^2.6.11", + "chalk": "^5.5.0", + "dotenv": "^17.2.1", "jest": "^29.7.0", "p-limit": "^6.2.0", "p-retry": "^6.2.1", - "ts-jest": "^29.1.1" + "ts-jest": "^29.1.1", + "zod": "^4.0.17" } } diff --git a/integration_test/run.ts b/integration_test/run.ts index 217c717b4..3822f74c1 100644 --- a/integration_test/run.ts +++ b/integration_test/run.ts @@ -6,10 +6,10 @@ import client from "firebase-tools"; import { getRuntimeDelegate } from "firebase-tools/lib/deploy/functions/runtimes/index.js"; import { detectFromPort } from "firebase-tools/lib/deploy/functions/runtimes/discovery/index.js"; import setup from "./setup.js"; -import { loadEnv } from "./utils.js"; +import * as dotenv from "dotenv"; import { deployFunctionsWithRetry, postCleanup } from "./deployment-utils.js"; -loadEnv(); +dotenv.config(); let { DEBUG, @@ -49,21 +49,26 @@ if (!["node", "python"].includes(TEST_RUNTIME)) { process.exit(1); } -if (!FIREBASE_ADMIN && TEST_RUNTIME === "node") { - FIREBASE_ADMIN = "^12.0.0"; -} +// TypeScript type guard to ensure TEST_RUNTIME is the correct type +const validRuntimes = ["node", "python"] as const; +type ValidRuntime = (typeof validRuntimes)[number]; +const runtime: ValidRuntime = TEST_RUNTIME as ValidRuntime; -if (!FIREBASE_ADMIN && TEST_RUNTIME === "python") { +if (!FIREBASE_ADMIN && runtime === "node") { + FIREBASE_ADMIN = "^12.0.0"; +} else if (!FIREBASE_ADMIN && runtime === "python") { FIREBASE_ADMIN = "6.5.0"; +} else if (!FIREBASE_ADMIN) { + throw new Error("FIREBASE_ADMIN is not set"); } -setup(TEST_RUNTIME as "node" | "python", TEST_RUN_ID, NODE_VERSION, FIREBASE_ADMIN!); +setup(runtime, TEST_RUN_ID, NODE_VERSION, FIREBASE_ADMIN); const config = { projectId: PROJECT_ID, projectDir: process.cwd(), sourceDir: `${process.cwd()}/functions`, - runtime: TEST_RUNTIME === "node" ? "nodejs18" : "python311", + runtime: runtime === "node" ? "nodejs18" : "python311", }; console.log("Firebase config created: "); @@ -175,28 +180,6 @@ async function deployModifiedFunctions(): Promise { } } -async function removeDeployedFunctions(functionNames: string[]): Promise { - console.log("Removing deployed functions..."); - - try { - const options = { - project: config.projectId, - config: "./firebase.json", - debug: true, - nonInteractive: true, - force: true, - }; - - console.log("Removing functions with id:", TEST_RUN_ID); - await client.functions.delete(functionNames, options); - - console.log("Deployed functions have been removed."); - } catch (err) { - console.error("Error removing deployed functions. Exiting.", err); - process.exit(1); - } -} - function cleanFiles(): void { console.log("Cleaning files..."); const functionsDir = "functions"; diff --git a/integration_test/setup-local.ts b/integration_test/setup-local.ts index 1ca037f40..c2c3b533e 100644 --- a/integration_test/setup-local.ts +++ b/integration_test/setup-local.ts @@ -1,6 +1,6 @@ import setup from "./setup"; -import { loadEnv } from "./utils"; +import * as dotenv from "dotenv"; -loadEnv(); +dotenv.config(); setup("node", "local", "18", "^12.0.0"); diff --git a/integration_test/src/cleanup.ts b/integration_test/src/cleanup.ts new file mode 100644 index 000000000..fe4737842 --- /dev/null +++ b/integration_test/src/cleanup.ts @@ -0,0 +1,65 @@ +import fs from "fs"; +import { logError, logCleanup } from "./logger.js"; + +export function cleanFiles(testRunId: string): void { + logCleanup("Cleaning files..."); + const functionsDir = "functions"; + process.chdir(functionsDir); // go to functions + try { + const files = fs.readdirSync("."); + files.forEach((file) => { + // For Node + if (file.match(`firebase-functions-${testRunId}.tgz`)) { + fs.rmSync(file); + } + // For Python + if (file.match(`firebase_functions.tar.gz`)) { + fs.rmSync(file); + } + if (file.match("package.json")) { + fs.rmSync(file); + } + if (file.match("requirements.txt")) { + fs.rmSync(file); + } + if (file.match("firebase-debug.log")) { + fs.rmSync(file); + } + if (file.match("functions.yaml")) { + fs.rmSync(file); + } + }); + + fs.rmSync("lib", { recursive: true, force: true }); + fs.rmSync("venv", { recursive: true, force: true }); + } catch (error) { + logError("Error occurred while cleaning files:", error as Error); + } + + process.chdir("../"); // go back to integration_test +} + +export async function handleCleanUp(client: any, testRunId: string): Promise { + logCleanup("Cleaning up..."); + try { + // Import postCleanup from deployment-utils + const { postCleanup } = await import("../deployment-utils.js"); + await postCleanup(client, testRunId); + } catch (err) { + logError("Error during post-cleanup:", err as Error); + // Don't throw here to ensure files are still cleaned + } + cleanFiles(testRunId); +} + +export function gracefulShutdown(cleanupFn: () => Promise): void { + console.log("SIGINT received..."); + cleanupFn() + .then(() => { + process.exit(1); + }) + .catch((error) => { + logError("Error during graceful shutdown:", error); + process.exit(1); + }); +} diff --git a/integration_test/src/config.ts b/integration_test/src/config.ts new file mode 100644 index 000000000..ed1edc78a --- /dev/null +++ b/integration_test/src/config.ts @@ -0,0 +1,142 @@ +import * as z from "zod/mini"; + +// Load English locale for better error messages +z.config(z.locales.en()); + +export interface TestConfig { + projectId: string; + testRunId: string; + runtime: "node" | "python"; + nodeVersion: string; + firebaseAdmin: string; + region: string; + storageRegion: string; + debug?: string; + databaseUrl: string; + storageBucket: string; + firebaseAppId: string; + firebaseMeasurementId: string; + firebaseAuthDomain: string; + firebaseApiKey: string; + googleAnalyticsApiSecret: string; +} + +// Environment validation schema +const environmentSchema = z.object({ + PROJECT_ID: z.string().check(z.minLength(1, "PROJECT_ID is required")), + DATABASE_URL: z.string().check(z.minLength(1, "DATABASE_URL is required")), + STORAGE_BUCKET: z.string().check(z.minLength(1, "STORAGE_BUCKET is required")), + FIREBASE_APP_ID: z.string().check(z.minLength(1, "FIREBASE_APP_ID is required")), + FIREBASE_MEASUREMENT_ID: z.string().check(z.minLength(1, "FIREBASE_MEASUREMENT_ID is required")), + FIREBASE_AUTH_DOMAIN: z.string().check(z.minLength(1, "FIREBASE_AUTH_DOMAIN is required")), + FIREBASE_API_KEY: z.string().check(z.minLength(1, "FIREBASE_API_KEY is required")), + GOOGLE_ANALYTICS_API_SECRET: z + .string() + .check(z.minLength(1, "GOOGLE_ANALYTICS_API_SECRET is required")), + TEST_RUNTIME: z.enum(["node", "python"]), + NODE_VERSION: z.optional(z.string()), + FIREBASE_ADMIN: z.optional(z.string()), + REGION: z.optional(z.string()), + STORAGE_REGION: z.optional(z.string()), + DEBUG: z.optional(z.string()), +}); + +/** + * Validates that all required environment variables are set and have valid values. + * Exits the process with code 1 if validation fails. + */ +export function validateEnvironment(): void { + try { + environmentSchema.parse(process.env); + } catch (error) { + console.error("Environment validation failed:"); + if (error && typeof error === "object" && "errors" in error) { + const zodError = error as { errors: Array<{ path: string[]; message: string }> }; + zodError.errors.forEach((err) => { + console.error(` ${err.path.join(".")}: ${err.message}`); + }); + } else { + console.error("Unexpected error during environment validation:", error); + } + process.exit(1); + } +} + +/** + * Loads and validates environment configuration, returning a typed config object. + * @returns TestConfig object with all validated environment variables + */ +export function loadConfig(): TestConfig { + // Validate environment first to ensure all required variables are set + const validatedEnv = environmentSchema.parse(process.env); + + // TypeScript type guard to ensure TEST_RUNTIME is the correct type + const validRuntimes = ["node", "python"] as const; + type ValidRuntime = (typeof validRuntimes)[number]; + const runtime: ValidRuntime = validatedEnv.TEST_RUNTIME; + + let firebaseAdmin = validatedEnv.FIREBASE_ADMIN; + if (!firebaseAdmin && runtime === "node") { + firebaseAdmin = "^12.0.0"; + } else if (!firebaseAdmin && runtime === "python") { + firebaseAdmin = "6.5.0"; + } else if (!firebaseAdmin) { + throw new Error("FIREBASE_ADMIN is not set"); + } + + const testRunId = `t${Date.now()}`; + + return { + projectId: validatedEnv.PROJECT_ID, + testRunId, + runtime, + nodeVersion: validatedEnv.NODE_VERSION ?? "18", + firebaseAdmin, + region: validatedEnv.REGION ?? "us-central1", + storageRegion: validatedEnv.STORAGE_REGION ?? "us-central1", + debug: validatedEnv.DEBUG, + databaseUrl: validatedEnv.DATABASE_URL, + storageBucket: validatedEnv.STORAGE_BUCKET, + firebaseAppId: validatedEnv.FIREBASE_APP_ID, + firebaseMeasurementId: validatedEnv.FIREBASE_MEASUREMENT_ID, + firebaseAuthDomain: validatedEnv.FIREBASE_AUTH_DOMAIN, + firebaseApiKey: validatedEnv.FIREBASE_API_KEY, + googleAnalyticsApiSecret: validatedEnv.GOOGLE_ANALYTICS_API_SECRET, + }; +} + +/** + * Creates Firebase configuration object for deployment. + * @param config - The test configuration object + * @returns Firebase configuration object + */ +export function createFirebaseConfig(config: TestConfig) { + return { + projectId: config.projectId, + projectDir: process.cwd(), + sourceDir: `${process.cwd()}/functions`, + runtime: config.runtime === "node" ? "nodejs18" : "python311", + }; +} + +/** + * Creates environment configuration for function deployment. + * @param config - The test configuration object + * @returns Environment configuration object + */ +export function createEnvironmentConfig(config: TestConfig) { + const firebaseConfig = { + databaseURL: config.databaseUrl, + projectId: config.projectId, + storageBucket: config.storageBucket, + }; + + return { + DEBUG: config.debug, + FIRESTORE_PREFER_REST: "true", + GCLOUD_PROJECT: config.projectId, + FIREBASE_CONFIG: JSON.stringify(firebaseConfig), + REGION: config.region, + STORAGE_REGION: config.storageRegion, + }; +} diff --git a/integration_test/src/deployment.ts b/integration_test/src/deployment.ts new file mode 100644 index 000000000..8d49798d9 --- /dev/null +++ b/integration_test/src/deployment.ts @@ -0,0 +1,107 @@ +import fs from "fs"; +import yaml from "js-yaml"; +import portfinder from "portfinder"; +import { getRuntimeDelegate } from "firebase-tools/lib/deploy/functions/runtimes/index.js"; +import { detectFromPort } from "firebase-tools/lib/deploy/functions/runtimes/discovery/index.js"; +import { logError, logDeployment } from "./logger.js"; +import { TestConfig } from "./config.js"; + +export interface EndpointConfig { + project?: string; + runtime?: string; + [key: string]: unknown; +} + +export interface ModifiedYaml { + endpoints: Record; + specVersion: string; +} + +export function generateUniqueHash(originalName: string, testRunId: string): string { + // Function name can only contain letters, numbers and hyphens and be less than 100 chars. + const modifiedName = `${testRunId}-${originalName}`; + if (modifiedName.length > 100) { + throw new Error( + `Function name is too long. Original=${originalName}, Modified=${modifiedName}` + ); + } + return modifiedName; +} + +export function writeFunctionsYaml(filePath: string, data: any): void { + try { + fs.writeFileSync(filePath, yaml.dump(data)); + } catch (err) { + logError("Error writing functions.yaml. Exiting.", err as Error); + process.exit(1); + } +} + +/** + * Discovers endpoints and modifies functions.yaml file. + * @returns A promise that resolves with a function to kill the server. + */ +export async function discoverAndModifyEndpoints( + config: TestConfig, + firebaseConfig: any, + env: any +): Promise<{ killServer: () => void; modifiedYaml: ModifiedYaml }> { + logDeployment("Discovering endpoints..."); + try { + const port = await portfinder.getPortPromise({ port: 9000 }); + const delegate = await getRuntimeDelegate(firebaseConfig); + const killServer = await delegate.serveAdmin(port.toString(), {}, env); + + console.log("Started on port", port); + const originalYaml = (await detectFromPort( + port, + firebaseConfig.projectId, + firebaseConfig.runtime, + 10000 + )) as ModifiedYaml; + + const modifiedYaml: ModifiedYaml = { + ...originalYaml, + endpoints: Object.fromEntries( + Object.entries(originalYaml.endpoints).map(([key, value]) => { + const modifiedKey = generateUniqueHash(key, config.testRunId); + const modifiedValue: EndpointConfig = { ...value }; + delete modifiedValue.project; + delete modifiedValue.runtime; + return [modifiedKey, modifiedValue]; + }) + ), + specVersion: "v1alpha1", + }; + + writeFunctionsYaml("./functions/functions.yaml", modifiedYaml); + + return { killServer, modifiedYaml }; + } catch (err) { + logError("Error discovering endpoints. Exiting.", err as Error); + process.exit(1); + } +} + +export async function deployModifiedFunctions( + client: any, + modifiedYaml: ModifiedYaml, + testRunId: string +): Promise { + logDeployment(`Deploying functions with id: ${testRunId}`); + try { + // Get the function names that will be deployed + const functionNames = Object.keys(modifiedYaml.endpoints); + + // Import deployFunctionsWithRetry from deployment-utils + const { deployFunctionsWithRetry } = await import("../deployment-utils.js"); + + // Deploy with rate limiting and retry logic + await deployFunctionsWithRetry(client, functionNames); + + logDeployment("Functions have been deployed successfully."); + } catch (err) { + logError("Error deploying functions. Exiting.", err as Error); + throw err; + } +} diff --git a/integration_test/src/index.ts b/integration_test/src/index.ts new file mode 100644 index 000000000..f31b94a35 --- /dev/null +++ b/integration_test/src/index.ts @@ -0,0 +1,61 @@ +import * as dotenv from "dotenv"; +import client from "firebase-tools"; +import setup from "../setup.js"; +import { + validateEnvironment, + loadConfig, + createFirebaseConfig, + createEnvironmentConfig, +} from "./config"; +import { logInfo, logError } from "./logger"; +import { handleCleanUp, gracefulShutdown } from "./cleanup"; +import { discoverAndModifyEndpoints, deployModifiedFunctions } from "./deployment.js"; +import { runTests } from "./process"; + +export async function runIntegrationTests(): Promise { + // Load environment variables + dotenv.config(); + + // Validate environment + validateEnvironment(); + + // Load configuration + const config = loadConfig(); + + // Setup SDK and functions + setup(config.runtime, config.testRunId, config.nodeVersion, config.firebaseAdmin); + + // Create Firebase and environment configs + const firebaseConfig = createFirebaseConfig(config); + const env = createEnvironmentConfig(config); + + logInfo("Firebase config created: "); + logInfo(JSON.stringify(firebaseConfig, null, 2)); + + // Set up graceful shutdown + const cleanupFn = () => handleCleanUp(client, config.testRunId); + process.on("SIGINT", () => gracefulShutdown(cleanupFn)); + + try { + // Skip pre-cleanup for now to test if the main flow works + logInfo("⏭️ Skipping pre-cleanup for testing..."); + + const { killServer, modifiedYaml } = await discoverAndModifyEndpoints( + config, + firebaseConfig, + env + ); + await deployModifiedFunctions(client, modifiedYaml, config.testRunId); + killServer(); + await runTests(config.testRunId); + } catch (err) { + logError("Error occurred during integration tests:", err as Error); + // Re-throw the original error instead of wrapping it + throw err; + } finally { + await cleanupFn(); + } +} + +// Export the main function for use in run.ts +export { runIntegrationTests as default }; diff --git a/integration_test/src/logger.ts b/integration_test/src/logger.ts new file mode 100644 index 000000000..9bce45df7 --- /dev/null +++ b/integration_test/src/logger.ts @@ -0,0 +1,165 @@ +import chalk from "chalk"; + +export enum LogLevel { + DEBUG = 0, + INFO = 1, + SUCCESS = 2, + WARNING = 3, + ERROR = 4, + NONE = 5, +} + +export class Logger { + private static instance: Logger; + private logLevel: LogLevel; + private useEmojis: boolean; + + private constructor(logLevel: LogLevel = LogLevel.INFO, useEmojis = true) { + this.logLevel = logLevel; + this.useEmojis = useEmojis; + } + + static getInstance(): Logger { + if (!Logger.instance) { + const level = process.env.LOG_LEVEL + ? LogLevel[process.env.LOG_LEVEL as keyof typeof LogLevel] || LogLevel.INFO + : LogLevel.INFO; + Logger.instance = new Logger(level); + } + return Logger.instance; + } + + setLogLevel(level: LogLevel): void { + this.logLevel = level; + } + + private formatTimestamp(): string { + return new Date().toISOString().replace("T", " ").split(".")[0]; + } + + private shouldLog(level: LogLevel): boolean { + return level >= this.logLevel; + } + + debug(message: string, ...args: any[]): void { + if (!this.shouldLog(LogLevel.DEBUG)) return; + + const timestamp = chalk.gray(this.formatTimestamp()); + const prefix = this.useEmojis ? "🔍" : "[DEBUG]"; + const formattedMsg = chalk.gray(`${prefix} ${message}`); + + console.log(`${timestamp} ${formattedMsg}`, ...args); + } + + info(message: string, ...args: any[]): void { + if (!this.shouldLog(LogLevel.INFO)) return; + + const timestamp = chalk.gray(this.formatTimestamp()); + const prefix = this.useEmojis ? "ℹ️ " : "[INFO]"; + const formattedMsg = chalk.blue(`${prefix} ${message}`); + + console.log(`${timestamp} ${formattedMsg}`, ...args); + } + + success(message: string, ...args: any[]): void { + if (!this.shouldLog(LogLevel.SUCCESS)) return; + + const timestamp = chalk.gray(this.formatTimestamp()); + const prefix = this.useEmojis ? "✅" : "[SUCCESS]"; + const formattedMsg = chalk.green(`${prefix} ${message}`); + + console.log(`${timestamp} ${formattedMsg}`, ...args); + } + + warning(message: string, ...args: any[]): void { + if (!this.shouldLog(LogLevel.WARNING)) return; + + const timestamp = chalk.gray(this.formatTimestamp()); + const prefix = this.useEmojis ? "⚠️ " : "[WARN]"; + const formattedMsg = chalk.yellow(`${prefix} ${message}`); + + console.warn(`${timestamp} ${formattedMsg}`, ...args); + } + + error(message: string, error?: Error | any, ...args: any[]): void { + if (!this.shouldLog(LogLevel.ERROR)) return; + + const timestamp = chalk.gray(this.formatTimestamp()); + const prefix = this.useEmojis ? "❌" : "[ERROR]"; + const formattedMsg = chalk.red(`${prefix} ${message}`); + + if (error instanceof Error) { + console.error(`${timestamp} ${formattedMsg}`, ...args); + console.error(chalk.red(error.stack || error.message)); + } else if (error) { + console.error(`${timestamp} ${formattedMsg}`, error, ...args); + } else { + console.error(`${timestamp} ${formattedMsg}`, ...args); + } + } + + // Special contextual loggers for test harness + cleanup(message: string, ...args: any[]): void { + if (!this.shouldLog(LogLevel.INFO)) return; + + const timestamp = chalk.gray(this.formatTimestamp()); + const prefix = this.useEmojis ? "🧹" : "[CLEANUP]"; + const formattedMsg = chalk.cyan(`${prefix} ${message}`); + + console.log(`${timestamp} ${formattedMsg}`, ...args); + } + + deployment(message: string, ...args: any[]): void { + if (!this.shouldLog(LogLevel.INFO)) return; + + const timestamp = chalk.gray(this.formatTimestamp()); + const prefix = this.useEmojis ? "🚀" : "[DEPLOY]"; + const formattedMsg = chalk.magenta(`${prefix} ${message}`); + + console.log(`${timestamp} ${formattedMsg}`, ...args); + } + + // Group related logs visually + group(title: string): void { + const line = chalk.gray("─".repeat(50)); + console.log(`\n${line}`); + console.log(chalk.bold.white(title)); + console.log(line); + } + + groupEnd(): void { + console.log(chalk.gray("─".repeat(50)) + "\n"); + } +} + +// Export singleton instance for convenience +export const logger = Logger.getInstance(); + +// Export legacy functions for backwards compatibility +export function logInfo(message: string): void { + logger.info(message); +} + +export function logError(message: string, error?: Error): void { + logger.error(message, error); +} + +export function logSuccess(message: string): void { + logger.success(message); +} + +export function logWarning(message: string): void { + logger.warning(message); +} + +export function logDebug(message: string): void { + logger.debug(message); +} + +export function logCleanup(message: string): void { + logger.cleanup(message); +} + +export function logDeployment(message: string): void { + logger.deployment(message); +} diff --git a/integration_test/src/process.ts b/integration_test/src/process.ts new file mode 100644 index 000000000..3f8dc1588 --- /dev/null +++ b/integration_test/src/process.ts @@ -0,0 +1,67 @@ +import { spawn } from "child_process"; +import { logError, logDebug } from "./logger.js"; + +export const spawnAsync = (command: string, args: string[], options: any): Promise => { + return new Promise((resolve, reject) => { + const child = spawn(command, args, options); + + let output = ""; + let errorOutput = ""; + + if (child.stdout) { + child.stdout.on("data", (data) => { + output += data.toString(); + }); + } + + if (child.stderr) { + child.stderr.on("data", (data) => { + errorOutput += data.toString(); + }); + } + + child.on("error", reject); + + child.on("close", (code) => { + if (code === 0) { + resolve(output); + } else { + const errorMessage = `Command failed with exit code ${code}`; + const fullError = errorOutput ? `${errorMessage}\n\nSTDERR:\n${errorOutput}` : errorMessage; + reject(new Error(fullError)); + } + }); + + // Add timeout to prevent hanging + const timeout = setTimeout(() => { + child.kill(); + reject(new Error(`Command timed out after 5 minutes: ${command} ${args.join(" ")}`)); + }, 5 * 60 * 1000); // 5 minutes + + child.on("close", () => { + clearTimeout(timeout); + }); + }); +}; + +export async function runTests(testRunId: string): Promise { + const humanReadableRuntime = process.env.TEST_RUNTIME === "node" ? "Node.js" : "Python"; + try { + console.log(`Starting ${humanReadableRuntime} Tests...`); + logDebug("About to run: npm test"); + + const output = await spawnAsync("npm", ["test"], { + env: { + ...process.env, + TEST_RUN_ID: testRunId, + }, + }); + + console.log("📋 Test output received:"); + console.log(output); + console.log(`${humanReadableRuntime} Tests Completed.`); + } catch (error) { + logError("❌ Error during testing:", error as Error); + throw error; + } +} diff --git a/integration_test/src/run.ts b/integration_test/src/run.ts new file mode 100644 index 000000000..d6f2ccb4b --- /dev/null +++ b/integration_test/src/run.ts @@ -0,0 +1,6 @@ +import { runIntegrationTests } from "./index"; + +runIntegrationTests().catch((error) => { + console.error("An error occurred during integration tests", error); + process.exit(1); +}); diff --git a/integration_test/utils.ts b/integration_test/utils.ts deleted file mode 100644 index f9d7ff173..000000000 --- a/integration_test/utils.ts +++ /dev/null @@ -1,17 +0,0 @@ -import path from "path"; -import fs from "fs"; - -export function loadEnv(): void { - try { - const envPath = path.resolve(process.cwd(), ".env"); - console.log("Loading .env file from", envPath); - const envFileContent = fs.readFileSync(envPath, "utf-8"); - envFileContent.split("\n").forEach((variable) => { - const [key, value] = variable.split("="); - if (key && value) process.env[key.trim()] = value.trim(); - }); - } catch (error: any) { - console.error("Error loading .env file:", error.message); - } -} - From 025b17005e0326b4688fc29836ebf6459e9956d8 Mon Sep 17 00:00:00 2001 From: HassanBahati Date: Tue, 19 Aug 2025 00:36:53 +0300 Subject: [PATCH 18/25] feat: setup database tests --- integration_test/deployment-utils.ts | 207 +++++- integration_test/functions/src/index.ts | 4 +- .../functions/src/v1/auth-tests.ts | 2 +- .../functions/src/v2/database-tests.ts | 144 ++--- integration_test/functions/src/v2/index.ts | 20 +- integration_test/global.d.ts | 10 + integration_test/package-lock.json | 479 +------------- integration_test/package.json | 2 +- integration_test/run.ts | 68 +- integration_test/tests/firebaseSetup.ts | 3 +- integration_test/tests/v1/auth.test.ts | 538 +++++++-------- integration_test/tests/v1/database.test.ts | 610 +++++++++--------- integration_test/tests/v1/firestore.test.ts | 496 +++++++------- integration_test/tests/v1/pubsub.test.ts | 226 +++---- .../tests/v1/remoteConfig.test.ts | 122 ++-- integration_test/tests/v1/storage.test.ts | 358 +++++----- integration_test/tests/v1/tasks.test.ts | 88 +-- integration_test/tests/v1/testLab.test.ts | 102 +-- integration_test/tests/v2/database.test.ts | 195 +++--- integration_test/tests/v2/eventarc.test.ts | 114 ++-- integration_test/tests/v2/firestore.test.ts | 462 ++++++------- integration_test/tests/v2/identity.test.ts | 260 ++++---- integration_test/tests/v2/pubsub.test.ts | 116 ++-- .../tests/v2/remoteConfig.test.ts | 114 ++-- integration_test/tests/v2/scheduler.test.ts | 112 ++-- integration_test/tests/v2/storage.test.ts | 334 +++++----- integration_test/tests/v2/tasks.test.ts | 88 +-- integration_test/tests/v2/testLab.test.ts | 100 +-- 28 files changed, 2591 insertions(+), 2783 deletions(-) diff --git a/integration_test/deployment-utils.ts b/integration_test/deployment-utils.ts index be4f4b90c..86ee3251b 100644 --- a/integration_test/deployment-utils.ts +++ b/integration_test/deployment-utils.ts @@ -3,16 +3,16 @@ import pLimit from "p-limit"; interface FirebaseClient { functions: { - list: () => Promise<{ name: string }[]>; + list: (options?: any) => Promise<{ name: string }[]>; delete(names: string[], options: any): Promise; }; - deploy: (options: { only: string; force: boolean }) => Promise; + deploy: (options: any) => Promise; } // Configuration constants const BATCH_SIZE = 3; // Reduced to 3 functions at a time for better rate limiting const DELAY_BETWEEN_BATCHES = 5000; // Increased from 2 to 5 seconds between batches -const MAX_RETRIES = 3; // Retry failed deployments +const MAX_RETRIES = 1; // Retry failed deployments const CLEANUP_DELAY = 1000; // 1 second between cleanup operations // Rate limiter for deployment operations const deploymentLimiter = pLimit(1); // Only one deployment operation at a time @@ -28,10 +28,48 @@ const sleep = (ms: number): Promise => new Promise((resolve) => setTimeout */ export async function getDeployedFunctions(client: FirebaseClient): Promise { try { - const functions = await client.functions.list(); + console.log("🔍 Attempting to list functions..."); + console.log(" Project ID:", process.env.PROJECT_ID); + console.log(" Working directory:", process.cwd()); + console.log(" Config file:", "./firebase.json"); + + // Check if PROJECT_ID is set + if (!process.env.PROJECT_ID) { + console.log(" ❌ PROJECT_ID environment variable is not set"); + return []; + } + + // Try to list functions with explicit project ID + const functions = await client.functions.list({ + project: process.env.PROJECT_ID, + config: "./firebase.json", + nonInteractive: true, + cwd: process.cwd(), + }); + + console.log("✅ Successfully listed functions:", functions.length); return functions.map((fn: { name: string }) => fn.name); } catch (error) { console.log("Could not list functions, assuming none deployed:", error); + + // Provide more detailed error information + if (error && typeof error === 'object' && 'message' in error) { + const errorMessage = String(error.message); + console.log(" Error message:", errorMessage); + if ('status' in error) console.log(" Error status:", error.status); + if ('exit' in error) console.log(" Error exit code:", error.exit); + + // Check if it's an authentication error + if (errorMessage.includes("not logged in") || errorMessage.includes("authentication")) { + console.log(" 💡 This might be an authentication issue. Try running 'firebase login' first."); + } + + // Check if it's a project access error + if (errorMessage.includes("not found") || errorMessage.includes("access")) { + console.log(" 💡 This might be a project access issue. Check if the project ID is correct and you have access to it."); + } + } + return []; } } @@ -52,6 +90,7 @@ async function deleteFunctionWithRetry( config: "./firebase.json", debug: true, nonInteractive: true, + cwd: process.cwd(), }); console.log(`✅ Deleted function: ${functionName}`); } catch (error: unknown) { @@ -137,6 +176,50 @@ export async function deployFunctionsWithRetry( functionsToDeploy: string[] ): Promise { console.log(`🚀 Deploying ${functionsToDeploy.length} functions with rate limiting...`); + console.log(`📋 Functions to deploy:`, functionsToDeploy); + console.log(`🔧 Project ID: ${process.env.PROJECT_ID}`); + console.log(`🔧 Region: ${process.env.REGION || 'us-central1'}`); + console.log(`🔧 Runtime: ${process.env.TEST_RUNTIME}`); + + // Pre-deployment checks + console.log(`\n🔍 Pre-deployment checks:`); + console.log(` - Project ID set: ${!!process.env.PROJECT_ID}`); + console.log(` - Working directory: ${process.cwd()}`); + + // Import fs dynamically for ES modules + const fs = await import('fs'); + + console.log(` - Functions directory exists: ${fs.existsSync('./functions')}`); + console.log(` - Functions.yaml exists: ${fs.existsSync('./functions/functions.yaml')}`); + console.log(` - Package.json exists: ${fs.existsSync('./functions/package.json')}`); + + if (!process.env.PROJECT_ID) { + throw new Error("PROJECT_ID environment variable is not set"); + } + + if (!fs.existsSync('./functions')) { + throw new Error("Functions directory does not exist"); + } + + if (!fs.existsSync('./functions/functions.yaml')) { + throw new Error("functions.yaml file does not exist in functions directory"); + } + + // Check functions.yaml content + try { + const functionsYaml = fs.readFileSync('./functions/functions.yaml', 'utf8'); + console.log(` - Functions.yaml content preview:`); + console.log(` ${functionsYaml.substring(0, 200)}...`); + } catch (error: any) { + console.log(` - Error reading functions.yaml: ${error.message}`); + } + + // Set up Firebase project configuration + console.log(` - Setting up Firebase project configuration...`); + process.env.FIREBASE_PROJECT = process.env.PROJECT_ID; + process.env.GCLOUD_PROJECT = process.env.PROJECT_ID; + console.log(` - FIREBASE_PROJECT: ${process.env.FIREBASE_PROJECT}`); + console.log(` - GCLOUD_PROJECT: ${process.env.GCLOUD_PROJECT}`); // Deploy functions in batches const batches = []; @@ -146,25 +229,66 @@ export async function deployFunctionsWithRetry( for (let i = 0; i < batches.length; i++) { const batch = batches[i]; - console.log(`Deploying batch ${i + 1}/${batches.length} (${batch.length} functions)`); + console.log(`\n📦 Deploying batch ${i + 1}/${batches.length} (${batch.length} functions)`); + console.log(`📋 Batch functions:`, batch); try { await pRetry( async () => { await deploymentLimiter(async () => { - await client.deploy({ + console.log(`\n🔧 Starting deployment attempt...`); + console.log(`🔧 Project ID: ${process.env.PROJECT_ID}`); + console.log(`🔧 Working directory: ${process.cwd()}`); + console.log(`🔧 Functions source: ${process.cwd()}/functions`); + + const deployOptions = { only: "functions", force: true, - }); + project: process.env.PROJECT_ID, + debug: true, + nonInteractive: true, + cwd: process.cwd(), + }; + + + + console.log(`🔧 Deploy options:`, JSON.stringify(deployOptions, null, 2)); + + try { + await client.deploy(deployOptions); + console.log(`✅ Deployment command completed successfully`); + } catch (deployError: any) { + console.log(`❌ Deployment command failed with error:`); + console.log(` Error type: ${deployError.constructor.name}`); + console.log(` Error message: ${deployError.message}`); + console.log(` Error stack: ${deployError.stack}`); + + // Log all properties of the error object + console.log(` Error properties:`); + Object.keys(deployError).forEach(key => { + try { + const value = deployError[key]; + if (typeof value === 'object' && value !== null) { + console.log(` ${key}: ${JSON.stringify(value, null, 4)}`); + } else { + console.log(` ${key}: ${value}`); + } + } catch (e) { + console.log(` ${key}: [Error serializing property]`); + } + }); + + throw deployError; + } }); }, { retries: MAX_RETRIES, onFailedAttempt: (error: any) => { - console.log( - `❌ Deployment failed (attempt ${error.attemptNumber}/${MAX_RETRIES + 1}):`, - error.message - ); + console.log(`\n❌ Deployment failed (attempt ${error.attemptNumber}/${MAX_RETRIES + 1}):`); + console.log(` Error message: ${error.message}`); + console.log(` Error type: ${error.constructor.name}`); + // Log detailed error information during retries if (error.children && error.children.length > 0) { console.log("📋 Detailed deployment errors:"); @@ -181,13 +305,24 @@ export async function deployFunctionsWithRetry( } }); } + // Log the full error structure for debugging - console.log("🔍 Error details:"); + console.log("🔍 Full error details:"); console.log(` - Message: ${error.message}`); console.log(` - Status: ${error.status}`); console.log(` - Exit code: ${error.exit}`); console.log(` - Attempt: ${error.attemptNumber}`); console.log(` - Retries left: ${error.retriesLeft}`); + + // Log error context if available + if (error.context) { + console.log(` - Context: ${JSON.stringify(error.context, null, 2)}`); + } + + // Log error body if available + if (error.body) { + console.log(` - Body: ${JSON.stringify(error.body, null, 2)}`); + } }, } ); @@ -200,7 +335,11 @@ export async function deployFunctionsWithRetry( await sleep(DELAY_BETWEEN_BATCHES); } } catch (error: any) { - console.error(`❌ Failed to deploy batch ${i + 1}:`, error); + console.error(`\n❌ FINAL FAILURE: Failed to deploy batch ${i + 1} after all retries`); + console.error(` Error type: ${error.constructor.name}`); + console.error(` Error message: ${error.message}`); + console.error(` Error stack: ${error.stack}`); + // Log detailed error information if (error.children && error.children.length > 0) { console.log("📋 Detailed deployment errors:"); @@ -213,13 +352,40 @@ export async function deployFunctionsWithRetry( } }); } + // Log the full error structure for debugging - console.log("🔍 Error details:"); + console.log("🔍 Final error details:"); console.log(` - Message: ${error.message}`); console.log(` - Status: ${error.status}`); console.log(` - Exit code: ${error.exit}`); console.log(` - Attempt: ${error.attemptNumber}`); console.log(` - Retries left: ${error.retriesLeft}`); + + // Log error context if available + if (error.context) { + console.log(` - Context: ${JSON.stringify(error.context, null, 2)}`); + } + + // Log error body if available + if (error.body) { + console.log(` - Body: ${JSON.stringify(error.body, null, 2)}`); + } + + // Log all error properties + console.log(` - All error properties:`); + Object.keys(error).forEach(key => { + try { + const value = error[key]; + if (typeof value === 'object' && value !== null) { + console.log(` ${key}: ${JSON.stringify(value, null, 4)}`); + } else { + console.log(` ${key}: ${value}`); + } + } catch (e) { + console.log(` ${key}: [Error serializing property]`); + } + }); + throw error; } } @@ -235,6 +401,8 @@ export async function postCleanup(client: any, testRunId: string): Promise try { const deployedFunctions = await getDeployedFunctions(client); + // print the deployed functions + console.log("🔍 Deployed functions:", deployedFunctions); const testFunctions = deployedFunctions.filter((name) => name && name.includes(testRunId)); if (testFunctions.length === 0) { @@ -242,7 +410,10 @@ export async function postCleanup(client: any, testRunId: string): Promise return; } - console.log(`Found ${testFunctions.length} test functions to clean up`); + console.log(`Found ${testFunctions.length} test functions to clean up:`); + testFunctions.forEach((funcName, index) => { + console.log(` ${index + 1}. ${funcName}`); + }); // Delete test functions in batches with rate limiting const batches = []; @@ -256,7 +427,11 @@ export async function postCleanup(client: any, testRunId: string): Promise // Delete functions in parallel within the batch const deletePromises = batch.map((functionName) => - cleanupLimiter(() => deleteFunctionWithRetry(client, functionName)) + cleanupLimiter(async () => { + console.log(`🗑️ Deleting function: ${functionName}`); + await deleteFunctionWithRetry(client, functionName); + console.log(`✅ Successfully deleted: ${functionName}`); + }) ); await Promise.all(deletePromises); diff --git a/integration_test/functions/src/index.ts b/integration_test/functions/src/index.ts index 80abc60ee..d523b2ed3 100644 --- a/integration_test/functions/src/index.ts +++ b/integration_test/functions/src/index.ts @@ -1,7 +1,7 @@ import * as admin from "firebase-admin"; -import * as v1 from "./v1"; +// import * as v1 from "./v1"; import * as v2 from "./v2"; -export { v1, v2 }; +export { v2 }; admin.initializeApp(); diff --git a/integration_test/functions/src/v1/auth-tests.ts b/integration_test/functions/src/v1/auth-tests.ts index b0adcdab7..a51b6b535 100644 --- a/integration_test/functions/src/v1/auth-tests.ts +++ b/integration_test/functions/src/v1/auth-tests.ts @@ -1,5 +1,5 @@ import * as admin from "firebase-admin"; -import * as functions from "firebase-functions"; +import * as functions from "firebase-functions/v1"; import { REGION } from "../region"; import { sanitizeData } from "../utils"; diff --git a/integration_test/functions/src/v2/database-tests.ts b/integration_test/functions/src/v2/database-tests.ts index 96c214f34..357359e63 100644 --- a/integration_test/functions/src/v2/database-tests.ts +++ b/integration_test/functions/src/v2/database-tests.ts @@ -32,77 +32,77 @@ export const databaseCreatedTests = onValueCreated( } ); -export const databaseDeletedTests = onValueDeleted( - { - ref: "databaseDeletedTests/{testId}/start", - region: REGION, - }, - async (event) => { - const testId = event.params.testId; - await admin - .firestore() - .collection("databaseDeletedTests") - .doc(testId) - .set( - sanitizeData({ - testId, - type: event.type, - id: event.id, - time: event.time, - url: event.ref.toString(), - }) - ); - } -); +// export const databaseDeletedTests = onValueDeleted( +// { +// ref: "databaseDeletedTests/{testId}/start", +// region: REGION, +// }, +// async (event) => { +// const testId = event.params.testId; +// await admin +// .firestore() +// .collection("databaseDeletedTests") +// .doc(testId) +// .set( +// sanitizeData({ +// testId, +// type: event.type, +// id: event.id, +// time: event.time, +// url: event.ref.toString(), +// }) +// ); +// } +// ); -export const databaseUpdatedTests = onValueUpdated( - { - ref: "databaseUpdatedTests/{testId}/start", - region: REGION, - }, - async (event) => { - const testId = event.params.testId; - const data = event.data.after.val(); - await admin - .firestore() - .collection("databaseUpdatedTests") - .doc(testId) - .set( - sanitizeData({ - testId, - url: event.ref.toString(), - type: event.type, - id: event.id, - time: event.time, - data: JSON.stringify(data ?? {}), - }) - ); - } -); +// export const databaseUpdatedTests = onValueUpdated( +// { +// ref: "databaseUpdatedTests/{testId}/start", +// region: REGION, +// }, +// async (event) => { +// const testId = event.params.testId; +// const data = event.data.after.val(); +// await admin +// .firestore() +// .collection("databaseUpdatedTests") +// .doc(testId) +// .set( +// sanitizeData({ +// testId, +// url: event.ref.toString(), +// type: event.type, +// id: event.id, +// time: event.time, +// data: JSON.stringify(data ?? {}), +// }) +// ); +// } +// ); -export const databaseWrittenTests = onValueWritten( - { - ref: "databaseWrittenTests/{testId}/start", - region: REGION, - }, - async (event) => { - const testId = event.params.testId; - if (!event.data.after.exists()) { - functions.logger.info(`Event for ${testId} is null; presuming data cleanup, so skipping.`); - return; - } - await admin - .firestore() - .collection("databaseWrittenTests") - .doc(testId) - .set( - sanitizeData({ - testId, - type: event.type, - id: event.id, - time: event.time, - url: event.ref.toString(), - }) - ); - } -); +// export const databaseWrittenTests = onValueWritten( +// { +// ref: "databaseWrittenTests/{testId}/start", +// region: REGION, +// }, +// async (event) => { +// const testId = event.params.testId; +// if (!event.data.after.exists()) { +// functions.logger.info(`Event for ${testId} is null; presuming data cleanup, so skipping.`); +// return; +// } +// await admin +// .firestore() +// .collection("databaseWrittenTests") +// .doc(testId) +// .set( +// sanitizeData({ +// testId, +// type: event.type, +// id: event.id, +// time: event.time, +// url: event.ref.toString(), +// }) +// ); +// } +// ); diff --git a/integration_test/functions/src/v2/index.ts b/integration_test/functions/src/v2/index.ts index 561505427..ae089d815 100644 --- a/integration_test/functions/src/v2/index.ts +++ b/integration_test/functions/src/v2/index.ts @@ -2,19 +2,19 @@ import { setGlobalOptions } from "firebase-functions/v2"; import { REGION } from "../region"; setGlobalOptions({ region: REGION }); -export * from "./alerts-tests"; +// export * from "./alerts-tests"; export * from "./database-tests"; -export * from "./eventarc-tests"; -export * from "./firestore-tests"; +// export * from "./eventarc-tests"; +// export * from "./firestore-tests"; // Temporarily disable http test - will not work unless running on projects // w/ permission to create public functions. // export * from "./https-tests"; // TODO: cannot deploy multiple auth blocking funcs at once. Only have one of // v2 identity or v1 auth exported at once. -export * from "./identity-tests"; -export * from "./pubsub-tests"; -export * from "./scheduler-tests"; -export * from "./storage-tests"; -export * from "./tasks-tests"; -export * from "./testLab-tests"; -export * from "./remoteConfig-tests"; +// export * from "./identity-tests"; +// export * from "./pubsub-tests"; +// export * from "./scheduler-tests"; +// export * from "./storage-tests"; +// export * from "./tasks-tests"; +// export * from "./testLab-tests"; +// export * from "./remoteConfig-tests"; diff --git a/integration_test/global.d.ts b/integration_test/global.d.ts index 68ce9f603..2fb5e98fb 100644 --- a/integration_test/global.d.ts +++ b/integration_test/global.d.ts @@ -1,3 +1,13 @@ declare module "firebase-tools"; declare module "firebase-tools/lib/deploy/functions/runtimes/index.js"; declare module "firebase-tools/lib/deploy/functions/runtimes/discovery/index.js"; + +// Jest globals +declare const describe: jest.Describe; +declare const it: jest.It; +declare const test: jest.It; +declare const expect: jest.Expect; +declare const beforeAll: jest.Lifecycle; +declare const afterAll: jest.Lifecycle; +declare const beforeEach: jest.Lifecycle; +declare const afterEach: jest.Lifecycle; diff --git a/integration_test/package-lock.json b/integration_test/package-lock.json index 6ce6319d6..9643c64d3 100644 --- a/integration_test/package-lock.json +++ b/integration_test/package-lock.json @@ -18,7 +18,7 @@ "@types/jest": "^29.5.11", "@types/js-yaml": "^4.0.9", "@types/node-fetch": "^2.6.11", - "chalk": "^5.5.0", + "chalk": "^4.1.2", "dotenv": "^17.2.1", "jest": "^29.7.0", "p-limit": "^6.2.0", @@ -2410,23 +2410,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/console/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/@jest/core": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", @@ -2475,23 +2458,6 @@ } } }, - "node_modules/@jest/core/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/@jest/environment": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", @@ -2613,23 +2579,6 @@ } } }, - "node_modules/@jest/reporters/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", @@ -2748,23 +2697,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/transform/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/@jest/transform/node_modules/write-file-atomic": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", @@ -2797,23 +2729,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -3814,23 +3729,6 @@ "@babel/core": "^7.8.0" } }, - "node_modules/babel-jest/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/babel-plugin-istanbul": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", @@ -4062,22 +3960,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/boxen/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/boxen/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -4362,12 +4244,16 @@ "license": "CC-BY-4.0" }, "node_modules/chalk": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz", - "integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" @@ -4509,22 +4395,6 @@ "npm": ">=5.0.0" } }, - "node_modules/cli-highlight/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/cli-highlight/node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -5107,23 +4977,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/create-jest/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/cross-env": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.1.tgz", @@ -7407,22 +7260,6 @@ "inquirer": "^8.0.0" } }, - "node_modules/inquirer/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/inquirer/node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -7976,23 +7813,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-circus/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/jest-circus/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -8056,23 +7876,6 @@ } } }, - "node_modules/jest-cli/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/jest-config": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", @@ -8119,23 +7922,6 @@ } } }, - "node_modules/jest-config/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -8152,23 +7938,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-diff/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/jest-docblock": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", @@ -8199,23 +7968,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-each/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/jest-environment-node": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", @@ -8300,23 +8052,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-matcher-utils/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/jest-message-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", @@ -8338,23 +8073,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-message-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/jest-mock": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", @@ -8433,23 +8151,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-resolve/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/jest-runner": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", @@ -8483,23 +8184,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runner/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/jest-runner/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -8563,23 +8247,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/jest-snapshot": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", @@ -8612,23 +8279,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/jest-snapshot/node_modules/semver": { "version": "7.5.4", "dev": true, @@ -8661,23 +8311,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/jest-validate": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", @@ -8696,23 +8329,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-validate/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/jest-watcher": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", @@ -8733,23 +8349,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-watcher/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/jest-worker": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", @@ -9226,22 +8825,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/logform": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", @@ -9458,6 +9041,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/marked-terminal/node_modules/chalk": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz", + "integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -10095,22 +9690,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/p-defer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-3.0.0.tgz", @@ -12413,22 +11992,6 @@ "node": ">=14" } }, - "node_modules/update-notifier-cjs/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/update-notifier-cjs/node_modules/semver": { "version": "7.5.4", "license": "ISC", diff --git a/integration_test/package.json b/integration_test/package.json index c439fa323..3dd6987de 100644 --- a/integration_test/package.json +++ b/integration_test/package.json @@ -20,7 +20,7 @@ "@types/jest": "^29.5.11", "@types/js-yaml": "^4.0.9", "@types/node-fetch": "^2.6.11", - "chalk": "^5.5.0", + "chalk": "^4.1.2", "dotenv": "^17.2.1", "jest": "^29.7.0", "p-limit": "^6.2.0", diff --git a/integration_test/run.ts b/integration_test/run.ts index 3822f74c1..fffedb0b8 100644 --- a/integration_test/run.ts +++ b/integration_test/run.ts @@ -37,7 +37,7 @@ if ( !FIREBASE_MEASUREMENT_ID || !FIREBASE_AUTH_DOMAIN || !FIREBASE_API_KEY || - !GOOGLE_ANALYTICS_API_SECRET || + // !GOOGLE_ANALYTICS_API_SECRET || !TEST_RUNTIME ) { console.error("Required environment variables are not set. Exiting..."); @@ -64,6 +64,10 @@ if (!FIREBASE_ADMIN && runtime === "node") { setup(runtime, TEST_RUN_ID, NODE_VERSION, FIREBASE_ADMIN); +// Configure Firebase client with project ID +console.log("Configuring Firebase client with project ID:", PROJECT_ID); +const firebaseClient = client; + const config = { projectId: PROJECT_ID, projectDir: process.cwd(), @@ -165,52 +169,81 @@ function writeFunctionsYaml(filePath: string, data: any): void { } async function deployModifiedFunctions(): Promise { - console.log("Deploying functions with id:", TEST_RUN_ID); + console.log("🚀 Deploying functions with id:", TEST_RUN_ID); try { // Get the function names that will be deployed const functionNames = modifiedYaml ? Object.keys(modifiedYaml.endpoints) : []; + + console.log("📋 Functions to deploy:", functionNames); + console.log("📊 Total functions to deploy:", functionNames.length); // Deploy with rate limiting and retry logic - await deployFunctionsWithRetry(client, functionNames); + await deployFunctionsWithRetry(firebaseClient, functionNames); - console.log("Functions have been deployed successfully."); + console.log("✅ Functions have been deployed successfully."); + console.log("🔗 You can view your deployed functions in the Firebase Console:"); + console.log(` https://console.firebase.google.com/project/${PROJECT_ID}/functions`); } catch (err) { - console.error("Error deploying functions. Exiting.", err); + console.error("❌ Error deploying functions. Exiting.", err); throw err; } } function cleanFiles(): void { - console.log("Cleaning files..."); + console.log("🧹 Cleaning files..."); const functionsDir = "functions"; process.chdir(functionsDir); // go to functions try { const files = fs.readdirSync("."); + const deletedFiles: string[] = []; + files.forEach((file) => { // For Node if (file.match(`firebase-functions-${TEST_RUN_ID}.tgz`)) { fs.rmSync(file); + deletedFiles.push(file); } // For Python if (file.match(`firebase_functions.tar.gz`)) { fs.rmSync(file); + deletedFiles.push(file); } if (file.match("package.json")) { fs.rmSync(file); + deletedFiles.push(file); } if (file.match("requirements.txt")) { fs.rmSync(file); + deletedFiles.push(file); } if (file.match("firebase-debug.log")) { fs.rmSync(file); + deletedFiles.push(file); } if (file.match("functions.yaml")) { fs.rmSync(file); + deletedFiles.push(file); } }); - fs.rmSync("lib", { recursive: true, force: true }); - fs.rmSync("venv", { recursive: true, force: true }); + // Check and delete directories + if (fs.existsSync("lib")) { + fs.rmSync("lib", { recursive: true, force: true }); + deletedFiles.push("lib/ (directory)"); + } + if (fs.existsSync("venv")) { + fs.rmSync("venv", { recursive: true, force: true }); + deletedFiles.push("venv/ (directory)"); + } + + if (deletedFiles.length > 0) { + console.log(`🗑️ Deleted ${deletedFiles.length} files/directories:`); + deletedFiles.forEach((file, index) => { + console.log(` ${index + 1}. ${file}`); + }); + } else { + console.log("ℹ️ No files to clean up"); + } } catch (error) { console.error("Error occurred while cleaning files:", error); } @@ -264,10 +297,12 @@ const spawnAsync = (command: string, args: string[], options: any): Promise { const humanReadableRuntime = TEST_RUNTIME === "node" ? "Node.js" : "Python"; try { - console.log(`Starting ${humanReadableRuntime} Tests...`); - console.log("🔍 About to run: npm test"); + console.log(`🧪 Starting ${humanReadableRuntime} Tests...`); + console.log("🔍 Running: database test only"); + console.log("📁 Test file: integration_test/tests/v2/database.test.ts"); - const output = await spawnAsync("npm", ["test"], { + // Run only the database test + const output = await spawnAsync("npx", ["jest", "--testPathPattern=database.test.ts", "--verbose"], { env: { ...process.env, TEST_RUN_ID, @@ -276,6 +311,15 @@ async function runTests(): Promise { console.log("📋 Test output received:"); console.log(output); + + // Check if tests passed + if (output.includes("PASS") && !output.includes("FAIL")) { + console.log("✅ Database tests completed successfully!"); + console.log("🎯 All database function triggers are working correctly."); + } else { + console.log("⚠️ Some tests may have failed. Check the output above."); + } + console.log(`${humanReadableRuntime} Tests Completed.`); } catch (error) { console.error("❌ Error during testing:", error); @@ -287,7 +331,7 @@ async function handleCleanUp(): Promise { console.log("Cleaning up..."); try { // Use our new post-cleanup utility with rate limiting - await postCleanup(client, TEST_RUN_ID); + await postCleanup(firebaseClient, TEST_RUN_ID); } catch (err) { console.error("Error during post-cleanup:", err); // Don't throw here to ensure files are still cleaned diff --git a/integration_test/tests/firebaseSetup.ts b/integration_test/tests/firebaseSetup.ts index 89d43d339..85fc3f4f4 100644 --- a/integration_test/tests/firebaseSetup.ts +++ b/integration_test/tests/firebaseSetup.ts @@ -1,4 +1,5 @@ import * as admin from "firebase-admin"; +import { logger } from "../src/logger"; /** * Initializes Firebase Admin SDK. @@ -18,7 +19,7 @@ export async function initializeFirebase(): Promise { projectId: process.env.PROJECT_ID, }); } catch (error) { - console.error("Error initializing Firebase:", error); + logger.error("Error initializing Firebase:", error); } } return admin.app(); diff --git a/integration_test/tests/v1/auth.test.ts b/integration_test/tests/v1/auth.test.ts index 3312198b6..0e91dc856 100644 --- a/integration_test/tests/v1/auth.test.ts +++ b/integration_test/tests/v1/auth.test.ts @@ -1,269 +1,269 @@ -import * as admin from "firebase-admin"; -import { initializeApp } from "firebase/app"; -import { createUserWithEmailAndPassword, getAuth, UserCredential } from "firebase/auth"; -import { initializeFirebase } from "../firebaseSetup"; -import { retry } from "../utils"; - -describe("Firebase Auth (v1)", () => { - let userIds: string[] = []; - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; - const config = { - apiKey: process.env.FIREBASE_API_KEY, - authDomain: process.env.FIREBASE_AUTH_DOMAIN, - databaseURL: process.env.DATABASE_URL, - projectId, - storageBucket: process.env.STORAGE_BUCKET, - appId: process.env.FIREBASE_APP_ID, - measurementId: process.env.FIREBASE_MEASUREMENT_ID, - }; - const app = initializeApp(config); - - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } - - beforeAll(async () => { - await initializeFirebase(); - }); - - afterAll(async () => { - for (const userId in userIds) { - await admin.firestore().collection("userProfiles").doc(userId).delete(); - await admin.firestore().collection("authUserOnCreateTests").doc(userId).delete(); - await admin.firestore().collection("authUserOnDeleteTests").doc(userId).delete(); - await admin.firestore().collection("authBeforeCreateTests").doc(userId).delete(); - await admin.firestore().collection("authBeforeSignInTests").doc(userId).delete(); - } - }); - - describe("user onCreate trigger", () => { - let userRecord: admin.auth.UserRecord; - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - userRecord = await admin.auth().createUser({ - email: `${testId}@fake-create.com`, - password: "secret", - displayName: `${testId}`, - }); - - loggedContext = await retry(() => - admin - .firestore() - .collection("authUserOnCreateTests") - .doc(userRecord.uid) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - - userIds.push(userRecord.uid); - }); - - afterAll(async () => { - await admin.auth().deleteUser(userRecord.uid); - }); - - it("should perform expected actions", async () => { - const userProfile = await admin - .firestore() - .collection("userProfiles") - .doc(userRecord.uid) - .get(); - expect(userProfile.exists).toBeTruthy(); - }); - - it("should have a project as resource", () => { - expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); - }); - - it("should not have a path", () => { - expect(loggedContext?.path).toBeUndefined(); - }); - - it("should have the correct eventType", () => { - expect(loggedContext?.eventType).toEqual("google.firebase.auth.user.create"); - }); - - it("should have an eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have a timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - - it("should not have auth", () => { - expect(loggedContext?.auth).toBeUndefined(); - }); - - it("should not have an action", () => { - expect(loggedContext?.action).toBeUndefined(); - }); - - it("should have properly defined metadata", () => { - const parsedMetadata = JSON.parse(loggedContext?.metadata); - // TODO: better handle date format mismatch and precision - const expectedCreationTime = new Date(userRecord.metadata.creationTime) - .toISOString() - .replace(/\.\d{3}/, ""); - const expectedMetadata = { - ...userRecord.metadata, - creationTime: expectedCreationTime, - }; - - expect(expectedMetadata).toEqual(expect.objectContaining(parsedMetadata)); - }); - }); - - describe("user onDelete trigger", () => { - let userRecord: admin.auth.UserRecord; - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - userRecord = await admin.auth().createUser({ - email: `${testId}@fake-delete.com`, - password: "secret", - displayName: `${testId}`, - }); - - await admin.auth().deleteUser(userRecord.uid); - - loggedContext = await retry( - () => - admin - .firestore() - .collection("authUserOnDeleteTests") - .doc(userRecord.uid) - .get() - .then((logSnapshot) => logSnapshot.data()), - ); - - userIds.push(userRecord.uid); - }); - - it("should have a project as resource", () => { - expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); - }); - - it("should not have a path", () => { - expect(loggedContext?.path).toBeUndefined(); - }); - - it("should have the correct eventType", async () => { - expect(loggedContext?.eventType).toEqual("google.firebase.auth.user.delete"); - }); - - it("should have an eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have a timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - - it("should not have auth", () => { - expect(loggedContext?.auth).toBeUndefined(); - }); - - it("should not have an action", () => { - expect(loggedContext?.action).toBeUndefined(); - }); - }); - - describe("user beforeCreate trigger", () => { - let userRecord: UserCredential; - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - userRecord = await createUserWithEmailAndPassword( - getAuth(app), - `${testId}@fake-before-create.com`, - "secret" - ); - - loggedContext = await retry(() => - admin - .firestore() - .collection("authBeforeCreateTests") - .doc(userRecord.user.uid) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - - userIds.push(userRecord.user.uid); - }); - - afterAll(async () => { - await admin.auth().deleteUser(userRecord.user.uid); - }); - - it("should have a project as resource", () => { - expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); - }); - - it("should have the correct eventType", () => { - expect(loggedContext?.eventType).toEqual( - "providers/cloud.auth/eventTypes/user.beforeCreate:password" - ); - }); - - it("should have an eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have a timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - }); - - describe("user beforeSignIn trigger", () => { - let userRecord: UserCredential; - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - userRecord = await createUserWithEmailAndPassword( - getAuth(app), - `${testId}@fake-before-signin.com`, - "secret" - ); - - loggedContext = await retry(() => - admin - .firestore() - .collection("authBeforeSignInTests") - .doc(userRecord.user.uid) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - - userIds.push(userRecord.user.uid); - - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } - }); - - afterAll(async () => { - await admin.auth().deleteUser(userRecord.user.uid); - }); - - it("should have a project as resource", () => { - expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); - }); - - it("should have the correct eventType", () => { - expect(loggedContext?.eventType).toEqual( - "providers/cloud.auth/eventTypes/user.beforeSignIn:password" - ); - }); - - it("should have an eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have a timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - }); -}); +// import * as admin from "firebase-admin"; +// import { initializeApp } from "firebase/app"; +// import { createUserWithEmailAndPassword, getAuth, UserCredential } from "firebase/auth"; +// import { initializeFirebase } from "../firebaseSetup"; +// import { retry } from "../utils"; + +// describe("Firebase Auth (v1)", () => { +// let userIds: string[] = []; +// const projectId = process.env.PROJECT_ID; +// const testId = process.env.TEST_RUN_ID; +// const config = { +// apiKey: process.env.FIREBASE_API_KEY, +// authDomain: process.env.FIREBASE_AUTH_DOMAIN, +// databaseURL: process.env.DATABASE_URL, +// projectId, +// storageBucket: process.env.STORAGE_BUCKET, +// appId: process.env.FIREBASE_APP_ID, +// measurementId: process.env.FIREBASE_MEASUREMENT_ID, +// }; +// const app = initializeApp(config); + +// if (!testId || !projectId) { +// throw new Error("Environment configured incorrectly."); +// } + +// beforeAll(async () => { +// await initializeFirebase(); +// }); + +// afterAll(async () => { +// for (const userId in userIds) { +// await admin.firestore().collection("userProfiles").doc(userId).delete(); +// await admin.firestore().collection("authUserOnCreateTests").doc(userId).delete(); +// await admin.firestore().collection("authUserOnDeleteTests").doc(userId).delete(); +// await admin.firestore().collection("authBeforeCreateTests").doc(userId).delete(); +// await admin.firestore().collection("authBeforeSignInTests").doc(userId).delete(); +// } +// }); + +// describe("user onCreate trigger", () => { +// let userRecord: admin.auth.UserRecord; +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// userRecord = await admin.auth().createUser({ +// email: `${testId}@fake-create.com`, +// password: "secret", +// displayName: `${testId}`, +// }); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("authUserOnCreateTests") +// .doc(userRecord.uid) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); + +// userIds.push(userRecord.uid); +// }); + +// afterAll(async () => { +// await admin.auth().deleteUser(userRecord.uid); +// }); + +// it("should perform expected actions", async () => { +// const userProfile = await admin +// .firestore() +// .collection("userProfiles") +// .doc(userRecord.uid) +// .get(); +// expect(userProfile.exists).toBeTruthy(); +// }); + +// it("should have a project as resource", () => { +// expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); +// }); + +// it("should not have a path", () => { +// expect(loggedContext?.path).toBeUndefined(); +// }); + +// it("should have the correct eventType", () => { +// expect(loggedContext?.eventType).toEqual("google.firebase.auth.user.create"); +// }); + +// it("should have an eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have a timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); + +// it("should not have auth", () => { +// expect(loggedContext?.auth).toBeUndefined(); +// }); + +// it("should not have an action", () => { +// expect(loggedContext?.action).toBeUndefined(); +// }); + +// it("should have properly defined metadata", () => { +// const parsedMetadata = JSON.parse(loggedContext?.metadata); +// // TODO: better handle date format mismatch and precision +// const expectedCreationTime = new Date(userRecord.metadata.creationTime) +// .toISOString() +// .replace(/\.\d{3}/, ""); +// const expectedMetadata = { +// ...userRecord.metadata, +// creationTime: expectedCreationTime, +// }; + +// expect(expectedMetadata).toEqual(expect.objectContaining(parsedMetadata)); +// }); +// }); + +// describe("user onDelete trigger", () => { +// let userRecord: admin.auth.UserRecord; +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// userRecord = await admin.auth().createUser({ +// email: `${testId}@fake-delete.com`, +// password: "secret", +// displayName: `${testId}`, +// }); + +// await admin.auth().deleteUser(userRecord.uid); + +// loggedContext = await retry( +// () => +// admin +// .firestore() +// .collection("authUserOnDeleteTests") +// .doc(userRecord.uid) +// .get() +// .then((logSnapshot) => logSnapshot.data()), +// ); + +// userIds.push(userRecord.uid); +// }); + +// it("should have a project as resource", () => { +// expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); +// }); + +// it("should not have a path", () => { +// expect(loggedContext?.path).toBeUndefined(); +// }); + +// it("should have the correct eventType", async () => { +// expect(loggedContext?.eventType).toEqual("google.firebase.auth.user.delete"); +// }); + +// it("should have an eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have a timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); + +// it("should not have auth", () => { +// expect(loggedContext?.auth).toBeUndefined(); +// }); + +// it("should not have an action", () => { +// expect(loggedContext?.action).toBeUndefined(); +// }); +// }); + +// describe("user beforeCreate trigger", () => { +// let userRecord: UserCredential; +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// userRecord = await createUserWithEmailAndPassword( +// getAuth(app), +// `${testId}@fake-before-create.com`, +// "secret" +// ); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("authBeforeCreateTests") +// .doc(userRecord.user.uid) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); + +// userIds.push(userRecord.user.uid); +// }); + +// afterAll(async () => { +// await admin.auth().deleteUser(userRecord.user.uid); +// }); + +// it("should have a project as resource", () => { +// expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); +// }); + +// it("should have the correct eventType", () => { +// expect(loggedContext?.eventType).toEqual( +// "providers/cloud.auth/eventTypes/user.beforeCreate:password" +// ); +// }); + +// it("should have an eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have a timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); +// }); + +// describe("user beforeSignIn trigger", () => { +// let userRecord: UserCredential; +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// userRecord = await createUserWithEmailAndPassword( +// getAuth(app), +// `${testId}@fake-before-signin.com`, +// "secret" +// ); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("authBeforeSignInTests") +// .doc(userRecord.user.uid) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); + +// userIds.push(userRecord.user.uid); + +// if (!loggedContext) { +// throw new Error("loggedContext is undefined"); +// } +// }); + +// afterAll(async () => { +// await admin.auth().deleteUser(userRecord.user.uid); +// }); + +// it("should have a project as resource", () => { +// expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); +// }); + +// it("should have the correct eventType", () => { +// expect(loggedContext?.eventType).toEqual( +// "providers/cloud.auth/eventTypes/user.beforeSignIn:password" +// ); +// }); + +// it("should have an eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have a timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); +// }); +// }); diff --git a/integration_test/tests/v1/database.test.ts b/integration_test/tests/v1/database.test.ts index 35f05d948..a180cb237 100644 --- a/integration_test/tests/v1/database.test.ts +++ b/integration_test/tests/v1/database.test.ts @@ -1,304 +1,306 @@ -import * as admin from "firebase-admin"; -import { retry } from "../utils"; -import { initializeFirebase } from "../firebaseSetup"; -import { Reference } from "@firebase/database-types"; - -describe("Firebase Database (v1)", () => { - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; - - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } - - beforeAll(async () => { - await initializeFirebase(); - }); - - afterAll(async () => { - await admin.firestore().collection("databaseRefOnCreateTests").doc(testId).delete(); - await admin.firestore().collection("databaseRefOnDeleteTests").doc(testId).delete(); - await admin.firestore().collection("databaseRefOnUpdateTests").doc(testId).delete(); - await admin.firestore().collection("databaseRefOnWriteTests").doc(testId).delete(); - }); - - async function setupRef(refPath: string) { - const ref = admin.database().ref(refPath); - await ref.set({ ".sv": "timestamp" }); - return ref; - } - - async function teardownRef(ref: Reference) { - if (ref) { - try { - await ref.remove(); - } catch (err) { - console.log("Teardown error", err); - } - } - } - - function getLoggedContext(collectionName: string, testId: string) { - return admin - .firestore() - .collection(collectionName) - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()); - } - - describe("ref onCreate trigger", () => { - let ref: Reference; - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - ref = await setupRef(`dbTests/${testId}/start`); - loggedContext = await retry(() => getLoggedContext("databaseRefOnCreateTests", testId)); - }); - - afterAll(async () => { - await teardownRef(ref); - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should give refs access to admin data", async () => { - await ref.parent?.child("adminOnly").update({ allowed: 1 }); - - const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); - const adminData = adminDataSnapshot?.val(); - - expect(adminData).toEqual({ allowed: 1 }); - }); - - it("should have a correct ref url", () => { - expect(loggedContext?.url).toMatch( - new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) - ); - }); - - it("should have refs resources", () => { - expect(loggedContext?.resource.name).toMatch( - new RegExp( - `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start` - ) - ); - }); - - it("should not include path", () => { - expect(loggedContext?.path).toBeUndefined(); - }); - - it("should have the right eventType", () => { - expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.create"); - }); - - it("should have eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - - it("should not have action", () => { - expect(loggedContext?.action).toBeUndefined(); - }); - - it("should have admin authType", () => { - expect(loggedContext?.authType).toEqual("ADMIN"); - }); - }); - - describe("ref onDelete trigger", () => { - let ref: Reference; - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - ref = await setupRef(`dbTests/${testId}/start`); - await ref.remove(); - loggedContext = await retry(() => getLoggedContext("databaseRefOnDeleteTests", testId)); - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should have a correct ref url", () => { - expect(loggedContext?.url).toMatch( - new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) - ); - }); - - it("should have refs resources", () => { - expect(loggedContext?.resource.name).toMatch( - new RegExp( - `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` - ) - ); - }); - - it("should not include path", () => { - expect(loggedContext?.path).toBeUndefined(); - }); - - it("should have the right eventType", () => { - expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.delete"); - }); - - it("should have eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - - it("should not have action", () => { - expect(loggedContext?.action).toBeUndefined(); - }); - - it("should have admin authType", () => { - expect(loggedContext?.authType).toEqual("ADMIN"); - }); - }); - - describe("ref onUpdate trigger", () => { - let ref: Reference; - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - ref = await setupRef(`dbTests/${testId}/start`); - await ref.update({ updated: true }); - loggedContext = await retry(() => getLoggedContext("databaseRefOnUpdateTests", testId)); - }); - - afterAll(async () => { - await teardownRef(ref); - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should give refs access to admin data", async () => { - await ref.parent?.child("adminOnly").update({ allowed: 1 }); - - const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); - const adminData = adminDataSnapshot?.val(); - - expect(adminData).toEqual({ allowed: 1 }); - }); - - it("should have a correct ref url", () => { - expect(loggedContext?.url).toMatch( - new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) - ); - }); - - it("should have refs resources", () => { - expect(loggedContext?.resource.name).toMatch( - new RegExp( - `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` - ) - ); - }); - - it("should not include path", () => { - expect(loggedContext?.path).toBeUndefined(); - }); - - it("should have the right eventType", () => { - expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.update"); - }); - - it("should have eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - - it("should not have action", () => { - expect(loggedContext?.action).toBeUndefined(); - }); - - it("should have admin authType", () => { - expect(loggedContext?.authType).toEqual("ADMIN"); - }); - - it("should log onUpdate event with updated data", async () => { - const parsedData = JSON.parse(loggedContext?.data ?? {}); - expect(parsedData).toEqual({ updated: true }); - }); - }); - - describe("ref onWrite trigger", () => { - let ref: Reference; - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - ref = await setupRef(`dbTests/${testId}/start`); - - loggedContext = await retry(() => getLoggedContext("databaseRefOnWriteTests", testId)); - }); - - afterAll(async () => { - await teardownRef(ref); - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should give refs access to admin data", async () => { - await ref.parent?.child("adminOnly").update({ allowed: 1 }); - - const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); - const adminData = adminDataSnapshot?.val(); - - expect(adminData).toEqual({ allowed: 1 }); - }); - - it("should have a correct ref url", () => { - expect(loggedContext?.url).toMatch( - new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) - ); - }); - - it("should have refs resources", () => { - expect(loggedContext?.resource.name).toMatch( - new RegExp( - `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` - ) - ); - }); - - it("should not include path", () => { - expect(loggedContext?.path).toBeUndefined(); - }); - - it("should have the right eventType", () => { - expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.write"); - }); - - it("should have eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - - it("should not have action", () => { - expect(loggedContext?.action).toBeUndefined(); - }); - - it("should have admin authType", () => { - expect(loggedContext?.authType).toEqual("ADMIN"); - }); - }); -}); +// import * as admin from "firebase-admin"; +// import { retry } from "../utils"; +// import { initializeFirebase } from "../firebaseSetup"; +// import { Reference } from "@firebase/database-types"; +// import { logger } from "../../src/logger"; + +// describe("Firebase Database (v1)", () => { +// // const projectId = process.env.PROJECT_ID; +// // const testId = process.env.TEST_RUN_ID; + +// // if (!testId || !projectId) { +// // throw new Error("Environment configured incorrectly."); +// // } + +// // beforeAll(async () => { +// // await initializeFirebase(); +// // }); + +// // afterAll(async () => { +// // await admin.firestore().collection("databaseRefOnCreateTests").doc(testId).delete(); +// // await admin.firestore().collection("databaseRefOnDeleteTests").doc(testId).delete(); +// // await admin.firestore().collection("databaseRefOnUpdateTests").doc(testId).delete(); +// // await admin.firestore().collection("databaseRefOnWriteTests").doc(testId).delete(); +// // }); + +// // async function setupRef(refPath: string) { +// // const ref = admin.database().ref(refPath); +// // await ref.set({ ".sv": "timestamp" }); +// // return ref; +// // } + +// // async function teardownRef(ref: Reference) { +// // if (ref) { +// // try { +// // await ref.remove(); +// // } catch (err) { +// // logger.error("Teardown error", err); +// // } +// // } +// // } + +// // function getLoggedContext(collectionName: string, testId: string) { +// // return admin +// // .firestore() +// // .collection(collectionName) +// // .doc(testId) +// // .get() +// // .then((logSnapshot) => logSnapshot.data()); +// // } + +// // describe("ref onCreate trigger", () => { +// // let ref: Reference; +// // let loggedContext: admin.firestore.DocumentData | undefined; + +// // beforeAll(async () => { +// // ref = await setupRef(`dbTests/${testId}/start`); +// // loggedContext = await retry(() => getLoggedContext("databaseRefOnCreateTests", testId)); +// // }); + +// // afterAll(async () => { +// // await teardownRef(ref); +// // }); + +// // it("should not have event.app", () => { +// // expect(loggedContext?.app).toBeUndefined(); +// // }); + +// // it("should give refs access to admin data", async () => { +// // await ref.parent?.child("adminOnly").update({ allowed: 1 }); + +// // const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); +// // const adminData = adminDataSnapshot?.val(); + +// // expect(adminData).toEqual({ allowed: 1 }); +// // }); + +// // it("should have a correct ref url", () => { +// // expect(loggedContext?.url).toMatch( +// // new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) +// // ); +// // }); + +// // it("should have refs resources", () => { +// // expect(loggedContext?.resource.name).toMatch( +// // new RegExp( +// // `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start` +// // ) +// // ); +// // }); + +// // it("should not include path", () => { +// // expect(loggedContext?.path).toBeUndefined(); +// // }); + +// // it("should have the right eventType", () => { +// // expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.create"); +// // }); + +// // it("should have eventId", () => { +// // expect(loggedContext?.eventId).toBeDefined(); +// // }); + +// // it("should have timestamp", () => { +// // expect(loggedContext?.timestamp).toBeDefined(); +// // }); + +// // it("should not have action", () => { +// // expect(loggedContext?.action).toBeUndefined(); +// // }); + +// // it("should have admin authType", () => { +// // expect(loggedContext?.authType).toEqual("ADMIN"); +// // }); +// // }); + +// // describe("ref onDelete trigger", () => { +// // let ref: Reference; +// // let loggedContext: admin.firestore.DocumentData | undefined; + +// // beforeAll(async () => { +// // ref = await setupRef(`dbTests/${testId}/start`); +// // await ref.remove(); +// // loggedContext = await retry(() => getLoggedContext("databaseRefOnDeleteTests", testId)); +// // }); + +// // it("should not have event.app", () => { +// // expect(loggedContext?.app).toBeUndefined(); +// // }); + +// // it("should have a correct ref url", () => { +// // expect(loggedContext?.url).toMatch( +// // new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) +// // ); +// // }); + +// // it("should have refs resources", () => { +// // expect(loggedContext?.resource.name).toMatch( +// // new RegExp( +// // `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` +// // ) +// // ); +// // }); + +// // it("should not include path", () => { +// // expect(loggedContext?.path).toBeUndefined(); +// // }); + +// // it("should have the right eventType", () => { +// // expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.delete"); +// // }); + +// // it("should have eventId", () => { +// // expect(loggedContext?.eventId).toBeDefined(); +// // }); + +// // it("should have timestamp", () => { +// // expect(loggedContext?.timestamp).toBeDefined(); +// // }); + +// // it("should not have action", () => { +// // expect(loggedContext?.action).toBeUndefined(); +// // }); + +// // it("should have admin authType", () => { +// // expect(loggedContext?.authType).toEqual("ADMIN"); +// // }); +// // }); + +// // describe("ref onUpdate trigger", () => { +// // let ref: Reference; +// // let loggedContext: admin.firestore.DocumentData | undefined; + +// // beforeAll(async () => { +// // ref = await setupRef(`dbTests/${testId}/start`); +// // await ref.update({ updated: true }); +// // loggedContext = await retry(() => getLoggedContext("databaseRefOnUpdateTests", testId)); +// // }); + +// // afterAll(async () => { +// // await teardownRef(ref); +// // }); + +// // it("should not have event.app", () => { +// // expect(loggedContext?.app).toBeUndefined(); +// // }); + +// // it("should give refs access to admin data", async () => { +// // await ref.parent?.child("adminOnly").update({ allowed: 1 }); + +// // const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); +// // const adminData = adminDataSnapshot?.val(); + +// // expect(adminData).toEqual({ allowed: 1 }); +// // }); + +// // it("should have a correct ref url", () => { +// // expect(loggedContext?.url).toMatch( +// // new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) +// // ); +// // }); + +// // it("should have refs resources", () => { +// // expect(loggedContext?.resource.name).toMatch( +// // new RegExp( +// // `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` +// // ) +// // ); +// // }); + +// // it("should not include path", () => { +// // expect(loggedContext?.path).toBeUndefined(); +// // }); + +// // it("should have the right eventType", () => { +// // expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.update"); +// // }); + +// // it("should have eventId", () => { +// // expect(loggedContext?.eventId).toBeDefined(); +// // }); + +// // it("should have timestamp", () => { +// // expect(loggedContext?.timestamp).toBeDefined(); +// // }); + +// // it("should not have action", () => { +// // expect(loggedContext?.action).toBeUndefined(); +// // }); + +// // it("should have admin authType", () => { +// // expect(loggedContext?.authType).toEqual("ADMIN"); +// // }); + +// // it("should log onUpdate event with updated data", async () => { +// // const parsedData = JSON.parse(loggedContext?.data ?? {}); +// // expect(parsedData).toEqual({ updated: true }); +// // }); +// // }); + +// // describe("ref onWrite trigger", () => { +// // let ref: Reference; +// // let loggedContext: admin.firestore.DocumentData | undefined; + +// // beforeAll(async () => { +// // ref = await setupRef(`dbTests/${testId}/start`); + +// // loggedContext = await retry(() => getLoggedContext("databaseRefOnWriteTests", testId)); +// // }); + +// // afterAll(async () => { +// // await teardownRef(ref); +// // }); + +// // it("should not have event.app", () => { +// // expect(loggedContext?.app).toBeUndefined(); +// // }); + +// // it("should give refs access to admin data", async () => { +// // await ref.parent?.child("adminOnly").update({ allowed: 1 }); + +// // const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); +// // const adminData = adminDataSnapshot?.val(); + +// // expect(adminData).toEqual({ allowed: 1 }); +// // }); + +// // it("should have a correct ref url", () => { +// // expect(loggedContext?.url).toMatch( +// // new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) +// // ); +// // }); + +// // it("should have refs resources", () => { +// // expect(loggedContext?.resource.name).toMatch( +// // new RegExp( +// // `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` +// // ) +// // ); +// // }); + +// // it("should not include path", () => { +// // expect(loggedContext?.path).toBeUndefined(); +// // }); + +// // it("should have the right eventType", () => { +// // expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.write"); +// // }); + +// // it("should have eventId", () => { +// // expect(loggedContext?.eventId).toBeDefined(); +// // }); + +// // it("should have timestamp", () => { +// // expect(loggedContext?.timestamp).toBeDefined(); +// // }); + +// // it("should not have action", () => { +// // expect(loggedContext?.action).toBeUndefined(); +// // }); + +// // it("should have admin authType", () => { +// // expect(loggedContext?.authType).toEqual("ADMIN"); +// // }); +// // }); + +// }); diff --git a/integration_test/tests/v1/firestore.test.ts b/integration_test/tests/v1/firestore.test.ts index 1e3e77c40..ee6b8e445 100644 --- a/integration_test/tests/v1/firestore.test.ts +++ b/integration_test/tests/v1/firestore.test.ts @@ -1,248 +1,248 @@ -import * as admin from "firebase-admin"; -import { initializeFirebase } from "../firebaseSetup"; -import { retry } from "../utils"; - -describe("Cloud Firestore (v1)", () => { - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; - - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } - - beforeAll(async () => { - await initializeFirebase(); - }); - - afterAll(async () => { - await admin.firestore().collection("firestoreDocumentOnCreateTests").doc(testId).delete(); - await admin.firestore().collection("firestoreDocumentOnDeleteTests").doc(testId).delete(); - await admin.firestore().collection("firestoreDocumentOnUpdateTests").doc(testId).delete(); - await admin.firestore().collection("firestoreDocumentOnWriteTests").doc(testId).delete(); - }); - - describe("Document onCreate trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - let dataSnapshot: admin.firestore.DocumentSnapshot; - let docRef: admin.firestore.DocumentReference; - - beforeAll(async () => { - docRef = admin.firestore().collection("tests").doc(testId); - await docRef.set({ test: testId }); - dataSnapshot = await docRef.get(); - - loggedContext = await retry(() => - admin - .firestore() - .collection("firestoreDocumentOnCreateTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - afterAll(async () => { - await admin.firestore().collection("tests").doc(testId).delete(); - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should give refs access to admin data", async () => { - const result = await docRef.set({ allowed: 1 }, { merge: true }); - expect(result).toBeTruthy(); - }); - - it("should have well-formed resource", () => { - expect(loggedContext?.resource.name).toMatch( - `projects/${projectId}/databases/(default)/documents/tests/${testId}` - ); - }); - - it("should have the correct eventType", () => { - expect(loggedContext?.eventType).toEqual("google.firestore.document.create"); - }); - - it("should have an eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have a timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - - it("should have the correct data", () => { - expect(dataSnapshot.data()).toEqual({ test: testId }); - }); - }); - - describe("Document onDelete trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - let dataSnapshot: admin.firestore.DocumentSnapshot; - let docRef: admin.firestore.DocumentReference; - - beforeAll(async () => { - docRef = admin.firestore().collection("tests").doc(testId); - await docRef.set({ test: testId }); - dataSnapshot = await docRef.get(); - - await docRef.delete(); - - // Refresh snapshot - dataSnapshot = await docRef.get(); - - loggedContext = await retry(() => - admin - .firestore() - .collection("firestoreDocumentOnDeleteTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - afterAll(async () => { - await admin.firestore().collection("tests").doc(testId).delete(); - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should have well-formed resource", () => { - expect(loggedContext?.resource.name).toMatch( - `projects/${projectId}/databases/(default)/documents/tests/${testId}` - ); - }); - - it("should have the correct eventType", () => { - expect(loggedContext?.eventType).toEqual("google.firestore.document.delete"); - }); - - it("should have an eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have a timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - - it("should not have the data", () => { - expect(dataSnapshot.data()).toBeUndefined(); - }); - }); - - describe("Document onUpdate trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - let dataSnapshot: admin.firestore.DocumentSnapshot; - let docRef: admin.firestore.DocumentReference; - - beforeAll(async () => { - docRef = admin.firestore().collection("tests").doc(testId); - await docRef.set({}); - dataSnapshot = await docRef.get(); - - await docRef.update({ test: testId }); - - // Refresh snapshot - dataSnapshot = await docRef.get(); - - loggedContext = await retry(() => - admin - .firestore() - .collection("firestoreDocumentOnUpdateTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - afterAll(async () => { - await admin.firestore().collection("tests").doc(testId).delete(); - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should have well-formed resource", () => { - expect(loggedContext?.resource.name).toMatch( - `projects/${projectId}/databases/(default)/documents/tests/${testId}` - ); - }); - - it("should have the correct eventType", () => { - expect(loggedContext?.eventType).toEqual("google.firestore.document.update"); - }); - - it("should have an eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have a timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - - it("should not have the data", () => { - expect(dataSnapshot.data()).toStrictEqual({ test: testId }); - }); - }); - - describe("Document onWrite trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - let dataSnapshot: admin.firestore.DocumentSnapshot; - let docRef: admin.firestore.DocumentReference; - - beforeAll(async () => { - docRef = admin.firestore().collection("tests").doc(testId); - await docRef.set({ test: testId }); - dataSnapshot = await docRef.get(); - - loggedContext = await retry( - () => - admin - .firestore() - .collection("firestoreDocumentOnWriteTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()), - ); - }); - - afterAll(async () => { - await admin.firestore().collection("tests").doc(testId).delete(); - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should give refs access to admin data", async () => { - const result = await docRef.set({ allowed: 1 }, { merge: true }); - expect(result).toBeTruthy(); - }); - - it("should have well-formed resource", () => { - expect(loggedContext?.resource.name).toMatch( - `projects/${projectId}/databases/(default)/documents/tests/${testId}` - ); - }); - - it("should have the correct eventType", () => { - expect(loggedContext?.eventType).toEqual("google.firestore.document.write"); - }); - - it("should have an eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have a timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - - it("should have the correct data", () => { - expect(dataSnapshot.data()).toEqual({ test: testId }); - }); - }); -}); +// import * as admin from "firebase-admin"; +// import { initializeFirebase } from "../firebaseSetup"; +// import { retry } from "../utils"; + +// describe("Cloud Firestore (v1)", () => { +// const projectId = process.env.PROJECT_ID; +// const testId = process.env.TEST_RUN_ID; + +// if (!testId || !projectId) { +// throw new Error("Environment configured incorrectly."); +// } + +// beforeAll(async () => { +// await initializeFirebase(); +// }); + +// afterAll(async () => { +// await admin.firestore().collection("firestoreDocumentOnCreateTests").doc(testId).delete(); +// await admin.firestore().collection("firestoreDocumentOnDeleteTests").doc(testId).delete(); +// await admin.firestore().collection("firestoreDocumentOnUpdateTests").doc(testId).delete(); +// await admin.firestore().collection("firestoreDocumentOnWriteTests").doc(testId).delete(); +// }); + +// describe("Document onCreate trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; +// let dataSnapshot: admin.firestore.DocumentSnapshot; +// let docRef: admin.firestore.DocumentReference; + +// beforeAll(async () => { +// docRef = admin.firestore().collection("tests").doc(testId); +// await docRef.set({ test: testId }); +// dataSnapshot = await docRef.get(); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("firestoreDocumentOnCreateTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// afterAll(async () => { +// await admin.firestore().collection("tests").doc(testId).delete(); +// }); + +// it("should not have event.app", () => { +// expect(loggedContext?.app).toBeUndefined(); +// }); + +// it("should give refs access to admin data", async () => { +// const result = await docRef.set({ allowed: 1 }, { merge: true }); +// expect(result).toBeTruthy(); +// }); + +// it("should have well-formed resource", () => { +// expect(loggedContext?.resource.name).toMatch( +// `projects/${projectId}/databases/(default)/documents/tests/${testId}` +// ); +// }); + +// it("should have the correct eventType", () => { +// expect(loggedContext?.eventType).toEqual("google.firestore.document.create"); +// }); + +// it("should have an eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have a timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); + +// it("should have the correct data", () => { +// expect(dataSnapshot.data()).toEqual({ test: testId }); +// }); +// }); + +// describe("Document onDelete trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; +// let dataSnapshot: admin.firestore.DocumentSnapshot; +// let docRef: admin.firestore.DocumentReference; + +// beforeAll(async () => { +// docRef = admin.firestore().collection("tests").doc(testId); +// await docRef.set({ test: testId }); +// dataSnapshot = await docRef.get(); + +// await docRef.delete(); + +// // Refresh snapshot +// dataSnapshot = await docRef.get(); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("firestoreDocumentOnDeleteTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// afterAll(async () => { +// await admin.firestore().collection("tests").doc(testId).delete(); +// }); + +// it("should not have event.app", () => { +// expect(loggedContext?.app).toBeUndefined(); +// }); + +// it("should have well-formed resource", () => { +// expect(loggedContext?.resource.name).toMatch( +// `projects/${projectId}/databases/(default)/documents/tests/${testId}` +// ); +// }); + +// it("should have the correct eventType", () => { +// expect(loggedContext?.eventType).toEqual("google.firestore.document.delete"); +// }); + +// it("should have an eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have a timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); + +// it("should not have the data", () => { +// expect(dataSnapshot.data()).toBeUndefined(); +// }); +// }); + +// describe("Document onUpdate trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; +// let dataSnapshot: admin.firestore.DocumentSnapshot; +// let docRef: admin.firestore.DocumentReference; + +// beforeAll(async () => { +// docRef = admin.firestore().collection("tests").doc(testId); +// await docRef.set({}); +// dataSnapshot = await docRef.get(); + +// await docRef.update({ test: testId }); + +// // Refresh snapshot +// dataSnapshot = await docRef.get(); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("firestoreDocumentOnUpdateTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// afterAll(async () => { +// await admin.firestore().collection("tests").doc(testId).delete(); +// }); + +// it("should not have event.app", () => { +// expect(loggedContext?.app).toBeUndefined(); +// }); + +// it("should have well-formed resource", () => { +// expect(loggedContext?.resource.name).toMatch( +// `projects/${projectId}/databases/(default)/documents/tests/${testId}` +// ); +// }); + +// it("should have the correct eventType", () => { +// expect(loggedContext?.eventType).toEqual("google.firestore.document.update"); +// }); + +// it("should have an eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have a timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); + +// it("should not have the data", () => { +// expect(dataSnapshot.data()).toStrictEqual({ test: testId }); +// }); +// }); + +// describe("Document onWrite trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; +// let dataSnapshot: admin.firestore.DocumentSnapshot; +// let docRef: admin.firestore.DocumentReference; + +// beforeAll(async () => { +// docRef = admin.firestore().collection("tests").doc(testId); +// await docRef.set({ test: testId }); +// dataSnapshot = await docRef.get(); + +// loggedContext = await retry( +// () => +// admin +// .firestore() +// .collection("firestoreDocumentOnWriteTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()), +// ); +// }); + +// afterAll(async () => { +// await admin.firestore().collection("tests").doc(testId).delete(); +// }); + +// it("should not have event.app", () => { +// expect(loggedContext?.app).toBeUndefined(); +// }); + +// it("should give refs access to admin data", async () => { +// const result = await docRef.set({ allowed: 1 }, { merge: true }); +// expect(result).toBeTruthy(); +// }); + +// it("should have well-formed resource", () => { +// expect(loggedContext?.resource.name).toMatch( +// `projects/${projectId}/databases/(default)/documents/tests/${testId}` +// ); +// }); + +// it("should have the correct eventType", () => { +// expect(loggedContext?.eventType).toEqual("google.firestore.document.write"); +// }); + +// it("should have an eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have a timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); + +// it("should have the correct data", () => { +// expect(dataSnapshot.data()).toEqual({ test: testId }); +// }); +// }); +// }); diff --git a/integration_test/tests/v1/pubsub.test.ts b/integration_test/tests/v1/pubsub.test.ts index aecc71835..ffabd467a 100644 --- a/integration_test/tests/v1/pubsub.test.ts +++ b/integration_test/tests/v1/pubsub.test.ts @@ -1,113 +1,113 @@ -import { PubSub } from "@google-cloud/pubsub"; -import * as admin from "firebase-admin"; -import { initializeFirebase } from "../firebaseSetup"; -import { retry } from "../utils"; - -describe("Pub/Sub (v1)", () => { - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; - const region = process.env.REGION; - const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; - const topicName = `firebase-schedule-${testId}-v1-pubsubScheduleTests-${region}`; - - if (!testId || !projectId || !region || !serviceAccountPath) { - throw new Error("Environment configured incorrectly."); - } - - beforeAll(async () => { - await initializeFirebase(); - }); - - afterAll(async () => { - await admin.firestore().collection("pubsubOnPublishTests").doc(testId).delete(); - await admin.firestore().collection("pubsubScheduleTests").doc(topicName).delete(); - }); - - describe("onPublish trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - const serviceAccount = await import(serviceAccountPath); - const topic = new PubSub({ - credentials: serviceAccount.default, - projectId, - }).topic("pubsubTests"); - - await topic.publish(Buffer.from(JSON.stringify({ testId }))); - - loggedContext = await retry(() => - admin - .firestore() - .collection("pubsubOnPublishTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - it("should have a topic as resource", () => { - expect(loggedContext?.resource.name).toEqual( - `projects/${process.env.PROJECT_ID}/topics/pubsubTests` - ); - }); - - it("should not have a path", () => { - expect(loggedContext?.path).toBeUndefined(); - }); - - it("should have the correct eventType", () => { - expect(loggedContext?.eventType).toEqual("google.pubsub.topic.publish"); - }); - - it("should have an eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - - it("should not have action", () => { - expect(loggedContext?.action).toBeUndefined(); - }); - - it("should have admin auth", () => { - expect(loggedContext?.auth).toBeUndefined(); - }); - - it("should have pubsub data", () => { - const decodedMessage = JSON.parse(loggedContext?.message); - const decoded = new Buffer(decodedMessage.data, "base64").toString(); - const parsed = JSON.parse(decoded); - expect(parsed.testId).toEqual(testId); - }); - }); - - describe("schedule trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - const pubsub = new PubSub(); - - const message = Buffer.from(JSON.stringify({ testId })); - - await pubsub.topic(topicName).publish(message); - - loggedContext = await retry(() => - admin - .firestore() - .collection("pubsubScheduleTests") - .doc(topicName) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - if (!loggedContext) { - throw new Error("loggedContext is undefined"); - } - }); - - it("should have been called", () => { - expect(loggedContext).toBeDefined(); - }); - }); -}); +// import { PubSub } from "@google-cloud/pubsub"; +// import * as admin from "firebase-admin"; +// import { initializeFirebase } from "../firebaseSetup"; +// import { retry } from "../utils"; + +// describe("Pub/Sub (v1)", () => { +// const projectId = process.env.PROJECT_ID; +// const testId = process.env.TEST_RUN_ID; +// const region = process.env.REGION; +// const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; +// const topicName = `firebase-schedule-${testId}-v1-pubsubScheduleTests-${region}`; + +// if (!testId || !projectId || !region || !serviceAccountPath) { +// throw new Error("Environment configured incorrectly."); +// } + +// beforeAll(async () => { +// await initializeFirebase(); +// }); + +// afterAll(async () => { +// await admin.firestore().collection("pubsubOnPublishTests").doc(testId).delete(); +// await admin.firestore().collection("pubsubScheduleTests").doc(topicName).delete(); +// }); + +// describe("onPublish trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// const serviceAccount = await import(serviceAccountPath); +// const topic = new PubSub({ +// credentials: serviceAccount.default, +// projectId, +// }).topic("pubsubTests"); + +// await topic.publish(Buffer.from(JSON.stringify({ testId }))); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("pubsubOnPublishTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// it("should have a topic as resource", () => { +// expect(loggedContext?.resource.name).toEqual( +// `projects/${process.env.PROJECT_ID}/topics/pubsubTests` +// ); +// }); + +// it("should not have a path", () => { +// expect(loggedContext?.path).toBeUndefined(); +// }); + +// it("should have the correct eventType", () => { +// expect(loggedContext?.eventType).toEqual("google.pubsub.topic.publish"); +// }); + +// it("should have an eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); + +// it("should not have action", () => { +// expect(loggedContext?.action).toBeUndefined(); +// }); + +// it("should have admin auth", () => { +// expect(loggedContext?.auth).toBeUndefined(); +// }); + +// it("should have pubsub data", () => { +// const decodedMessage = JSON.parse(loggedContext?.message); +// const decoded = new Buffer(decodedMessage.data, "base64").toString(); +// const parsed = JSON.parse(decoded); +// expect(parsed.testId).toEqual(testId); +// }); +// }); + +// describe("schedule trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// const pubsub = new PubSub(); + +// const message = Buffer.from(JSON.stringify({ testId })); + +// await pubsub.topic(topicName).publish(message); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("pubsubScheduleTests") +// .doc(topicName) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// if (!loggedContext) { +// throw new Error("loggedContext is undefined"); +// } +// }); + +// it("should have been called", () => { +// expect(loggedContext).toBeDefined(); +// }); +// }); +// }); diff --git a/integration_test/tests/v1/remoteConfig.test.ts b/integration_test/tests/v1/remoteConfig.test.ts index e2e06b404..9f542ab1c 100644 --- a/integration_test/tests/v1/remoteConfig.test.ts +++ b/integration_test/tests/v1/remoteConfig.test.ts @@ -1,72 +1,72 @@ -import * as admin from "firebase-admin"; -import { retry } from "../utils"; -import { initializeFirebase } from "../firebaseSetup"; -import fetch from "node-fetch"; +// import * as admin from "firebase-admin"; +// import { retry } from "../utils"; +// import { initializeFirebase } from "../firebaseSetup"; +// import fetch from "node-fetch"; -describe("Firebase Remote Config (v1)", () => { - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; +// describe("Firebase Remote Config (v1)", () => { +// const projectId = process.env.PROJECT_ID; +// const testId = process.env.TEST_RUN_ID; - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } +// if (!testId || !projectId) { +// throw new Error("Environment configured incorrectly."); +// } - beforeAll(async () => { - await initializeFirebase(); - }); +// beforeAll(async () => { +// await initializeFirebase(); +// }); - afterAll(async () => { - await admin.firestore().collection("remoteConfigOnUpdateTests").doc(testId).delete(); - }); +// afterAll(async () => { +// await admin.firestore().collection("remoteConfigOnUpdateTests").doc(testId).delete(); +// }); - describe("onUpdate trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; +// describe("onUpdate trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; - beforeAll(async () => { - const accessToken = await admin.credential.applicationDefault().getAccessToken(); - const resp = await fetch( - `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/remoteConfig`, - { - method: "PUT", - headers: { - Authorization: `Bearer ${accessToken.access_token}`, - "Content-Type": "application/json; UTF-8", - "Accept-Encoding": "gzip", - "If-Match": "*", - }, - body: JSON.stringify({ version: { description: testId } }), - } - ); - if (!resp.ok) { - throw new Error(resp.statusText); - } - loggedContext = await retry(() => - admin - .firestore() - .collection("remoteConfigOnUpdateTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); +// beforeAll(async () => { +// const accessToken = await admin.credential.applicationDefault().getAccessToken(); +// const resp = await fetch( +// `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/remoteConfig`, +// { +// method: "PUT", +// headers: { +// Authorization: `Bearer ${accessToken.access_token}`, +// "Content-Type": "application/json; UTF-8", +// "Accept-Encoding": "gzip", +// "If-Match": "*", +// }, +// body: JSON.stringify({ version: { description: testId } }), +// } +// ); +// if (!resp.ok) { +// throw new Error(resp.statusText); +// } +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("remoteConfigOnUpdateTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); - it("should have refs resources", () => - expect(loggedContext?.resource.name).toMatch(`projects/${process.env.PROJECT_ID}`)); +// it("should have refs resources", () => +// expect(loggedContext?.resource.name).toMatch(`projects/${process.env.PROJECT_ID}`)); - it("should have the right eventType", () => { - expect(loggedContext?.eventType).toEqual("google.firebase.remoteconfig.update"); - }); +// it("should have the right eventType", () => { +// expect(loggedContext?.eventType).toEqual("google.firebase.remoteconfig.update"); +// }); - it("should have eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); +// it("should have eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); - it("should have timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); +// it("should have timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); - it("should not have auth", () => { - expect(loggedContext?.auth).toBeUndefined(); - }); - }); -}); +// it("should not have auth", () => { +// expect(loggedContext?.auth).toBeUndefined(); +// }); +// }); +// }); diff --git a/integration_test/tests/v1/storage.test.ts b/integration_test/tests/v1/storage.test.ts index 7f74d41af..2f8e4da33 100644 --- a/integration_test/tests/v1/storage.test.ts +++ b/integration_test/tests/v1/storage.test.ts @@ -1,179 +1,179 @@ -import * as admin from "firebase-admin"; -import { retry, timeout } from "../utils"; -import { initializeFirebase } from "../firebaseSetup"; - -async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { - const bucket = admin.storage().bucket(); - - const file = bucket.file(fileName); - await file.save(buffer, { - metadata: { - contentType: "text/plain", - }, - }); -} - -describe("Firebase Storage", () => { - const testId = process.env.TEST_RUN_ID; - if (!testId) { - throw new Error("Environment configured incorrectly."); - } - - beforeAll(async () => { - await initializeFirebase(); - }); - - afterAll(async () => { - await admin.firestore().collection("storageOnFinalizeTests").doc(testId).delete(); - await admin.firestore().collection("storageOnDeleteTests").doc(testId).delete(); - await admin.firestore().collection("storageOnMetadataUpdateTests").doc(testId).delete(); - }); - - describe("object onFinalize trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - const testContent = testId; - const buffer = Buffer.from(testContent, "utf-8"); - - await uploadBufferToFirebase(buffer, testId + ".txt"); - - loggedContext = await retry(() => - admin - .firestore() - .collection("storageOnFinalizeTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - afterAll(async () => { - const file = admin - .storage() - .bucket() - .file(testId + ".txt"); - - const [exists] = await file.exists(); - if (exists) { - await file.delete(); - } - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should have the right eventType", () => { - expect(loggedContext?.eventType).toEqual("google.storage.object.finalize"); - }); - - it("should have eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - }); - - // TODO: (b/372315689) Re-enable function once bug is fixed - describe.skip("object onDelete trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - const testContent = testId; - const buffer = Buffer.from(testContent, "utf-8"); - - await uploadBufferToFirebase(buffer, testId + ".txt"); - - await timeout(5000); // Short delay before delete - - const file = admin - .storage() - .bucket() - .file(testId + ".txt"); - await file.delete(); - - const loggedContext = await retry(() => - admin - .firestore() - .collection("storageOnDeleteTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should have the right eventType", () => { - expect(loggedContext?.eventType).toEqual("google.storage.object.delete"); - }); - - it("should have eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - }); - - describe("object onMetadataUpdate trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - const testContent = testId; - const buffer = Buffer.from(testContent, "utf-8"); - - await uploadBufferToFirebase(buffer, testId + ".txt"); - - // Trigger metadata update - const file = admin - .storage() - .bucket() - .file(testId + ".txt"); - await file.setMetadata({ contentType: "application/json" }); - - loggedContext = await retry(() => - admin - .firestore() - .collection("storageOnMetadataUpdateTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - afterAll(async () => { - const file = admin - .storage() - .bucket() - .file(testId + ".txt"); - - const [exists] = await file.exists(); - if (exists) { - await file.delete(); - } - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should have the right eventType", () => { - expect(loggedContext?.eventType).toEqual("google.storage.object.metadataUpdate"); - }); - - it("should have eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - }); -}); +// import * as admin from "firebase-admin"; +// import { retry, timeout } from "../utils"; +// import { initializeFirebase } from "../firebaseSetup"; + +// async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { +// const bucket = admin.storage().bucket(); + +// const file = bucket.file(fileName); +// await file.save(buffer, { +// metadata: { +// contentType: "text/plain", +// }, +// }); +// } + +// describe("Firebase Storage", () => { +// const testId = process.env.TEST_RUN_ID; +// if (!testId) { +// throw new Error("Environment configured incorrectly."); +// } + +// beforeAll(async () => { +// await initializeFirebase(); +// }); + +// afterAll(async () => { +// await admin.firestore().collection("storageOnFinalizeTests").doc(testId).delete(); +// await admin.firestore().collection("storageOnDeleteTests").doc(testId).delete(); +// await admin.firestore().collection("storageOnMetadataUpdateTests").doc(testId).delete(); +// }); + +// describe("object onFinalize trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// const testContent = testId; +// const buffer = Buffer.from(testContent, "utf-8"); + +// await uploadBufferToFirebase(buffer, testId + ".txt"); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("storageOnFinalizeTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// afterAll(async () => { +// const file = admin +// .storage() +// .bucket() +// .file(testId + ".txt"); + +// const [exists] = await file.exists(); +// if (exists) { +// await file.delete(); +// } +// }); + +// it("should not have event.app", () => { +// expect(loggedContext?.app).toBeUndefined(); +// }); + +// it("should have the right eventType", () => { +// expect(loggedContext?.eventType).toEqual("google.storage.object.finalize"); +// }); + +// it("should have eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); +// }); + +// // TODO: (b/372315689) Re-enable function once bug is fixed +// describe.skip("object onDelete trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// const testContent = testId; +// const buffer = Buffer.from(testContent, "utf-8"); + +// await uploadBufferToFirebase(buffer, testId + ".txt"); + +// await timeout(5000); // Short delay before delete + +// const file = admin +// .storage() +// .bucket() +// .file(testId + ".txt"); +// await file.delete(); + +// const loggedContext = await retry(() => +// admin +// .firestore() +// .collection("storageOnDeleteTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// it("should not have event.app", () => { +// expect(loggedContext?.app).toBeUndefined(); +// }); + +// it("should have the right eventType", () => { +// expect(loggedContext?.eventType).toEqual("google.storage.object.delete"); +// }); + +// it("should have eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); +// }); + +// describe("object onMetadataUpdate trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// const testContent = testId; +// const buffer = Buffer.from(testContent, "utf-8"); + +// await uploadBufferToFirebase(buffer, testId + ".txt"); + +// // Trigger metadata update +// const file = admin +// .storage() +// .bucket() +// .file(testId + ".txt"); +// await file.setMetadata({ contentType: "application/json" }); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("storageOnMetadataUpdateTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// afterAll(async () => { +// const file = admin +// .storage() +// .bucket() +// .file(testId + ".txt"); + +// const [exists] = await file.exists(); +// if (exists) { +// await file.delete(); +// } +// }); + +// it("should not have event.app", () => { +// expect(loggedContext?.app).toBeUndefined(); +// }); + +// it("should have the right eventType", () => { +// expect(loggedContext?.eventType).toEqual("google.storage.object.metadataUpdate"); +// }); + +// it("should have eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); +// }); +// }); diff --git a/integration_test/tests/v1/tasks.test.ts b/integration_test/tests/v1/tasks.test.ts index 3677adf51..ec7f41c3a 100644 --- a/integration_test/tests/v1/tasks.test.ts +++ b/integration_test/tests/v1/tasks.test.ts @@ -1,44 +1,44 @@ -import * as admin from "firebase-admin"; -import { initializeFirebase } from "../firebaseSetup"; -import { createTask, retry } from "../utils"; - -describe("Cloud Tasks (v1)", () => { - const region = process.env.REGION; - const testId = process.env.TEST_RUN_ID; - const projectId = process.env.PROJECT_ID; - const queueName = `${testId}-v1-tasksOnDispatchTests`; - - if (!testId || !projectId || !region) { - throw new Error("Environment configured incorrectly."); - } - - beforeAll(async () => { - await initializeFirebase(); - }); - - afterAll(async () => { - await admin.firestore().collection("tasksOnDispatchTests").doc(testId).delete(); - }); - - describe("onDispatch trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - const url = `https://${region}-${projectId}.cloudfunctions.net/${testId}-v1-tasksOnDispatchTests`; - await createTask(projectId, queueName, region, url, { data: { testId } }); - - loggedContext = await retry(() => - admin - .firestore() - .collection("tasksOnDispatchTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - it("should have correct event id", () => { - expect(loggedContext?.id).toBeDefined(); - }); - }); -}); +// import * as admin from "firebase-admin"; +// import { initializeFirebase } from "../firebaseSetup"; +// import { createTask, retry } from "../utils"; + +// describe("Cloud Tasks (v1)", () => { +// const region = process.env.REGION; +// const testId = process.env.TEST_RUN_ID; +// const projectId = process.env.PROJECT_ID; +// const queueName = `${testId}-v1-tasksOnDispatchTests`; + +// if (!testId || !projectId || !region) { +// throw new Error("Environment configured incorrectly."); +// } + +// beforeAll(async () => { +// await initializeFirebase(); +// }); + +// afterAll(async () => { +// await admin.firestore().collection("tasksOnDispatchTests").doc(testId).delete(); +// }); + +// describe("onDispatch trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// const url = `https://${region}-${projectId}.cloudfunctions.net/${testId}-v1-tasksOnDispatchTests`; +// await createTask(projectId, queueName, region, url, { data: { testId } }); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("tasksOnDispatchTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// it("should have correct event id", () => { +// expect(loggedContext?.id).toBeDefined(); +// }); +// }); +// }); diff --git a/integration_test/tests/v1/testLab.test.ts b/integration_test/tests/v1/testLab.test.ts index 92a1cab52..38532003b 100644 --- a/integration_test/tests/v1/testLab.test.ts +++ b/integration_test/tests/v1/testLab.test.ts @@ -1,51 +1,51 @@ -import * as admin from "firebase-admin"; -import { retry, startTestRun } from "../utils"; -import { initializeFirebase } from "../firebaseSetup"; - -describe("TestLab (v1)", () => { - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; - - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } - - beforeAll(async () => { - await initializeFirebase(); - }); - - afterAll(async () => { - await admin.firestore().collection("testLabOnCompleteTests").doc(testId).delete(); - }); - - describe("test matrix onComplete trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - const accessToken = await admin.credential.applicationDefault().getAccessToken(); - await startTestRun(projectId, testId, accessToken.access_token); - - loggedContext = await retry(() => - admin - .firestore() - .collection("testLabOnCompleteTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - it("should have eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have right eventType", () => { - expect(loggedContext?.eventType).toEqual("google.testing.testMatrix.complete"); - }); - - it("should be in state 'INVALID'", () => { - const matrix = JSON.parse(loggedContext?.matrix); - expect(matrix?.state).toEqual("INVALID"); - }); - }); -}); +// import * as admin from "firebase-admin"; +// import { retry, startTestRun } from "../utils"; +// import { initializeFirebase } from "../firebaseSetup"; + +// describe("TestLab (v1)", () => { +// const projectId = process.env.PROJECT_ID; +// const testId = process.env.TEST_RUN_ID; + +// if (!testId || !projectId) { +// throw new Error("Environment configured incorrectly."); +// } + +// beforeAll(async () => { +// await initializeFirebase(); +// }); + +// afterAll(async () => { +// await admin.firestore().collection("testLabOnCompleteTests").doc(testId).delete(); +// }); + +// describe("test matrix onComplete trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// const accessToken = await admin.credential.applicationDefault().getAccessToken(); +// await startTestRun(projectId, testId, accessToken.access_token); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("testLabOnCompleteTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// it("should have eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have right eventType", () => { +// expect(loggedContext?.eventType).toEqual("google.testing.testMatrix.complete"); +// }); + +// it("should be in state 'INVALID'", () => { +// const matrix = JSON.parse(loggedContext?.matrix); +// expect(matrix?.state).toEqual("INVALID"); +// }); +// }); +// }); diff --git a/integration_test/tests/v2/database.test.ts b/integration_test/tests/v2/database.test.ts index 557ad05cf..7cb17bf58 100644 --- a/integration_test/tests/v2/database.test.ts +++ b/integration_test/tests/v2/database.test.ts @@ -2,6 +2,7 @@ import * as admin from "firebase-admin"; import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; import { Reference } from "@firebase/database-types"; +import { logger } from "../../src/logger"; describe("Firebase Database (v2)", () => { const projectId = process.env.PROJECT_ID; @@ -16,10 +17,22 @@ describe("Firebase Database (v2)", () => { }); afterAll(async () => { - await admin.firestore().collection("databaseCreatedTests").doc(testId).delete(); - await admin.firestore().collection("databaseDeletedTests").doc(testId).delete(); - await admin.firestore().collection("databaseUpdatesTests").doc(testId).delete(); - await admin.firestore().collection("databaseWrittenTests").doc(testId).delete(); + console.log("🧹 Cleaning up test data..."); + const collectionsToClean = [ + "databaseCreatedTests", + "databaseDeletedTests", + "databaseUpdatesTests", + "databaseWrittenTests" + ]; + + for (const collection of collectionsToClean) { + try { + await admin.firestore().collection(collection).doc(testId).delete(); + console.log(`🗑️ Deleted test document: ${collection}/${testId}`); + } catch (error) { + console.log(`ℹ️ No test document to delete: ${collection}/${testId}`); + } + } }); async function setupRef(refPath: string) { @@ -33,7 +46,7 @@ describe("Firebase Database (v2)", () => { try { await ref.remove(); } catch (err) { - console.log("Teardown error", err); + logger.error("Teardown error", err); } } } @@ -88,114 +101,114 @@ describe("Firebase Database (v2)", () => { }); }); - describe("deleted trigger", () => { - let ref: Reference; - let loggedContext: admin.firestore.DocumentData | undefined; + // describe("deleted trigger", () => { + // let ref: Reference; + // let loggedContext: admin.firestore.DocumentData | undefined; - beforeAll(async () => { - ref = await setupRef(`databaseDeletedTests/${testId}/start`); - await teardownRef(ref); - loggedContext = await getLoggedContext("databaseDeletedTests", testId); - }); + // beforeAll(async () => { + // ref = await setupRef(`databaseDeletedTests/${testId}/start`); + // await teardownRef(ref); + // loggedContext = await getLoggedContext("databaseDeletedTests", testId); + // }); - it("should have a correct ref url", () => { - expect(loggedContext?.url).toMatch(`databaseDeletedTests/${testId}/start`); - }); + // it("should have a correct ref url", () => { + // expect(loggedContext?.url).toMatch(`databaseDeletedTests/${testId}/start`); + // }); - it("should have the right event type", () => { - expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.deleted"); - }); + // it("should have the right event type", () => { + // expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.deleted"); + // }); - it("should have event id", () => { - expect(loggedContext?.id).toBeDefined(); - }); + // it("should have event id", () => { + // expect(loggedContext?.id).toBeDefined(); + // }); - it("should have a time", () => { - expect(loggedContext?.time).toBeDefined(); - }); - }); + // it("should have a time", () => { + // expect(loggedContext?.time).toBeDefined(); + // }); + // }); - describe("updated trigger", () => { - let ref: Reference; - let loggedContext: admin.firestore.DocumentData | undefined; + // describe("updated trigger", () => { + // let ref: Reference; + // let loggedContext: admin.firestore.DocumentData | undefined; - beforeAll(async () => { - ref = await setupRef(`databaseUpdatedTests/${testId}/start`); - await ref.update({ updated: true }); - loggedContext = await getLoggedContext("databaseUpdatedTests", testId); - }); + // beforeAll(async () => { + // ref = await setupRef(`databaseUpdatedTests/${testId}/start`); + // await ref.update({ updated: true }); + // loggedContext = await getLoggedContext("databaseUpdatedTests", testId); + // }); - afterAll(async () => { - await teardownRef(ref); - }); + // afterAll(async () => { + // await teardownRef(ref); + // }); - it("should give refs access to admin data", async () => { - await ref.parent?.child("adminOnly").update({ allowed: 1 }); - - const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); - const adminData = adminDataSnapshot?.val(); + // it("should give refs access to admin data", async () => { + // await ref.parent?.child("adminOnly").update({ allowed: 1 }); - expect(adminData).toEqual({ allowed: 1 }); - }); - - it("should have a correct ref url", () => { - expect(loggedContext?.url).toMatch(`databaseUpdatedTests/${testId}/start`); - }); + // const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); + // const adminData = adminDataSnapshot?.val(); - it("should have the right event type", () => { - expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.updated"); - }); + // expect(adminData).toEqual({ allowed: 1 }); + // }); - it("should have event id", () => { - expect(loggedContext?.id).toBeDefined(); - }); + // it("should have a correct ref url", () => { + // expect(loggedContext?.url).toMatch(`databaseUpdatedTests/${testId}/start`); + // }); - it("should have a time", () => { - expect(loggedContext?.time).toBeDefined(); - }); + // it("should have the right event type", () => { + // expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.updated"); + // }); - it("should have updated data", async () => { - const parsedData = JSON.parse(loggedContext?.data ?? {}); - expect(parsedData).toEqual({ updated: true }); - }); - }); + // it("should have event id", () => { + // expect(loggedContext?.id).toBeDefined(); + // }); - describe("written trigger", () => { - let ref: Reference; - let loggedContext: admin.firestore.DocumentData | undefined; + // it("should have a time", () => { + // expect(loggedContext?.time).toBeDefined(); + // }); - beforeAll(async () => { - ref = await setupRef(`databaseWrittenTests/${testId}/start`); - loggedContext = await getLoggedContext("databaseWrittenTests", testId); - }); + // it("should have updated data", async () => { + // const parsedData = JSON.parse(loggedContext?.data ?? {}); + // expect(parsedData).toEqual({ updated: true }); + // }); + // }); - afterAll(async () => { - await teardownRef(ref); - }); + // describe("written trigger", () => { + // let ref: Reference; + // let loggedContext: admin.firestore.DocumentData | undefined; - it("should give refs access to admin data", async () => { - await ref.parent?.child("adminOnly").update({ allowed: 1 }); + // beforeAll(async () => { + // ref = await setupRef(`databaseWrittenTests/${testId}/start`); + // loggedContext = await getLoggedContext("databaseWrittenTests", testId); + // }); - const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); - const adminData = adminDataSnapshot?.val(); + // afterAll(async () => { + // await teardownRef(ref); + // }); - expect(adminData).toEqual({ allowed: 1 }); - }); + // it("should give refs access to admin data", async () => { + // await ref.parent?.child("adminOnly").update({ allowed: 1 }); - it("should have a correct ref url", () => { - expect(loggedContext?.url).toMatch(`databaseWrittenTests/${testId}/start`); - }); + // const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); + // const adminData = adminDataSnapshot?.val(); - it("should have the right event type", () => { - expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.written"); - }); + // expect(adminData).toEqual({ allowed: 1 }); + // }); - it("should have event id", () => { - expect(loggedContext?.id).toBeDefined(); - }); + // it("should have a correct ref url", () => { + // expect(loggedContext?.url).toMatch(`databaseWrittenTests/${testId}/start`); + // }); - it("should have a time", () => { - expect(loggedContext?.time).toBeDefined(); - }); - }); + // it("should have the right event type", () => { + // expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.written"); + // }); + + // it("should have event id", () => { + // expect(loggedContext?.id).toBeDefined(); + // }); + + // it("should have a time", () => { + // expect(loggedContext?.time).toBeDefined(); + // }); + // }); }); diff --git a/integration_test/tests/v2/eventarc.test.ts b/integration_test/tests/v2/eventarc.test.ts index 950f80ff5..90bc76f46 100644 --- a/integration_test/tests/v2/eventarc.test.ts +++ b/integration_test/tests/v2/eventarc.test.ts @@ -1,69 +1,69 @@ -import * as admin from "firebase-admin"; -import { initializeFirebase } from "../firebaseSetup"; -import { CloudEvent, getEventarc } from "firebase-admin/eventarc"; -import { retry } from "../utils"; +// import * as admin from "firebase-admin"; +// import { initializeFirebase } from "../firebaseSetup"; +// import { CloudEvent, getEventarc } from "firebase-admin/eventarc"; +// import { retry } from "../utils"; -describe("Eventarc (v2)", () => { - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; - const region = process.env.REGION; +// describe("Eventarc (v2)", () => { +// const projectId = process.env.PROJECT_ID; +// const testId = process.env.TEST_RUN_ID; +// const region = process.env.REGION; - if (!testId || !projectId || !region) { - throw new Error("Environment configured incorrectly."); - } +// if (!testId || !projectId || !region) { +// throw new Error("Environment configured incorrectly."); +// } - beforeAll(async () => { - await initializeFirebase(); - }); +// beforeAll(async () => { +// await initializeFirebase(); +// }); - afterAll(async () => { - await admin.firestore().collection("eventarcOnCustomEventPublishedTests").doc(testId).delete(); - }); +// afterAll(async () => { +// await admin.firestore().collection("eventarcOnCustomEventPublishedTests").doc(testId).delete(); +// }); - describe("onCustomEventPublished trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; +// describe("onCustomEventPublished trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; - beforeAll(async () => { - const cloudEvent: CloudEvent = { - type: "achieved-leaderboard", - source: testId, - subject: "Welcome to the top 10", - data: { - message: "You have achieved the nth position in our leaderboard! To see...", - testId, - }, - }; - await getEventarc().channel(`locations/${region}/channels/firebase`).publish(cloudEvent); +// beforeAll(async () => { +// const cloudEvent: CloudEvent = { +// type: "achieved-leaderboard", +// source: testId, +// subject: "Welcome to the top 10", +// data: { +// message: "You have achieved the nth position in our leaderboard! To see...", +// testId, +// }, +// }; +// await getEventarc().channel(`locations/${region}/channels/firebase`).publish(cloudEvent); - loggedContext = await retry(() => - admin - .firestore() - .collection("eventarcOnCustomEventPublishedTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("eventarcOnCustomEventPublishedTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); - it("should have well-formed source", () => { - expect(loggedContext?.source).toMatch(testId); - }); +// it("should have well-formed source", () => { +// expect(loggedContext?.source).toMatch(testId); +// }); - it("should have the correct type", () => { - expect(loggedContext?.type).toEqual("achieved-leaderboard"); - }); +// it("should have the correct type", () => { +// expect(loggedContext?.type).toEqual("achieved-leaderboard"); +// }); - it("should have an id", () => { - expect(loggedContext?.id).toBeDefined(); - }); +// it("should have an id", () => { +// expect(loggedContext?.id).toBeDefined(); +// }); - it("should have a time", () => { - expect(loggedContext?.time).toBeDefined(); - }); +// it("should have a time", () => { +// expect(loggedContext?.time).toBeDefined(); +// }); - it("should not have the data", () => { - const eventData = JSON.parse(loggedContext?.data || "{}"); - expect(eventData.testId).toBeDefined(); - }); - }); -}); +// it("should not have the data", () => { +// const eventData = JSON.parse(loggedContext?.data || "{}"); +// expect(eventData.testId).toBeDefined(); +// }); +// }); +// }); diff --git a/integration_test/tests/v2/firestore.test.ts b/integration_test/tests/v2/firestore.test.ts index e982b89d4..d61ec6701 100644 --- a/integration_test/tests/v2/firestore.test.ts +++ b/integration_test/tests/v2/firestore.test.ts @@ -1,231 +1,231 @@ -import * as admin from "firebase-admin"; -import { retry } from "../utils"; -import { initializeFirebase } from "../firebaseSetup"; - -describe("Cloud Firestore (v2)", () => { - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; - - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } - - beforeAll(async () => { - await initializeFirebase(); - }); - - afterAll(async () => { - await admin.firestore().collection("firestoreOnDocumentCreatedTests").doc(testId).delete(); - await admin.firestore().collection("firestoreOnDocumentDeletedTests").doc(testId).delete(); - await admin.firestore().collection("firestoreOnDocumentUpdatedTests").doc(testId).delete(); - await admin.firestore().collection("firestoreOnDocumentWrittenTests").doc(testId).delete(); - }); - - describe("Document created trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - let dataSnapshot: admin.firestore.DocumentSnapshot; - let docRef: admin.firestore.DocumentReference; - - beforeAll(async () => { - docRef = admin.firestore().collection("tests").doc(testId); - await docRef.set({ test: testId }); - dataSnapshot = await docRef.get(); - - loggedContext = await retry(() => - admin - .firestore() - .collection("firestoreOnDocumentCreatedTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should give refs access to admin data", async () => { - const result = await docRef.set({ allowed: 1 }, { merge: true }); - expect(result).toBeTruthy(); - }); - - it("should have well-formed resource", () => { - expect(loggedContext?.source).toMatch( - `//firestore.googleapis.com/projects/${projectId}/databases/(default)` - ); - }); - - it("should have the correct type", () => { - expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.created"); - }); - - it("should have an id", () => { - expect(loggedContext?.id).toBeDefined(); - }); - - it("should have a time", () => { - expect(loggedContext?.time).toBeDefined(); - }); - - it("should have the correct data", () => { - expect(dataSnapshot.data()).toEqual({ test: testId }); - }); - }); - - describe("Document deleted trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - let dataSnapshot: admin.firestore.DocumentSnapshot; - let docRef: admin.firestore.DocumentReference; - - beforeAll(async () => { - docRef = admin.firestore().collection("tests").doc(testId); - await docRef.set({ test: testId }); - dataSnapshot = await docRef.get(); - - await docRef.delete(); - - // Refresh snapshot - dataSnapshot = await docRef.get(); - - loggedContext = await retry(() => - admin - .firestore() - .collection("firestoreOnDocumentDeletedTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should have well-formed source", () => { - expect(loggedContext?.source).toMatch( - `//firestore.googleapis.com/projects/${projectId}/databases/(default)` - ); - }); - - it("should have the correct type", () => { - expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.deleted"); - }); - - it("should have an id", () => { - expect(loggedContext?.id).toBeDefined(); - }); - - it("should have a time", () => { - expect(loggedContext?.time).toBeDefined(); - }); - - it("should not have the data", () => { - expect(dataSnapshot.data()).toBeUndefined(); - }); - }); - - describe("Document updated trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - let dataSnapshot: admin.firestore.DocumentSnapshot; - let docRef: admin.firestore.DocumentReference; - - beforeAll(async () => { - docRef = admin.firestore().collection("tests").doc(testId); - await docRef.set({}); - dataSnapshot = await docRef.get(); - - await docRef.update({ test: testId }); - - // Refresh snapshot - dataSnapshot = await docRef.get(); - - loggedContext = await retry(() => - admin - .firestore() - .collection("firestoreOnDocumentUpdatedTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should have well-formed resource", () => { - expect(loggedContext?.source).toMatch( - `//firestore.googleapis.com/projects/${projectId}/databases/(default)` - ); - }); - - it("should have the correct type", () => { - expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.updated"); - }); - - it("should have an id", () => { - expect(loggedContext?.id).toBeDefined(); - }); - - it("should have a time", () => { - expect(loggedContext?.time).toBeDefined(); - }); - - it("should have the correct data", () => { - expect(dataSnapshot.data()).toStrictEqual({ test: testId }); - }); - }); - - describe("Document written trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - let dataSnapshot: admin.firestore.DocumentSnapshot; - let docRef: admin.firestore.DocumentReference; - - beforeAll(async () => { - docRef = admin.firestore().collection("tests").doc(testId); - await docRef.set({ test: testId }); - dataSnapshot = await docRef.get(); - - loggedContext = await retry(() => - admin - .firestore() - .collection("firestoreOnDocumentWrittenTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - it("should not have event.app", () => { - expect(loggedContext?.app).toBeUndefined(); - }); - - it("should give refs access to admin data", async () => { - const result = await docRef.set({ allowed: 1 }, { merge: true }); - expect(result).toBeTruthy(); - }); - - it("should have well-formed resource", () => { - expect(loggedContext?.source).toMatch( - `//firestore.googleapis.com/projects/${projectId}/databases/(default)` - ); - }); - - it("should have the correct type", () => { - expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.written"); - }); - - it("should have an id", () => { - expect(loggedContext?.id).toBeDefined(); - }); - - it("should have a time", () => { - expect(loggedContext?.time).toBeDefined(); - }); - - it("should have the correct data", () => { - expect(dataSnapshot.data()).toEqual({ test: testId }); - }); - }); -}); +// import * as admin from "firebase-admin"; +// import { retry } from "../utils"; +// import { initializeFirebase } from "../firebaseSetup"; + +// describe("Cloud Firestore (v2)", () => { +// const projectId = process.env.PROJECT_ID; +// const testId = process.env.TEST_RUN_ID; + +// if (!testId || !projectId) { +// throw new Error("Environment configured incorrectly."); +// } + +// beforeAll(async () => { +// await initializeFirebase(); +// }); + +// afterAll(async () => { +// await admin.firestore().collection("firestoreOnDocumentCreatedTests").doc(testId).delete(); +// await admin.firestore().collection("firestoreOnDocumentDeletedTests").doc(testId).delete(); +// await admin.firestore().collection("firestoreOnDocumentUpdatedTests").doc(testId).delete(); +// await admin.firestore().collection("firestoreOnDocumentWrittenTests").doc(testId).delete(); +// }); + +// describe("Document created trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; +// let dataSnapshot: admin.firestore.DocumentSnapshot; +// let docRef: admin.firestore.DocumentReference; + +// beforeAll(async () => { +// docRef = admin.firestore().collection("tests").doc(testId); +// await docRef.set({ test: testId }); +// dataSnapshot = await docRef.get(); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("firestoreOnDocumentCreatedTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// it("should not have event.app", () => { +// expect(loggedContext?.app).toBeUndefined(); +// }); + +// it("should give refs access to admin data", async () => { +// const result = await docRef.set({ allowed: 1 }, { merge: true }); +// expect(result).toBeTruthy(); +// }); + +// it("should have well-formed resource", () => { +// expect(loggedContext?.source).toMatch( +// `//firestore.googleapis.com/projects/${projectId}/databases/(default)` +// ); +// }); + +// it("should have the correct type", () => { +// expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.created"); +// }); + +// it("should have an id", () => { +// expect(loggedContext?.id).toBeDefined(); +// }); + +// it("should have a time", () => { +// expect(loggedContext?.time).toBeDefined(); +// }); + +// it("should have the correct data", () => { +// expect(dataSnapshot.data()).toEqual({ test: testId }); +// }); +// }); + +// describe("Document deleted trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; +// let dataSnapshot: admin.firestore.DocumentSnapshot; +// let docRef: admin.firestore.DocumentReference; + +// beforeAll(async () => { +// docRef = admin.firestore().collection("tests").doc(testId); +// await docRef.set({ test: testId }); +// dataSnapshot = await docRef.get(); + +// await docRef.delete(); + +// // Refresh snapshot +// dataSnapshot = await docRef.get(); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("firestoreOnDocumentDeletedTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// it("should not have event.app", () => { +// expect(loggedContext?.app).toBeUndefined(); +// }); + +// it("should have well-formed source", () => { +// expect(loggedContext?.source).toMatch( +// `//firestore.googleapis.com/projects/${projectId}/databases/(default)` +// ); +// }); + +// it("should have the correct type", () => { +// expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.deleted"); +// }); + +// it("should have an id", () => { +// expect(loggedContext?.id).toBeDefined(); +// }); + +// it("should have a time", () => { +// expect(loggedContext?.time).toBeDefined(); +// }); + +// it("should not have the data", () => { +// expect(dataSnapshot.data()).toBeUndefined(); +// }); +// }); + +// describe("Document updated trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; +// let dataSnapshot: admin.firestore.DocumentSnapshot; +// let docRef: admin.firestore.DocumentReference; + +// beforeAll(async () => { +// docRef = admin.firestore().collection("tests").doc(testId); +// await docRef.set({}); +// dataSnapshot = await docRef.get(); + +// await docRef.update({ test: testId }); + +// // Refresh snapshot +// dataSnapshot = await docRef.get(); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("firestoreOnDocumentUpdatedTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// it("should not have event.app", () => { +// expect(loggedContext?.app).toBeUndefined(); +// }); + +// it("should have well-formed resource", () => { +// expect(loggedContext?.source).toMatch( +// `//firestore.googleapis.com/projects/${projectId}/databases/(default)` +// ); +// }); + +// it("should have the correct type", () => { +// expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.updated"); +// }); + +// it("should have an id", () => { +// expect(loggedContext?.id).toBeDefined(); +// }); + +// it("should have a time", () => { +// expect(loggedContext?.time).toBeDefined(); +// }); + +// it("should have the correct data", () => { +// expect(dataSnapshot.data()).toStrictEqual({ test: testId }); +// }); +// }); + +// describe("Document written trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; +// let dataSnapshot: admin.firestore.DocumentSnapshot; +// let docRef: admin.firestore.DocumentReference; + +// beforeAll(async () => { +// docRef = admin.firestore().collection("tests").doc(testId); +// await docRef.set({ test: testId }); +// dataSnapshot = await docRef.get(); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("firestoreOnDocumentWrittenTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// it("should not have event.app", () => { +// expect(loggedContext?.app).toBeUndefined(); +// }); + +// it("should give refs access to admin data", async () => { +// const result = await docRef.set({ allowed: 1 }, { merge: true }); +// expect(result).toBeTruthy(); +// }); + +// it("should have well-formed resource", () => { +// expect(loggedContext?.source).toMatch( +// `//firestore.googleapis.com/projects/${projectId}/databases/(default)` +// ); +// }); + +// it("should have the correct type", () => { +// expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.written"); +// }); + +// it("should have an id", () => { +// expect(loggedContext?.id).toBeDefined(); +// }); + +// it("should have a time", () => { +// expect(loggedContext?.time).toBeDefined(); +// }); + +// it("should have the correct data", () => { +// expect(dataSnapshot.data()).toEqual({ test: testId }); +// }); +// }); +// }); diff --git a/integration_test/tests/v2/identity.test.ts b/integration_test/tests/v2/identity.test.ts index 86edbd879..a5b489b66 100644 --- a/integration_test/tests/v2/identity.test.ts +++ b/integration_test/tests/v2/identity.test.ts @@ -1,130 +1,130 @@ -import * as admin from "firebase-admin"; -import { retry } from "../utils"; -import { initializeApp } from "firebase/app"; -import { initializeFirebase } from "../firebaseSetup"; -import { getAuth, createUserWithEmailAndPassword, UserCredential } from "firebase/auth"; - -describe("Firebase Identity (v2)", () => { - const userIds: string[] = []; - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; - const config = { - apiKey: process.env.FIREBASE_API_KEY, - authDomain: process.env.FIREBASE_AUTH_DOMAIN, - databaseURL: process.env.DATABASE_URL, - projectId, - storageBucket: process.env.STORAGE_BUCKET, - appId: process.env.FIREBASE_APP_ID, - measurementId: process.env.FIREBASE_MEASUREMENT_ID, - }; - const app = initializeApp(config); - - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } - - beforeAll(async () => { - await initializeFirebase(); - }); - - afterAll(async () => { - for (const userId in userIds) { - await admin.firestore().collection("userProfiles").doc(userId).delete(); - await admin.firestore().collection("authUserOnCreateTests").doc(userId).delete(); - await admin.firestore().collection("authUserOnDeleteTests").doc(userId).delete(); - await admin.firestore().collection("authBeforeCreateTests").doc(userId).delete(); - await admin.firestore().collection("authBeforeSignInTests").doc(userId).delete(); - } - }); - describe("beforeUserCreated trigger", () => { - let userRecord: UserCredential; - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - userRecord = await createUserWithEmailAndPassword( - getAuth(app), - `${testId}@fake-create.com`, - "secret" - ); - - userIds.push(userRecord.user.uid); - - loggedContext = await retry(() => - admin - .firestore() - .collection("identityBeforeUserCreatedTests") - .doc(userRecord.user.uid) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - afterAll(async () => { - await admin.auth().deleteUser(userRecord.user.uid); - }); - - it("should have a project as resource", () => { - expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); - }); - - it("should have the correct eventType", () => { - expect(loggedContext?.eventType).toEqual( - "providers/cloud.auth/eventTypes/user.beforeCreate:password" - ); - }); - - it("should have an eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have a timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - }); - - describe("identityBeforeUserSignedInTests trigger", () => { - let userRecord: UserCredential; - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - userRecord = await createUserWithEmailAndPassword( - getAuth(app), - `${testId}@fake-before-signin.com`, - "secret" - ); - - userIds.push(userRecord.user.uid); - - loggedContext = await retry(() => - admin - .firestore() - .collection("identityBeforeUserSignedInTests") - .doc(userRecord.user.uid) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - afterAll(async () => { - await admin.auth().deleteUser(userRecord.user.uid); - }); - - it("should have a project as resource", () => { - expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); - }); - - it("should have the correct eventType", () => { - expect(loggedContext?.eventType).toEqual( - "providers/cloud.auth/eventTypes/user.beforeSignIn:password" - ); - }); - - it("should have an eventId", () => { - expect(loggedContext?.eventId).toBeDefined(); - }); - - it("should have a timestamp", () => { - expect(loggedContext?.timestamp).toBeDefined(); - }); - }); -}); +// import * as admin from "firebase-admin"; +// import { retry } from "../utils"; +// import { initializeApp } from "firebase/app"; +// import { initializeFirebase } from "../firebaseSetup"; +// import { getAuth, createUserWithEmailAndPassword, UserCredential } from "firebase/auth"; + +// describe("Firebase Identity (v2)", () => { +// const userIds: string[] = []; +// const projectId = process.env.PROJECT_ID; +// const testId = process.env.TEST_RUN_ID; +// const config = { +// apiKey: process.env.FIREBASE_API_KEY, +// authDomain: process.env.FIREBASE_AUTH_DOMAIN, +// databaseURL: process.env.DATABASE_URL, +// projectId, +// storageBucket: process.env.STORAGE_BUCKET, +// appId: process.env.FIREBASE_APP_ID, +// measurementId: process.env.FIREBASE_MEASUREMENT_ID, +// }; +// const app = initializeApp(config); + +// if (!testId || !projectId) { +// throw new Error("Environment configured incorrectly."); +// } + +// beforeAll(async () => { +// await initializeFirebase(); +// }); + +// afterAll(async () => { +// for (const userId in userIds) { +// await admin.firestore().collection("userProfiles").doc(userId).delete(); +// await admin.firestore().collection("authUserOnCreateTests").doc(userId).delete(); +// await admin.firestore().collection("authUserOnDeleteTests").doc(userId).delete(); +// await admin.firestore().collection("authBeforeCreateTests").doc(userId).delete(); +// await admin.firestore().collection("authBeforeSignInTests").doc(userId).delete(); +// } +// }); +// describe("beforeUserCreated trigger", () => { +// let userRecord: UserCredential; +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// userRecord = await createUserWithEmailAndPassword( +// getAuth(app), +// `${testId}@fake-create.com`, +// "secret" +// ); + +// userIds.push(userRecord.user.uid); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("identityBeforeUserCreatedTests") +// .doc(userRecord.user.uid) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// afterAll(async () => { +// await admin.auth().deleteUser(userRecord.user.uid); +// }); + +// it("should have a project as resource", () => { +// expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); +// }); + +// it("should have the correct eventType", () => { +// expect(loggedContext?.eventType).toEqual( +// "providers/cloud.auth/eventTypes/user.beforeCreate:password" +// ); +// }); + +// it("should have an eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have a timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); +// }); + +// describe("identityBeforeUserSignedInTests trigger", () => { +// let userRecord: UserCredential; +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// userRecord = await createUserWithEmailAndPassword( +// getAuth(app), +// `${testId}@fake-before-signin.com`, +// "secret" +// ); + +// userIds.push(userRecord.user.uid); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("identityBeforeUserSignedInTests") +// .doc(userRecord.user.uid) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// afterAll(async () => { +// await admin.auth().deleteUser(userRecord.user.uid); +// }); + +// it("should have a project as resource", () => { +// expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); +// }); + +// it("should have the correct eventType", () => { +// expect(loggedContext?.eventType).toEqual( +// "providers/cloud.auth/eventTypes/user.beforeSignIn:password" +// ); +// }); + +// it("should have an eventId", () => { +// expect(loggedContext?.eventId).toBeDefined(); +// }); + +// it("should have a timestamp", () => { +// expect(loggedContext?.timestamp).toBeDefined(); +// }); +// }); +// }); diff --git a/integration_test/tests/v2/pubsub.test.ts b/integration_test/tests/v2/pubsub.test.ts index 6cba45cd1..d08e3b908 100644 --- a/integration_test/tests/v2/pubsub.test.ts +++ b/integration_test/tests/v2/pubsub.test.ts @@ -1,71 +1,71 @@ -import * as admin from "firebase-admin"; -import { retry, timeout } from "../utils"; -import { PubSub } from "@google-cloud/pubsub"; -import { initializeFirebase } from "../firebaseSetup"; +// import * as admin from "firebase-admin"; +// import { retry, timeout } from "../utils"; +// import { PubSub } from "@google-cloud/pubsub"; +// import { initializeFirebase } from "../firebaseSetup"; -describe("Pub/Sub (v2)", () => { - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; - const region = process.env.REGION; - const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; +// describe("Pub/Sub (v2)", () => { +// const projectId = process.env.PROJECT_ID; +// const testId = process.env.TEST_RUN_ID; +// const region = process.env.REGION; +// const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; - if (!testId || !projectId || !region || !serviceAccountPath) { - throw new Error("Environment configured incorrectly."); - } +// if (!testId || !projectId || !region || !serviceAccountPath) { +// throw new Error("Environment configured incorrectly."); +// } - beforeAll(async () => { - await initializeFirebase(); - }); +// beforeAll(async () => { +// await initializeFirebase(); +// }); - afterAll(async () => { - await admin.firestore().collection("pubsubOnMessagePublishedTests").doc(testId).delete(); - }); +// afterAll(async () => { +// await admin.firestore().collection("pubsubOnMessagePublishedTests").doc(testId).delete(); +// }); - describe("onMessagePublished trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; +// describe("onMessagePublished trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; - beforeAll(async () => { - const serviceAccount = await import(serviceAccountPath); - const topic = new PubSub({ - credentials: serviceAccount.default, - projectId, - }).topic("custom_message_tests"); +// beforeAll(async () => { +// const serviceAccount = await import(serviceAccountPath); +// const topic = new PubSub({ +// credentials: serviceAccount.default, +// projectId, +// }).topic("custom_message_tests"); - await topic.publish(Buffer.from(JSON.stringify({ testId }))); +// await topic.publish(Buffer.from(JSON.stringify({ testId }))); - loggedContext = await retry(() => - admin - .firestore() - .collection("pubsubOnMessagePublishedTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("pubsubOnMessagePublishedTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); - it("should have a topic as source", () => { - expect(loggedContext?.source).toEqual( - `//pubsub.googleapis.com/projects/${projectId}/topics/custom_message_tests` - ); - }); +// it("should have a topic as source", () => { +// expect(loggedContext?.source).toEqual( +// `//pubsub.googleapis.com/projects/${projectId}/topics/custom_message_tests` +// ); +// }); - it("should have the correct event type", () => { - expect(loggedContext?.type).toEqual("google.cloud.pubsub.topic.v1.messagePublished"); - }); +// it("should have the correct event type", () => { +// expect(loggedContext?.type).toEqual("google.cloud.pubsub.topic.v1.messagePublished"); +// }); - it("should have an event id", () => { - expect(loggedContext?.id).toBeDefined(); - }); +// it("should have an event id", () => { +// expect(loggedContext?.id).toBeDefined(); +// }); - it("should have time", () => { - expect(loggedContext?.time).toBeDefined(); - }); +// it("should have time", () => { +// expect(loggedContext?.time).toBeDefined(); +// }); - it("should have pubsub data", () => { - const decodedMessage = JSON.parse(loggedContext?.message); - const decoded = new Buffer(decodedMessage.data, "base64").toString(); - const parsed = JSON.parse(decoded); - expect(parsed.testId).toEqual(testId); - }); - }); -}); +// it("should have pubsub data", () => { +// const decodedMessage = JSON.parse(loggedContext?.message); +// const decoded = new Buffer(decodedMessage.data, "base64").toString(); +// const parsed = JSON.parse(decoded); +// expect(parsed.testId).toEqual(testId); +// }); +// }); +// }); diff --git a/integration_test/tests/v2/remoteConfig.test.ts b/integration_test/tests/v2/remoteConfig.test.ts index 4d17e3573..1679dfd36 100644 --- a/integration_test/tests/v2/remoteConfig.test.ts +++ b/integration_test/tests/v2/remoteConfig.test.ts @@ -1,67 +1,67 @@ -import * as admin from "firebase-admin"; -import { retry } from "../utils"; -import { initializeFirebase } from "../firebaseSetup"; -import fetch from "node-fetch"; +// import * as admin from "firebase-admin"; +// import { retry } from "../utils"; +// import { initializeFirebase } from "../firebaseSetup"; +// import fetch from "node-fetch"; -describe("Firebase Remote Config (v2)", () => { - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; +// describe("Firebase Remote Config (v2)", () => { +// const projectId = process.env.PROJECT_ID; +// const testId = process.env.TEST_RUN_ID; - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } +// if (!testId || !projectId) { +// throw new Error("Environment configured incorrectly."); +// } - beforeAll(async () => { - await initializeFirebase(); - }); +// beforeAll(async () => { +// await initializeFirebase(); +// }); - afterAll(async () => { - await admin.firestore().collection("remoteConfigOnConfigUpdatedTests").doc(testId).delete(); - }); +// afterAll(async () => { +// await admin.firestore().collection("remoteConfigOnConfigUpdatedTests").doc(testId).delete(); +// }); - describe("onUpdated trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; +// describe("onUpdated trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; - beforeAll(async () => { - const accessToken = await admin.credential.applicationDefault().getAccessToken(); - const resp = await fetch( - `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/remoteConfig`, - { - method: "PUT", - headers: { - Authorization: `Bearer ${accessToken.access_token}`, - "Content-Type": "application/json; UTF-8", - "Accept-Encoding": "gzip", - "If-Match": "*", - }, - body: JSON.stringify({ version: { description: testId } }), - } - ); - if (!resp.ok) { - throw new Error(resp.statusText); - } +// beforeAll(async () => { +// const accessToken = await admin.credential.applicationDefault().getAccessToken(); +// const resp = await fetch( +// `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/remoteConfig`, +// { +// method: "PUT", +// headers: { +// Authorization: `Bearer ${accessToken.access_token}`, +// "Content-Type": "application/json; UTF-8", +// "Accept-Encoding": "gzip", +// "If-Match": "*", +// }, +// body: JSON.stringify({ version: { description: testId } }), +// } +// ); +// if (!resp.ok) { +// throw new Error(resp.statusText); +// } - loggedContext = await retry(() => - admin - .firestore() - .collection("remoteConfigOnConfigUpdatedTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("remoteConfigOnConfigUpdatedTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); - it("should have the right event type", () => { - // TODO: not sure if the nested remoteconfig.remoteconfig is expected? - expect(loggedContext?.type).toEqual("google.firebase.remoteconfig.remoteConfig.v1.updated"); - }); +// it("should have the right event type", () => { +// // TODO: not sure if the nested remoteconfig.remoteconfig is expected? +// expect(loggedContext?.type).toEqual("google.firebase.remoteconfig.remoteConfig.v1.updated"); +// }); - it("should have event id", () => { - expect(loggedContext?.id).toBeDefined(); - }); +// it("should have event id", () => { +// expect(loggedContext?.id).toBeDefined(); +// }); - it("should have time", () => { - expect(loggedContext?.time).toBeDefined(); - }); - }); -}); +// it("should have time", () => { +// expect(loggedContext?.time).toBeDefined(); +// }); +// }); +// }); diff --git a/integration_test/tests/v2/scheduler.test.ts b/integration_test/tests/v2/scheduler.test.ts index 0e81c3003..561db0236 100644 --- a/integration_test/tests/v2/scheduler.test.ts +++ b/integration_test/tests/v2/scheduler.test.ts @@ -1,56 +1,56 @@ -import * as admin from "firebase-admin"; -import { retry } from "../utils"; -import { initializeFirebase } from "../firebaseSetup"; - -describe("Scheduler", () => { - const projectId = process.env.PROJECT_ID; - const region = process.env.REGION; - const testId = process.env.TEST_RUN_ID; - - if (!testId || !projectId || !region) { - throw new Error("Environment configured incorrectly."); - } - - beforeAll(async () => { - await initializeFirebase(); - }); - - afterAll(async () => { - await admin.firestore().collection("schedulerOnScheduleV2Tests").doc(testId).delete(); - }); - - describe("onSchedule trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - const accessToken = await admin.credential.applicationDefault().getAccessToken(); - const jobName = `firebase-schedule-${testId}-v2-schedule-${region}`; - const response = await fetch( - `https://cloudscheduler.googleapis.com/v1/projects/${projectId}/locations/us-central1/jobs/firebase-schedule-${testId}-v2-schedule-${region}:run`, - { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${accessToken.access_token}`, - }, - } - ); - if (!response.ok) { - throw new Error(`Failed request with status ${response.status}!`); - } - - loggedContext = await retry(() => - admin - .firestore() - .collection("schedulerOnScheduleV2Tests") - .doc(jobName) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - it("should trigger when the scheduler fires", () => { - expect(loggedContext?.success).toBeTruthy(); - }); - }); -}); +// import * as admin from "firebase-admin"; +// import { retry } from "../utils"; +// import { initializeFirebase } from "../firebaseSetup"; + +// describe("Scheduler", () => { +// const projectId = process.env.PROJECT_ID; +// const region = process.env.REGION; +// const testId = process.env.TEST_RUN_ID; + +// if (!testId || !projectId || !region) { +// throw new Error("Environment configured incorrectly."); +// } + +// beforeAll(async () => { +// await initializeFirebase(); +// }); + +// afterAll(async () => { +// await admin.firestore().collection("schedulerOnScheduleV2Tests").doc(testId).delete(); +// }); + +// describe("onSchedule trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// const accessToken = await admin.credential.applicationDefault().getAccessToken(); +// const jobName = `firebase-schedule-${testId}-v2-schedule-${region}`; +// const response = await fetch( +// `https://cloudscheduler.googleapis.com/v1/projects/${projectId}/locations/us-central1/jobs/firebase-schedule-${testId}-v2-schedule-${region}:run`, +// { +// method: "POST", +// headers: { +// "Content-Type": "application/json", +// Authorization: `Bearer ${accessToken.access_token}`, +// }, +// } +// ); +// if (!response.ok) { +// throw new Error(`Failed request with status ${response.status}!`); +// } + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("schedulerOnScheduleV2Tests") +// .doc(jobName) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// it("should trigger when the scheduler fires", () => { +// expect(loggedContext?.success).toBeTruthy(); +// }); +// }); +// }); diff --git a/integration_test/tests/v2/storage.test.ts b/integration_test/tests/v2/storage.test.ts index 341b6ea7d..6961ab3cb 100644 --- a/integration_test/tests/v2/storage.test.ts +++ b/integration_test/tests/v2/storage.test.ts @@ -1,167 +1,167 @@ -import * as admin from "firebase-admin"; -import { initializeFirebase } from "../firebaseSetup"; -import { retry, timeout } from "../utils"; - -async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { - const bucket = admin.storage().bucket(); - - const file = bucket.file(fileName); - await file.save(buffer, { - metadata: { - contentType: "text/plain", - }, - }); -} - -describe("Firebase Storage (v2)", () => { - const testId = process.env.TEST_RUN_ID; - - if (!testId) { - throw new Error("Environment configured incorrectly."); - } - - beforeAll(async () => { - await initializeFirebase(); - }); - - afterAll(async () => { - await admin.firestore().collection("storageOnObjectFinalizedTests").doc(testId).delete(); - await admin.firestore().collection("storageOnObjectDeletedTests").doc(testId).delete(); - await admin.firestore().collection("storageOnObjectMetadataUpdatedTests").doc(testId).delete(); - }); - - describe("onObjectFinalized trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - const testContent = testId; - const buffer = Buffer.from(testContent, "utf-8"); - - await uploadBufferToFirebase(buffer, testId + ".txt"); - - loggedContext = await retry(() => - admin - .firestore() - .collection("storageOnObjectFinalizedTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - afterAll(async () => { - const file = admin - .storage() - .bucket() - .file(testId + ".txt"); - - const [exists] = await file.exists(); - if (exists) { - await file.delete(); - } - }); - - it("should have the right event type", () => { - expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.finalized"); - }); - - it("should have event id", () => { - expect(loggedContext?.id).toBeDefined(); - }); - - it("should have time", () => { - expect(loggedContext?.time).toBeDefined(); - }); - }); - - describe("onDeleted trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - const testContent = testId; - const buffer = Buffer.from(testContent, "utf-8"); - - await uploadBufferToFirebase(buffer, testId + ".txt"); - - await timeout(5000); // Short delay before delete - - const file = admin - .storage() - .bucket() - .file(testId + ".txt"); - await file.delete(); - - loggedContext = await retry(() => - admin - .firestore() - .collection("storageOnObjectDeletedTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - it("should have the right event type", () => { - expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.deleted"); - }); - - it("should have event id", () => { - expect(loggedContext?.id).toBeDefined(); - }); - - it("should have time", () => { - expect(loggedContext?.time).toBeDefined(); - }); - }); - - describe("onMetadataUpdated trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - const testContent = testId; - const buffer = Buffer.from(testContent, "utf-8"); - - await uploadBufferToFirebase(buffer, testId + ".txt"); - - // Trigger metadata update - const file = admin - .storage() - .bucket() - .file(testId + ".txt"); - await file.setMetadata({ contentType: "application/json" }); - - loggedContext = await retry(() => - admin - .firestore() - .collection("storageOnObjectMetadataUpdatedTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - afterAll(async () => { - const file = admin - .storage() - .bucket() - .file(testId + ".txt"); - - const [exists] = await file.exists(); - if (exists) { - await file.delete(); - } - }); - - it("should have the right event type", () => { - expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.metadataUpdated"); - }); - - it("should have event id", () => { - expect(loggedContext?.id).toBeDefined(); - }); - - it("should have time", () => { - expect(loggedContext?.time).toBeDefined(); - }); - }); -}); +// import * as admin from "firebase-admin"; +// import { initializeFirebase } from "../firebaseSetup"; +// import { retry, timeout } from "../utils"; + +// async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { +// const bucket = admin.storage().bucket(); + +// const file = bucket.file(fileName); +// await file.save(buffer, { +// metadata: { +// contentType: "text/plain", +// }, +// }); +// } + +// describe("Firebase Storage (v2)", () => { +// const testId = process.env.TEST_RUN_ID; + +// if (!testId) { +// throw new Error("Environment configured incorrectly."); +// } + +// beforeAll(async () => { +// await initializeFirebase(); +// }); + +// afterAll(async () => { +// await admin.firestore().collection("storageOnObjectFinalizedTests").doc(testId).delete(); +// await admin.firestore().collection("storageOnObjectDeletedTests").doc(testId).delete(); +// await admin.firestore().collection("storageOnObjectMetadataUpdatedTests").doc(testId).delete(); +// }); + +// describe("onObjectFinalized trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// const testContent = testId; +// const buffer = Buffer.from(testContent, "utf-8"); + +// await uploadBufferToFirebase(buffer, testId + ".txt"); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("storageOnObjectFinalizedTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// afterAll(async () => { +// const file = admin +// .storage() +// .bucket() +// .file(testId + ".txt"); + +// const [exists] = await file.exists(); +// if (exists) { +// await file.delete(); +// } +// }); + +// it("should have the right event type", () => { +// expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.finalized"); +// }); + +// it("should have event id", () => { +// expect(loggedContext?.id).toBeDefined(); +// }); + +// it("should have time", () => { +// expect(loggedContext?.time).toBeDefined(); +// }); +// }); + +// describe("onDeleted trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// const testContent = testId; +// const buffer = Buffer.from(testContent, "utf-8"); + +// await uploadBufferToFirebase(buffer, testId + ".txt"); + +// await timeout(5000); // Short delay before delete + +// const file = admin +// .storage() +// .bucket() +// .file(testId + ".txt"); +// await file.delete(); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("storageOnObjectDeletedTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// it("should have the right event type", () => { +// expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.deleted"); +// }); + +// it("should have event id", () => { +// expect(loggedContext?.id).toBeDefined(); +// }); + +// it("should have time", () => { +// expect(loggedContext?.time).toBeDefined(); +// }); +// }); + +// describe("onMetadataUpdated trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// const testContent = testId; +// const buffer = Buffer.from(testContent, "utf-8"); + +// await uploadBufferToFirebase(buffer, testId + ".txt"); + +// // Trigger metadata update +// const file = admin +// .storage() +// .bucket() +// .file(testId + ".txt"); +// await file.setMetadata({ contentType: "application/json" }); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("storageOnObjectMetadataUpdatedTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// afterAll(async () => { +// const file = admin +// .storage() +// .bucket() +// .file(testId + ".txt"); + +// const [exists] = await file.exists(); +// if (exists) { +// await file.delete(); +// } +// }); + +// it("should have the right event type", () => { +// expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.metadataUpdated"); +// }); + +// it("should have event id", () => { +// expect(loggedContext?.id).toBeDefined(); +// }); + +// it("should have time", () => { +// expect(loggedContext?.time).toBeDefined(); +// }); +// }); +// }); diff --git a/integration_test/tests/v2/tasks.test.ts b/integration_test/tests/v2/tasks.test.ts index 8384735c8..0e0c7664c 100644 --- a/integration_test/tests/v2/tasks.test.ts +++ b/integration_test/tests/v2/tasks.test.ts @@ -1,44 +1,44 @@ -import * as admin from "firebase-admin"; -import { initializeFirebase } from "../firebaseSetup"; -import { createTask, retry } from "../utils"; - -describe("Cloud Tasks (v2)", () => { - const region = process.env.REGION; - const testId = process.env.TEST_RUN_ID; - const projectId = process.env.PROJECT_ID; - const queueName = `${testId}-v2-tasksOnTaskDispatchedTests`; - - if (!testId || !projectId || !region) { - throw new Error("Environment configured incorrectly."); - } - - beforeAll(async () => { - await initializeFirebase(); - }); - - afterAll(async () => { - await admin.firestore().collection("tasksOnTaskDispatchedTests").doc(testId).delete(); - }); - - describe("onDispatch trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - const url = `https://${region}-${projectId}.cloudfunctions.net/${testId}-v2-tasksOnTaskDispatchedTests`; - await createTask(projectId, queueName, region, url, { data: { testId } }); - - loggedContext = await retry(() => - admin - .firestore() - .collection("tasksOnTaskDispatchedTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - it("should have correct event id", () => { - expect(loggedContext?.id).toBeDefined(); - }); - }); -}); +// import * as admin from "firebase-admin"; +// import { initializeFirebase } from "../firebaseSetup"; +// import { createTask, retry } from "../utils"; + +// describe("Cloud Tasks (v2)", () => { +// const region = process.env.REGION; +// const testId = process.env.TEST_RUN_ID; +// const projectId = process.env.PROJECT_ID; +// const queueName = `${testId}-v2-tasksOnTaskDispatchedTests`; + +// if (!testId || !projectId || !region) { +// throw new Error("Environment configured incorrectly."); +// } + +// beforeAll(async () => { +// await initializeFirebase(); +// }); + +// afterAll(async () => { +// await admin.firestore().collection("tasksOnTaskDispatchedTests").doc(testId).delete(); +// }); + +// describe("onDispatch trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// const url = `https://${region}-${projectId}.cloudfunctions.net/${testId}-v2-tasksOnTaskDispatchedTests`; +// await createTask(projectId, queueName, region, url, { data: { testId } }); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("tasksOnTaskDispatchedTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// it("should have correct event id", () => { +// expect(loggedContext?.id).toBeDefined(); +// }); +// }); +// }); diff --git a/integration_test/tests/v2/testLab.test.ts b/integration_test/tests/v2/testLab.test.ts index a2686156e..08310f7fe 100644 --- a/integration_test/tests/v2/testLab.test.ts +++ b/integration_test/tests/v2/testLab.test.ts @@ -1,50 +1,50 @@ -import * as admin from "firebase-admin"; -import { retry, startTestRun } from "../utils"; -import { initializeFirebase } from "../firebaseSetup"; - -describe("TestLab (v2)", () => { - const projectId = process.env.PROJECT_ID; - const testId = process.env.TEST_RUN_ID; - - if (!testId || !projectId) { - throw new Error("Environment configured incorrectly."); - } - - beforeAll(async () => { - await initializeFirebase(); - }); - - afterAll(async () => { - await admin.firestore().collection("testLabOnTestMatrixCompletedTests").doc(testId).delete(); - }); - - describe("test matrix onComplete trigger", () => { - let loggedContext: admin.firestore.DocumentData | undefined; - - beforeAll(async () => { - const accessToken = await admin.credential.applicationDefault().getAccessToken(); - await startTestRun(projectId, testId, accessToken.access_token); - - loggedContext = await retry(() => - admin - .firestore() - .collection("testLabOnTestMatrixCompletedTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()) - ); - }); - - it("should have event id", () => { - expect(loggedContext?.id).toBeDefined(); - }); - - it("should have right event type", () => { - expect(loggedContext?.type).toEqual("google.firebase.testlab.testMatrix.v1.completed"); - }); - - it("should be in state 'INVALID'", () => { - expect(loggedContext?.state).toEqual("INVALID"); - }); - }); -}); +// import * as admin from "firebase-admin"; +// import { retry, startTestRun } from "../utils"; +// import { initializeFirebase } from "../firebaseSetup"; + +// describe("TestLab (v2)", () => { +// const projectId = process.env.PROJECT_ID; +// const testId = process.env.TEST_RUN_ID; + +// if (!testId || !projectId) { +// throw new Error("Environment configured incorrectly."); +// } + +// beforeAll(async () => { +// await initializeFirebase(); +// }); + +// afterAll(async () => { +// await admin.firestore().collection("testLabOnTestMatrixCompletedTests").doc(testId).delete(); +// }); + +// describe("test matrix onComplete trigger", () => { +// let loggedContext: admin.firestore.DocumentData | undefined; + +// beforeAll(async () => { +// const accessToken = await admin.credential.applicationDefault().getAccessToken(); +// await startTestRun(projectId, testId, accessToken.access_token); + +// loggedContext = await retry(() => +// admin +// .firestore() +// .collection("testLabOnTestMatrixCompletedTests") +// .doc(testId) +// .get() +// .then((logSnapshot) => logSnapshot.data()) +// ); +// }); + +// it("should have event id", () => { +// expect(loggedContext?.id).toBeDefined(); +// }); + +// it("should have right event type", () => { +// expect(loggedContext?.type).toEqual("google.firebase.testlab.testMatrix.v1.completed"); +// }); + +// it("should be in state 'INVALID'", () => { +// expect(loggedContext?.state).toEqual("INVALID"); +// }); +// }); +// }); From 4f7411ac0aa7662255c91d28a0a521207d897d99 Mon Sep 17 00:00:00 2001 From: HassanBahati Date: Tue, 19 Aug 2025 00:48:03 +0300 Subject: [PATCH 19/25] test: add database tests --- .../functions/src/v2/database-tests.ts | 144 ++++++------ integration_test/tests/v2/database.test.ts | 220 +++++++++--------- 2 files changed, 182 insertions(+), 182 deletions(-) diff --git a/integration_test/functions/src/v2/database-tests.ts b/integration_test/functions/src/v2/database-tests.ts index 357359e63..96c214f34 100644 --- a/integration_test/functions/src/v2/database-tests.ts +++ b/integration_test/functions/src/v2/database-tests.ts @@ -32,77 +32,77 @@ export const databaseCreatedTests = onValueCreated( } ); -// export const databaseDeletedTests = onValueDeleted( -// { -// ref: "databaseDeletedTests/{testId}/start", -// region: REGION, -// }, -// async (event) => { -// const testId = event.params.testId; -// await admin -// .firestore() -// .collection("databaseDeletedTests") -// .doc(testId) -// .set( -// sanitizeData({ -// testId, -// type: event.type, -// id: event.id, -// time: event.time, -// url: event.ref.toString(), -// }) -// ); -// } -// ); +export const databaseDeletedTests = onValueDeleted( + { + ref: "databaseDeletedTests/{testId}/start", + region: REGION, + }, + async (event) => { + const testId = event.params.testId; + await admin + .firestore() + .collection("databaseDeletedTests") + .doc(testId) + .set( + sanitizeData({ + testId, + type: event.type, + id: event.id, + time: event.time, + url: event.ref.toString(), + }) + ); + } +); -// export const databaseUpdatedTests = onValueUpdated( -// { -// ref: "databaseUpdatedTests/{testId}/start", -// region: REGION, -// }, -// async (event) => { -// const testId = event.params.testId; -// const data = event.data.after.val(); -// await admin -// .firestore() -// .collection("databaseUpdatedTests") -// .doc(testId) -// .set( -// sanitizeData({ -// testId, -// url: event.ref.toString(), -// type: event.type, -// id: event.id, -// time: event.time, -// data: JSON.stringify(data ?? {}), -// }) -// ); -// } -// ); +export const databaseUpdatedTests = onValueUpdated( + { + ref: "databaseUpdatedTests/{testId}/start", + region: REGION, + }, + async (event) => { + const testId = event.params.testId; + const data = event.data.after.val(); + await admin + .firestore() + .collection("databaseUpdatedTests") + .doc(testId) + .set( + sanitizeData({ + testId, + url: event.ref.toString(), + type: event.type, + id: event.id, + time: event.time, + data: JSON.stringify(data ?? {}), + }) + ); + } +); -// export const databaseWrittenTests = onValueWritten( -// { -// ref: "databaseWrittenTests/{testId}/start", -// region: REGION, -// }, -// async (event) => { -// const testId = event.params.testId; -// if (!event.data.after.exists()) { -// functions.logger.info(`Event for ${testId} is null; presuming data cleanup, so skipping.`); -// return; -// } -// await admin -// .firestore() -// .collection("databaseWrittenTests") -// .doc(testId) -// .set( -// sanitizeData({ -// testId, -// type: event.type, -// id: event.id, -// time: event.time, -// url: event.ref.toString(), -// }) -// ); -// } -// ); +export const databaseWrittenTests = onValueWritten( + { + ref: "databaseWrittenTests/{testId}/start", + region: REGION, + }, + async (event) => { + const testId = event.params.testId; + if (!event.data.after.exists()) { + functions.logger.info(`Event for ${testId} is null; presuming data cleanup, so skipping.`); + return; + } + await admin + .firestore() + .collection("databaseWrittenTests") + .doc(testId) + .set( + sanitizeData({ + testId, + type: event.type, + id: event.id, + time: event.time, + url: event.ref.toString(), + }) + ); + } +); diff --git a/integration_test/tests/v2/database.test.ts b/integration_test/tests/v2/database.test.ts index 7cb17bf58..96e723d4b 100644 --- a/integration_test/tests/v2/database.test.ts +++ b/integration_test/tests/v2/database.test.ts @@ -101,114 +101,114 @@ describe("Firebase Database (v2)", () => { }); }); - // describe("deleted trigger", () => { - // let ref: Reference; - // let loggedContext: admin.firestore.DocumentData | undefined; - - // beforeAll(async () => { - // ref = await setupRef(`databaseDeletedTests/${testId}/start`); - // await teardownRef(ref); - // loggedContext = await getLoggedContext("databaseDeletedTests", testId); - // }); - - // it("should have a correct ref url", () => { - // expect(loggedContext?.url).toMatch(`databaseDeletedTests/${testId}/start`); - // }); - - // it("should have the right event type", () => { - // expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.deleted"); - // }); - - // it("should have event id", () => { - // expect(loggedContext?.id).toBeDefined(); - // }); - - // it("should have a time", () => { - // expect(loggedContext?.time).toBeDefined(); - // }); - // }); - - // describe("updated trigger", () => { - // let ref: Reference; - // let loggedContext: admin.firestore.DocumentData | undefined; - - // beforeAll(async () => { - // ref = await setupRef(`databaseUpdatedTests/${testId}/start`); - // await ref.update({ updated: true }); - // loggedContext = await getLoggedContext("databaseUpdatedTests", testId); - // }); - - // afterAll(async () => { - // await teardownRef(ref); - // }); - - // it("should give refs access to admin data", async () => { - // await ref.parent?.child("adminOnly").update({ allowed: 1 }); - - // const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); - // const adminData = adminDataSnapshot?.val(); - - // expect(adminData).toEqual({ allowed: 1 }); - // }); - - // it("should have a correct ref url", () => { - // expect(loggedContext?.url).toMatch(`databaseUpdatedTests/${testId}/start`); - // }); - - // it("should have the right event type", () => { - // expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.updated"); - // }); - - // it("should have event id", () => { - // expect(loggedContext?.id).toBeDefined(); - // }); - - // it("should have a time", () => { - // expect(loggedContext?.time).toBeDefined(); - // }); - - // it("should have updated data", async () => { - // const parsedData = JSON.parse(loggedContext?.data ?? {}); - // expect(parsedData).toEqual({ updated: true }); - // }); - // }); - - // describe("written trigger", () => { - // let ref: Reference; - // let loggedContext: admin.firestore.DocumentData | undefined; - - // beforeAll(async () => { - // ref = await setupRef(`databaseWrittenTests/${testId}/start`); - // loggedContext = await getLoggedContext("databaseWrittenTests", testId); - // }); - - // afterAll(async () => { - // await teardownRef(ref); - // }); - - // it("should give refs access to admin data", async () => { - // await ref.parent?.child("adminOnly").update({ allowed: 1 }); - - // const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); - // const adminData = adminDataSnapshot?.val(); - - // expect(adminData).toEqual({ allowed: 1 }); - // }); - - // it("should have a correct ref url", () => { - // expect(loggedContext?.url).toMatch(`databaseWrittenTests/${testId}/start`); - // }); - - // it("should have the right event type", () => { - // expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.written"); - // }); - - // it("should have event id", () => { - // expect(loggedContext?.id).toBeDefined(); - // }); - - // it("should have a time", () => { - // expect(loggedContext?.time).toBeDefined(); - // }); - // }); + describe("deleted trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + ref = await setupRef(`databaseDeletedTests/${testId}/start`); + await teardownRef(ref); + loggedContext = await getLoggedContext("databaseDeletedTests", testId); + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch(`databaseDeletedTests/${testId}/start`); + }); + + it("should have the right event type", () => { + expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.deleted"); + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + }); + + describe("updated trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + ref = await setupRef(`databaseUpdatedTests/${testId}/start`); + await ref.update({ updated: true }); + loggedContext = await getLoggedContext("databaseUpdatedTests", testId); + }); + + afterAll(async () => { + await teardownRef(ref); + }); + + it("should give refs access to admin data", async () => { + await ref.parent?.child("adminOnly").update({ allowed: 1 }); + + const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); + const adminData = adminDataSnapshot?.val(); + + expect(adminData).toEqual({ allowed: 1 }); + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch(`databaseUpdatedTests/${testId}/start`); + }); + + it("should have the right event type", () => { + expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.updated"); + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + + it("should have updated data", async () => { + const parsedData = JSON.parse(loggedContext?.data ?? {}); + expect(parsedData).toEqual({ updated: true }); + }); + }); + + describe("written trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + ref = await setupRef(`databaseWrittenTests/${testId}/start`); + loggedContext = await getLoggedContext("databaseWrittenTests", testId); + }); + + afterAll(async () => { + await teardownRef(ref); + }); + + it("should give refs access to admin data", async () => { + await ref.parent?.child("adminOnly").update({ allowed: 1 }); + + const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); + const adminData = adminDataSnapshot?.val(); + + expect(adminData).toEqual({ allowed: 1 }); + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch(`databaseWrittenTests/${testId}/start`); + }); + + it("should have the right event type", () => { + expect(loggedContext?.type).toEqual("google.firebase.database.ref.v1.written"); + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + }); }); From 7a30831e605ce89329680202457e41533a7b72dd Mon Sep 17 00:00:00 2001 From: HassanBahati Date: Tue, 19 Aug 2025 01:12:27 +0300 Subject: [PATCH 20/25] refactor: use logger class --- integration_test/deployment-utils.ts | 218 +++++++++++++-------------- integration_test/run.ts | 77 +++++----- 2 files changed, 148 insertions(+), 147 deletions(-) diff --git a/integration_test/deployment-utils.ts b/integration_test/deployment-utils.ts index 86ee3251b..14dc48631 100644 --- a/integration_test/deployment-utils.ts +++ b/integration_test/deployment-utils.ts @@ -1,5 +1,6 @@ import pRetry from "p-retry"; import pLimit from "p-limit"; +import { logger } from "./src/logger.js"; interface FirebaseClient { functions: { @@ -28,14 +29,14 @@ const sleep = (ms: number): Promise => new Promise((resolve) => setTimeout */ export async function getDeployedFunctions(client: FirebaseClient): Promise { try { - console.log("🔍 Attempting to list functions..."); - console.log(" Project ID:", process.env.PROJECT_ID); - console.log(" Working directory:", process.cwd()); - console.log(" Config file:", "./firebase.json"); + logger.debug("Attempting to list functions..."); + logger.debug("Project ID:", process.env.PROJECT_ID); + logger.debug("Working directory:", process.cwd()); + logger.debug("Config file:", "./firebase.json"); // Check if PROJECT_ID is set if (!process.env.PROJECT_ID) { - console.log(" ❌ PROJECT_ID environment variable is not set"); + logger.error("PROJECT_ID environment variable is not set"); return []; } @@ -47,26 +48,26 @@ export async function getDeployedFunctions(client: FirebaseClient): Promise fn.name); } catch (error) { - console.log("Could not list functions, assuming none deployed:", error); + logger.warning("Could not list functions, assuming none deployed:", error); // Provide more detailed error information if (error && typeof error === 'object' && 'message' in error) { const errorMessage = String(error.message); - console.log(" Error message:", errorMessage); - if ('status' in error) console.log(" Error status:", error.status); - if ('exit' in error) console.log(" Error exit code:", error.exit); + logger.debug(" Error message:", errorMessage); + if ('status' in error) logger.debug(" Error status:", error.status); + if ('exit' in error) logger.debug(" Error exit code:", error.exit); // Check if it's an authentication error if (errorMessage.includes("not logged in") || errorMessage.includes("authentication")) { - console.log(" 💡 This might be an authentication issue. Try running 'firebase login' first."); + logger.warning("This might be an authentication issue. Try running 'firebase login' first."); } // Check if it's a project access error if (errorMessage.includes("not found") || errorMessage.includes("access")) { - console.log(" 💡 This might be a project access issue. Check if the project ID is correct and you have access to it."); + logger.warning("This might be a project access issue. Check if the project ID is correct and you have access to it."); } } @@ -92,7 +93,7 @@ async function deleteFunctionWithRetry( nonInteractive: true, cwd: process.cwd(), }); - console.log(`✅ Deleted function: ${functionName}`); + logger.success(`Deleted function: ${functionName}`); } catch (error: unknown) { if ( error && @@ -101,7 +102,7 @@ async function deleteFunctionWithRetry( typeof error.message === "string" && error.message.includes("not found") ) { - console.log(`ℹ️ Function not found (already deleted): ${functionName}`); + logger.info(`Function not found (already deleted): ${functionName}`); return; // Not an error, function was already deleted } throw error; @@ -110,8 +111,8 @@ async function deleteFunctionWithRetry( { retries: MAX_RETRIES, onFailedAttempt: (error) => { - console.log( - `❌ Failed to delete ${functionName} (attempt ${error.attemptNumber}/${ + logger.error( + `Failed to delete ${functionName} (attempt ${error.attemptNumber}/${ MAX_RETRIES + 1 }):`, error.message @@ -125,17 +126,17 @@ async function deleteFunctionWithRetry( * Pre-cleanup: Remove all existing functions before deployment */ export async function preCleanup(client: FirebaseClient): Promise { - console.log("🧹 Starting pre-cleanup..."); + logger.cleanup("Starting pre-cleanup..."); try { const deployedFunctions = await getDeployedFunctions(client); if (deployedFunctions.length === 0) { - console.log("ℹ️ No functions to clean up"); + logger.info("No functions to clean up"); return; } - console.log(`Found ${deployedFunctions.length} functions to clean up`); + logger.info(`Found ${deployedFunctions.length} functions to clean up`); // Delete functions in batches with rate limiting const batches: string[][] = []; @@ -145,7 +146,7 @@ export async function preCleanup(client: FirebaseClient): Promise { for (let i = 0; i < batches.length; i++) { const batch = batches[i]; - console.log(`Cleaning up batch ${i + 1}/${batches.length} (${batch.length} functions)`); + logger.cleanup(`Cleaning up batch ${i + 1}/${batches.length} (${batch.length} functions)`); // Delete functions in parallel within the batch const deletePromises = batch.map((functionName) => @@ -156,14 +157,14 @@ export async function preCleanup(client: FirebaseClient): Promise { // Add delay between batches if (i < batches.length - 1) { - console.log(`Waiting ${CLEANUP_DELAY}ms before next batch...`); + logger.debug(`Waiting ${CLEANUP_DELAY}ms before next batch...`); await sleep(CLEANUP_DELAY); } } - console.log("✅ Pre-cleanup completed"); + logger.success("Pre-cleanup completed"); } catch (error) { - console.error("❌ Pre-cleanup failed:", error); + logger.error("Pre-cleanup failed:", error); throw error; } } @@ -175,23 +176,23 @@ export async function deployFunctionsWithRetry( client: any, functionsToDeploy: string[] ): Promise { - console.log(`🚀 Deploying ${functionsToDeploy.length} functions with rate limiting...`); - console.log(`📋 Functions to deploy:`, functionsToDeploy); - console.log(`🔧 Project ID: ${process.env.PROJECT_ID}`); - console.log(`🔧 Region: ${process.env.REGION || 'us-central1'}`); - console.log(`🔧 Runtime: ${process.env.TEST_RUNTIME}`); + logger.deployment(`Deploying ${functionsToDeploy.length} functions with rate limiting...`); + logger.deployment(`Functions to deploy:`, functionsToDeploy); + logger.deployment(`Project ID: ${process.env.PROJECT_ID}`); + logger.deployment(`Region: ${process.env.REGION || 'us-central1'}`); + logger.deployment(`Runtime: ${process.env.TEST_RUNTIME}`); // Pre-deployment checks - console.log(`\n🔍 Pre-deployment checks:`); - console.log(` - Project ID set: ${!!process.env.PROJECT_ID}`); - console.log(` - Working directory: ${process.cwd()}`); + logger.group("Pre-deployment checks"); + logger.debug(`- Project ID set: ${!!process.env.PROJECT_ID}`); + logger.debug(`- Working directory: ${process.cwd()}`); // Import fs dynamically for ES modules const fs = await import('fs'); - console.log(` - Functions directory exists: ${fs.existsSync('./functions')}`); - console.log(` - Functions.yaml exists: ${fs.existsSync('./functions/functions.yaml')}`); - console.log(` - Package.json exists: ${fs.existsSync('./functions/package.json')}`); + logger.debug(`- Functions directory exists: ${fs.existsSync('./functions')}`); + logger.debug(`- Functions.yaml exists: ${fs.existsSync('./functions/functions.yaml')}`); + logger.debug(`- Package.json exists: ${fs.existsSync('./functions/package.json')}`); if (!process.env.PROJECT_ID) { throw new Error("PROJECT_ID environment variable is not set"); @@ -208,18 +209,18 @@ export async function deployFunctionsWithRetry( // Check functions.yaml content try { const functionsYaml = fs.readFileSync('./functions/functions.yaml', 'utf8'); - console.log(` - Functions.yaml content preview:`); - console.log(` ${functionsYaml.substring(0, 200)}...`); + logger.debug(` - Functions.yaml content preview:`); + logger.debug(` ${functionsYaml.substring(0, 200)}...`); } catch (error: any) { - console.log(` - Error reading functions.yaml: ${error.message}`); + logger.warning(` - Error reading functions.yaml: ${error.message}`); } // Set up Firebase project configuration - console.log(` - Setting up Firebase project configuration...`); + logger.debug(` - Setting up Firebase project configuration...`); process.env.FIREBASE_PROJECT = process.env.PROJECT_ID; process.env.GCLOUD_PROJECT = process.env.PROJECT_ID; - console.log(` - FIREBASE_PROJECT: ${process.env.FIREBASE_PROJECT}`); - console.log(` - GCLOUD_PROJECT: ${process.env.GCLOUD_PROJECT}`); + logger.debug(` - FIREBASE_PROJECT: ${process.env.FIREBASE_PROJECT}`); + logger.debug(` - GCLOUD_PROJECT: ${process.env.GCLOUD_PROJECT}`); // Deploy functions in batches const batches = []; @@ -229,17 +230,17 @@ export async function deployFunctionsWithRetry( for (let i = 0; i < batches.length; i++) { const batch = batches[i]; - console.log(`\n📦 Deploying batch ${i + 1}/${batches.length} (${batch.length} functions)`); - console.log(`📋 Batch functions:`, batch); + logger.deployment(`Deploying batch ${i + 1}/${batches.length} (${batch.length} functions)`); + logger.deployment(`Batch functions:`, batch); try { await pRetry( async () => { await deploymentLimiter(async () => { - console.log(`\n🔧 Starting deployment attempt...`); - console.log(`🔧 Project ID: ${process.env.PROJECT_ID}`); - console.log(`🔧 Working directory: ${process.cwd()}`); - console.log(`🔧 Functions source: ${process.cwd()}/functions`); + logger.deployment(`Starting deployment attempt...`); + logger.deployment(`Project ID: ${process.env.PROJECT_ID}`); + logger.deployment(`Working directory: ${process.cwd()}`); + logger.deployment(`Functions source: ${process.cwd()}/functions`); const deployOptions = { only: "functions", @@ -250,31 +251,29 @@ export async function deployFunctionsWithRetry( cwd: process.cwd(), }; - - - console.log(`🔧 Deploy options:`, JSON.stringify(deployOptions, null, 2)); + logger.debug(`Deploy options:`, JSON.stringify(deployOptions, null, 2)); try { await client.deploy(deployOptions); - console.log(`✅ Deployment command completed successfully`); + logger.success(`Deployment command completed successfully`); } catch (deployError: any) { - console.log(`❌ Deployment command failed with error:`); - console.log(` Error type: ${deployError.constructor.name}`); - console.log(` Error message: ${deployError.message}`); - console.log(` Error stack: ${deployError.stack}`); + logger.error(`Deployment command failed with error:`); + logger.error(` Error type: ${deployError.constructor.name}`); + logger.error(` Error message: ${deployError.message}`); + logger.error(` Error stack: ${deployError.stack}`); // Log all properties of the error object - console.log(` Error properties:`); + logger.debug(` Error properties:`); Object.keys(deployError).forEach(key => { try { const value = deployError[key]; if (typeof value === 'object' && value !== null) { - console.log(` ${key}: ${JSON.stringify(value, null, 4)}`); + logger.debug(` ${key}: ${JSON.stringify(value, null, 4)}`); } else { - console.log(` ${key}: ${value}`); + logger.debug(` ${key}: ${value}`); } } catch (e) { - console.log(` ${key}: [Error serializing property]`); + logger.debug(` ${key}: [Error serializing property]`); } }); @@ -285,21 +284,21 @@ export async function deployFunctionsWithRetry( { retries: MAX_RETRIES, onFailedAttempt: (error: any) => { - console.log(`\n❌ Deployment failed (attempt ${error.attemptNumber}/${MAX_RETRIES + 1}):`); - console.log(` Error message: ${error.message}`); - console.log(` Error type: ${error.constructor.name}`); + logger.error(`Deployment failed (attempt ${error.attemptNumber}/${MAX_RETRIES + 1}):`); + logger.error(` Error message: ${error.message}`); + logger.error(` Error type: ${error.constructor.name}`); // Log detailed error information during retries if (error.children && error.children.length > 0) { - console.log("📋 Detailed deployment errors:"); + logger.debug("Detailed deployment errors:"); error.children.forEach((child: any, index: number) => { - console.log(` ${index + 1}. ${child.message || child}`); + logger.debug(` ${index + 1}. ${child.message || child}`); if (child.original) { - console.log( + logger.debug( ` Original error message: ${child.original.message || "No message"}` ); - console.log(` Original error code: ${child.original.code || "No code"}`); - console.log( + logger.debug(` Original error code: ${child.original.code || "No code"}`); + logger.debug( ` Original error status: ${child.original.status || "No status"}` ); } @@ -307,82 +306,82 @@ export async function deployFunctionsWithRetry( } // Log the full error structure for debugging - console.log("🔍 Full error details:"); - console.log(` - Message: ${error.message}`); - console.log(` - Status: ${error.status}`); - console.log(` - Exit code: ${error.exit}`); - console.log(` - Attempt: ${error.attemptNumber}`); - console.log(` - Retries left: ${error.retriesLeft}`); + logger.debug("Full error details:"); + logger.debug(` - Message: ${error.message}`); + logger.debug(` - Status: ${error.status}`); + logger.debug(` - Exit code: ${error.exit}`); + logger.debug(` - Attempt: ${error.attemptNumber}`); + logger.debug(` - Retries left: ${error.retriesLeft}`); // Log error context if available if (error.context) { - console.log(` - Context: ${JSON.stringify(error.context, null, 2)}`); + logger.debug(` - Context: ${JSON.stringify(error.context, null, 2)}`); } // Log error body if available if (error.body) { - console.log(` - Body: ${JSON.stringify(error.body, null, 2)}`); + logger.debug(` - Body: ${JSON.stringify(error.body, null, 2)}`); } }, } ); - console.log(`✅ Batch ${i + 1} deployed successfully`); + logger.success(`Batch ${i + 1} deployed successfully`); // Add delay between batches if (i < batches.length - 1) { - console.log(`Waiting ${DELAY_BETWEEN_BATCHES}ms before next batch...`); + logger.debug(`Waiting ${DELAY_BETWEEN_BATCHES}ms before next batch...`); await sleep(DELAY_BETWEEN_BATCHES); } } catch (error: any) { - console.error(`\n❌ FINAL FAILURE: Failed to deploy batch ${i + 1} after all retries`); - console.error(` Error type: ${error.constructor.name}`); - console.error(` Error message: ${error.message}`); - console.error(` Error stack: ${error.stack}`); + logger.error(`FINAL FAILURE: Failed to deploy batch ${i + 1} after all retries`); + logger.error(` Error type: ${error.constructor.name}`); + logger.error(` Error message: ${error.message}`); + logger.error(` Error stack: ${error.stack}`); // Log detailed error information if (error.children && error.children.length > 0) { - console.log("📋 Detailed deployment errors:"); + logger.debug("Detailed deployment errors:"); error.children.forEach((child: any, index: number) => { - console.log(` ${index + 1}. ${child.message || child}`); + logger.debug(` ${index + 1}. ${child.message || child}`); if (child.original) { - console.log(` Original error message: ${child.original.message || "No message"}`); - console.log(` Original error code: ${child.original.code || "No code"}`); - console.log(` Original error status: ${child.original.status || "No status"}`); + logger.debug(` Original error message: ${child.original.message || "No message"}`); + logger.debug(` Original error code: ${child.original.code || "No code"}`); + logger.debug(` Original error status: ${child.original.status || "No status"}`); } }); } // Log the full error structure for debugging - console.log("🔍 Final error details:"); - console.log(` - Message: ${error.message}`); - console.log(` - Status: ${error.status}`); - console.log(` - Exit code: ${error.exit}`); - console.log(` - Attempt: ${error.attemptNumber}`); - console.log(` - Retries left: ${error.retriesLeft}`); + logger.debug("Final error details:"); + logger.debug(` - Message: ${error.message}`); + logger.debug(` - Status: ${error.status}`); + logger.debug(` - Exit code: ${error.exit}`); + logger.debug(` - Attempt: ${error.attemptNumber}`); + logger.debug(` - Retries left: ${error.retriesLeft}`); // Log error context if available if (error.context) { - console.log(` - Context: ${JSON.stringify(error.context, null, 2)}`); + logger.debug(` - Context: ${JSON.stringify(error.context, null, 2)}`); } // Log error body if available if (error.body) { - console.log(` - Body: ${JSON.stringify(error.body, null, 2)}`); + logger.debug(` - Body: ${JSON.stringify(error.body, null, 2)}`); } // Log all error properties - console.log(` - All error properties:`); + logger.debug(` - All error properties:`); Object.keys(error).forEach(key => { try { const value = error[key]; if (typeof value === 'object' && value !== null) { - console.log(` ${key}: ${JSON.stringify(value, null, 4)}`); + logger.debug(` ${key}: ${JSON.stringify(value, null, 4)}`); } else { - console.log(` ${key}: ${value}`); + logger.debug(` ${key}: ${value}`); } } catch (e) { - console.log(` ${key}: [Error serializing property]`); + logger.debug(` ${key}: [Error serializing property]`); } }); @@ -390,29 +389,30 @@ export async function deployFunctionsWithRetry( } } - console.log("✅ All functions deployed successfully"); + logger.success("All functions deployed successfully"); + logger.groupEnd(); } /** * Post-cleanup: Remove deployed functions after tests */ export async function postCleanup(client: any, testRunId: string): Promise { - console.log("🧹 Starting post-cleanup..."); + logger.cleanup("Starting post-cleanup..."); try { const deployedFunctions = await getDeployedFunctions(client); // print the deployed functions - console.log("🔍 Deployed functions:", deployedFunctions); + logger.debug("Deployed functions:", deployedFunctions); const testFunctions = deployedFunctions.filter((name) => name && name.includes(testRunId)); if (testFunctions.length === 0) { - console.log("ℹ️ No test functions to clean up"); + logger.info("No test functions to clean up"); return; } - console.log(`Found ${testFunctions.length} test functions to clean up:`); + logger.info(`Found ${testFunctions.length} test functions to clean up:`); testFunctions.forEach((funcName, index) => { - console.log(` ${index + 1}. ${funcName}`); + logger.debug(` ${index + 1}. ${funcName}`); }); // Delete test functions in batches with rate limiting @@ -423,14 +423,14 @@ export async function postCleanup(client: any, testRunId: string): Promise for (let i = 0; i < batches.length; i++) { const batch = batches[i]; - console.log(`Cleaning up batch ${i + 1}/${batches.length} (${batch.length} functions)`); + logger.cleanup(`Cleaning up batch ${i + 1}/${batches.length} (${batch.length} functions)`); // Delete functions in parallel within the batch const deletePromises = batch.map((functionName) => cleanupLimiter(async () => { - console.log(`🗑️ Deleting function: ${functionName}`); + logger.cleanup(`Deleting function: ${functionName}`); await deleteFunctionWithRetry(client, functionName); - console.log(`✅ Successfully deleted: ${functionName}`); + logger.success(`Successfully deleted: ${functionName}`); }) ); @@ -438,14 +438,14 @@ export async function postCleanup(client: any, testRunId: string): Promise // Add delay between batches if (i < batches.length - 1) { - console.log(`Waiting ${CLEANUP_DELAY}ms before next batch...`); + logger.debug(`Waiting ${CLEANUP_DELAY}ms before next batch...`); await sleep(CLEANUP_DELAY); } } - console.log("✅ Post-cleanup completed"); + logger.success("Post-cleanup completed"); } catch (error) { - console.error("❌ Post-cleanup failed:", error); + logger.error("Post-cleanup failed:", error); throw error; } } diff --git a/integration_test/run.ts b/integration_test/run.ts index fffedb0b8..4aa04e782 100644 --- a/integration_test/run.ts +++ b/integration_test/run.ts @@ -8,6 +8,7 @@ import { detectFromPort } from "firebase-tools/lib/deploy/functions/runtimes/dis import setup from "./setup.js"; import * as dotenv from "dotenv"; import { deployFunctionsWithRetry, postCleanup } from "./deployment-utils.js"; +import { logger } from "./src/logger.js"; dotenv.config(); @@ -40,12 +41,12 @@ if ( // !GOOGLE_ANALYTICS_API_SECRET || !TEST_RUNTIME ) { - console.error("Required environment variables are not set. Exiting..."); + logger.error("Required environment variables are not set. Exiting..."); process.exit(1); } if (!["node", "python"].includes(TEST_RUNTIME)) { - console.error("Invalid TEST_RUNTIME. Must be either 'node' or 'python'. Exiting..."); + logger.error("Invalid TEST_RUNTIME. Must be either 'node' or 'python'. Exiting..."); process.exit(1); } @@ -65,7 +66,7 @@ if (!FIREBASE_ADMIN && runtime === "node") { setup(runtime, TEST_RUN_ID, NODE_VERSION, FIREBASE_ADMIN); // Configure Firebase client with project ID -console.log("Configuring Firebase client with project ID:", PROJECT_ID); +logger.info("Configuring Firebase client with project ID:", PROJECT_ID); const firebaseClient = client; const config = { @@ -75,8 +76,8 @@ const config = { runtime: runtime === "node" ? "nodejs18" : "python311", }; -console.log("Firebase config created: "); -console.log(JSON.stringify(config, null, 2)); +logger.debug("Firebase config created: "); +logger.debug(JSON.stringify(config, null, 2)); const firebaseConfig = { databaseURL: DATABASE_URL, @@ -122,13 +123,13 @@ function generateUniqueHash(originalName: string): string { * @returns A promise that resolves with a function to kill the server. */ async function discoverAndModifyEndpoints() { - console.log("Discovering endpoints..."); + logger.info("Discovering endpoints..."); try { const port = await portfinder.getPortPromise({ port: 9000 }); const delegate = await getRuntimeDelegate(config); const killServer = await delegate.serveAdmin(port.toString(), {}, env); - console.log("Started on port", port); + logger.info("Started on port", port); const originalYaml = (await detectFromPort( port, config.projectId, @@ -154,7 +155,7 @@ async function discoverAndModifyEndpoints() { return killServer; } catch (err) { - console.error("Error discovering endpoints. Exiting.", err); + logger.error("Error discovering endpoints. Exiting.", err); process.exit(1); } } @@ -163,34 +164,34 @@ function writeFunctionsYaml(filePath: string, data: any): void { try { fs.writeFileSync(filePath, yaml.dump(data)); } catch (err) { - console.error("Error writing functions.yaml. Exiting.", err); + logger.error("Error writing functions.yaml. Exiting.", err); process.exit(1); } } async function deployModifiedFunctions(): Promise { - console.log("🚀 Deploying functions with id:", TEST_RUN_ID); + logger.deployment(`Deploying functions with id: ${TEST_RUN_ID}`); try { // Get the function names that will be deployed const functionNames = modifiedYaml ? Object.keys(modifiedYaml.endpoints) : []; - console.log("📋 Functions to deploy:", functionNames); - console.log("📊 Total functions to deploy:", functionNames.length); + logger.deployment("Functions to deploy:", functionNames); + logger.deployment(`Total functions to deploy: ${functionNames.length}`); // Deploy with rate limiting and retry logic await deployFunctionsWithRetry(firebaseClient, functionNames); - console.log("✅ Functions have been deployed successfully."); - console.log("🔗 You can view your deployed functions in the Firebase Console:"); - console.log(` https://console.firebase.google.com/project/${PROJECT_ID}/functions`); + logger.success("Functions have been deployed successfully."); + logger.info("You can view your deployed functions in the Firebase Console:"); + logger.info(` https://console.firebase.google.com/project/${PROJECT_ID}/functions`); } catch (err) { - console.error("❌ Error deploying functions. Exiting.", err); + logger.error("Error deploying functions. Exiting.", err); throw err; } } function cleanFiles(): void { - console.log("🧹 Cleaning files..."); + logger.cleanup("Cleaning files..."); const functionsDir = "functions"; process.chdir(functionsDir); // go to functions try { @@ -237,15 +238,15 @@ function cleanFiles(): void { } if (deletedFiles.length > 0) { - console.log(`🗑️ Deleted ${deletedFiles.length} files/directories:`); + logger.cleanup(`Deleted ${deletedFiles.length} files/directories:`); deletedFiles.forEach((file, index) => { - console.log(` ${index + 1}. ${file}`); + logger.debug(` ${index + 1}. ${file}`); }); } else { - console.log("ℹ️ No files to clean up"); + logger.info("No files to clean up"); } } catch (error) { - console.error("Error occurred while cleaning files:", error); + logger.error("Error occurred while cleaning files:", error); } process.chdir("../"); // go back to integration_test @@ -297,9 +298,9 @@ const spawnAsync = (command: string, args: string[], options: any): Promise { const humanReadableRuntime = TEST_RUNTIME === "node" ? "Node.js" : "Python"; try { - console.log(`🧪 Starting ${humanReadableRuntime} Tests...`); - console.log("🔍 Running: database test only"); - console.log("📁 Test file: integration_test/tests/v2/database.test.ts"); + logger.info(`Starting ${humanReadableRuntime} Tests...`); + logger.info("Running: database test only"); + logger.info("Test file: integration_test/tests/v2/database.test.ts"); // Run only the database test const output = await spawnAsync("npx", ["jest", "--testPathPattern=database.test.ts", "--verbose"], { @@ -309,38 +310,38 @@ async function runTests(): Promise { }, }); - console.log("📋 Test output received:"); - console.log(output); + logger.info("Test output received:"); + logger.debug(output); // Check if tests passed if (output.includes("PASS") && !output.includes("FAIL")) { - console.log("✅ Database tests completed successfully!"); - console.log("🎯 All database function triggers are working correctly."); + logger.success("Database tests completed successfully!"); + logger.success("All database function triggers are working correctly."); } else { - console.log("⚠️ Some tests may have failed. Check the output above."); + logger.warning("Some tests may have failed. Check the output above."); } - console.log(`${humanReadableRuntime} Tests Completed.`); + logger.info(`${humanReadableRuntime} Tests Completed.`); } catch (error) { - console.error("❌ Error during testing:", error); + logger.error("Error during testing:", error); throw error; } } async function handleCleanUp(): Promise { - console.log("Cleaning up..."); + logger.cleanup("Cleaning up..."); try { // Use our new post-cleanup utility with rate limiting await postCleanup(firebaseClient, TEST_RUN_ID); } catch (err) { - console.error("Error during post-cleanup:", err); + logger.error("Error during post-cleanup:", err); // Don't throw here to ensure files are still cleaned } cleanFiles(); } async function gracefulShutdown(): Promise { - console.log("SIGINT received..."); + logger.info("SIGINT received..."); await handleCleanUp(); process.exit(1); } @@ -350,14 +351,14 @@ async function runIntegrationTests(): Promise { try { // Skip pre-cleanup for now to test if the main flow works - console.log("⏭️ Skipping pre-cleanup for testing..."); + logger.info("Skipping pre-cleanup for testing..."); const killServer = await discoverAndModifyEndpoints(); await deployModifiedFunctions(); await killServer(); await runTests(); } catch (err) { - console.error("Error occurred during integration tests:", err); + logger.error("Error occurred during integration tests:", err); // Re-throw the original error instead of wrapping it throw err; } finally { @@ -367,10 +368,10 @@ async function runIntegrationTests(): Promise { runIntegrationTests() .then(() => { - console.log("Integration tests completed"); + logger.success("Integration tests completed"); process.exit(0); }) .catch((error) => { - console.error("An error occurred during integration tests", error); + logger.error("An error occurred during integration tests", error); process.exit(1); }); From 89309777cdee1554d4ab2aa75d09f2fcfb622a53 Mon Sep 17 00:00:00 2001 From: HassanBahati Date: Tue, 19 Aug 2025 01:35:49 +0300 Subject: [PATCH 21/25] tests: add v1 database functions --- integration_test/functions/src/index.ts | 4 +- integration_test/functions/src/v1/index.ts | 14 +- integration_test/run.ts | 11 +- integration_test/tests/v1/database.test.ts | 612 ++++++++++----------- 4 files changed, 320 insertions(+), 321 deletions(-) diff --git a/integration_test/functions/src/index.ts b/integration_test/functions/src/index.ts index d523b2ed3..80abc60ee 100644 --- a/integration_test/functions/src/index.ts +++ b/integration_test/functions/src/index.ts @@ -1,7 +1,7 @@ import * as admin from "firebase-admin"; -// import * as v1 from "./v1"; +import * as v1 from "./v1"; import * as v2 from "./v2"; -export { v2 }; +export { v1, v2 }; admin.initializeApp(); diff --git a/integration_test/functions/src/v1/index.ts b/integration_test/functions/src/v1/index.ts index b9f43a177..815a84592 100644 --- a/integration_test/functions/src/v1/index.ts +++ b/integration_test/functions/src/v1/index.ts @@ -1,11 +1,11 @@ -export * from "./analytics-tests"; +// export * from "./analytics-tests"; // export * from "./auth-tests"; export * from "./database-tests"; -export * from "./firestore-tests"; +// export * from "./firestore-tests"; // Temporarily disable http test - will not work unless running on projects w/ permission to create public functions. // export * from "./https-tests"; -export * from "./pubsub-tests"; -export * from "./remoteConfig-tests"; -export * from "./storage-tests"; -export * from "./tasks-tests"; -export * from "./testLab-tests"; +// export * from "./pubsub-tests"; +// export * from "./remoteConfig-tests"; +// export * from "./storage-tests"; +// export * from "./tasks-tests"; +// export * from "./testLab-tests"; diff --git a/integration_test/run.ts b/integration_test/run.ts index 4aa04e782..ca4efc755 100644 --- a/integration_test/run.ts +++ b/integration_test/run.ts @@ -299,11 +299,10 @@ async function runTests(): Promise { const humanReadableRuntime = TEST_RUNTIME === "node" ? "Node.js" : "Python"; try { logger.info(`Starting ${humanReadableRuntime} Tests...`); - logger.info("Running: database test only"); - logger.info("Test file: integration_test/tests/v2/database.test.ts"); + logger.info("Running all integration tests"); - // Run only the database test - const output = await spawnAsync("npx", ["jest", "--testPathPattern=database.test.ts", "--verbose"], { + // Run all tests + const output = await spawnAsync("npx", ["jest", "--verbose"], { env: { ...process.env, TEST_RUN_ID, @@ -315,8 +314,8 @@ async function runTests(): Promise { // Check if tests passed if (output.includes("PASS") && !output.includes("FAIL")) { - logger.success("Database tests completed successfully!"); - logger.success("All database function triggers are working correctly."); + logger.success("All tests completed successfully!"); + logger.success("All function triggers are working correctly."); } else { logger.warning("Some tests may have failed. Check the output above."); } diff --git a/integration_test/tests/v1/database.test.ts b/integration_test/tests/v1/database.test.ts index a180cb237..bfaf04103 100644 --- a/integration_test/tests/v1/database.test.ts +++ b/integration_test/tests/v1/database.test.ts @@ -1,306 +1,306 @@ -// import * as admin from "firebase-admin"; -// import { retry } from "../utils"; -// import { initializeFirebase } from "../firebaseSetup"; -// import { Reference } from "@firebase/database-types"; -// import { logger } from "../../src/logger"; - -// describe("Firebase Database (v1)", () => { -// // const projectId = process.env.PROJECT_ID; -// // const testId = process.env.TEST_RUN_ID; - -// // if (!testId || !projectId) { -// // throw new Error("Environment configured incorrectly."); -// // } - -// // beforeAll(async () => { -// // await initializeFirebase(); -// // }); - -// // afterAll(async () => { -// // await admin.firestore().collection("databaseRefOnCreateTests").doc(testId).delete(); -// // await admin.firestore().collection("databaseRefOnDeleteTests").doc(testId).delete(); -// // await admin.firestore().collection("databaseRefOnUpdateTests").doc(testId).delete(); -// // await admin.firestore().collection("databaseRefOnWriteTests").doc(testId).delete(); -// // }); - -// // async function setupRef(refPath: string) { -// // const ref = admin.database().ref(refPath); -// // await ref.set({ ".sv": "timestamp" }); -// // return ref; -// // } - -// // async function teardownRef(ref: Reference) { -// // if (ref) { -// // try { -// // await ref.remove(); -// // } catch (err) { -// // logger.error("Teardown error", err); -// // } -// // } -// // } - -// // function getLoggedContext(collectionName: string, testId: string) { -// // return admin -// // .firestore() -// // .collection(collectionName) -// // .doc(testId) -// // .get() -// // .then((logSnapshot) => logSnapshot.data()); -// // } - -// // describe("ref onCreate trigger", () => { -// // let ref: Reference; -// // let loggedContext: admin.firestore.DocumentData | undefined; - -// // beforeAll(async () => { -// // ref = await setupRef(`dbTests/${testId}/start`); -// // loggedContext = await retry(() => getLoggedContext("databaseRefOnCreateTests", testId)); -// // }); - -// // afterAll(async () => { -// // await teardownRef(ref); -// // }); - -// // it("should not have event.app", () => { -// // expect(loggedContext?.app).toBeUndefined(); -// // }); - -// // it("should give refs access to admin data", async () => { -// // await ref.parent?.child("adminOnly").update({ allowed: 1 }); - -// // const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); -// // const adminData = adminDataSnapshot?.val(); - -// // expect(adminData).toEqual({ allowed: 1 }); -// // }); - -// // it("should have a correct ref url", () => { -// // expect(loggedContext?.url).toMatch( -// // new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) -// // ); -// // }); - -// // it("should have refs resources", () => { -// // expect(loggedContext?.resource.name).toMatch( -// // new RegExp( -// // `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start` -// // ) -// // ); -// // }); - -// // it("should not include path", () => { -// // expect(loggedContext?.path).toBeUndefined(); -// // }); - -// // it("should have the right eventType", () => { -// // expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.create"); -// // }); - -// // it("should have eventId", () => { -// // expect(loggedContext?.eventId).toBeDefined(); -// // }); - -// // it("should have timestamp", () => { -// // expect(loggedContext?.timestamp).toBeDefined(); -// // }); - -// // it("should not have action", () => { -// // expect(loggedContext?.action).toBeUndefined(); -// // }); - -// // it("should have admin authType", () => { -// // expect(loggedContext?.authType).toEqual("ADMIN"); -// // }); -// // }); - -// // describe("ref onDelete trigger", () => { -// // let ref: Reference; -// // let loggedContext: admin.firestore.DocumentData | undefined; - -// // beforeAll(async () => { -// // ref = await setupRef(`dbTests/${testId}/start`); -// // await ref.remove(); -// // loggedContext = await retry(() => getLoggedContext("databaseRefOnDeleteTests", testId)); -// // }); - -// // it("should not have event.app", () => { -// // expect(loggedContext?.app).toBeUndefined(); -// // }); - -// // it("should have a correct ref url", () => { -// // expect(loggedContext?.url).toMatch( -// // new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) -// // ); -// // }); - -// // it("should have refs resources", () => { -// // expect(loggedContext?.resource.name).toMatch( -// // new RegExp( -// // `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` -// // ) -// // ); -// // }); - -// // it("should not include path", () => { -// // expect(loggedContext?.path).toBeUndefined(); -// // }); - -// // it("should have the right eventType", () => { -// // expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.delete"); -// // }); - -// // it("should have eventId", () => { -// // expect(loggedContext?.eventId).toBeDefined(); -// // }); - -// // it("should have timestamp", () => { -// // expect(loggedContext?.timestamp).toBeDefined(); -// // }); - -// // it("should not have action", () => { -// // expect(loggedContext?.action).toBeUndefined(); -// // }); - -// // it("should have admin authType", () => { -// // expect(loggedContext?.authType).toEqual("ADMIN"); -// // }); -// // }); - -// // describe("ref onUpdate trigger", () => { -// // let ref: Reference; -// // let loggedContext: admin.firestore.DocumentData | undefined; - -// // beforeAll(async () => { -// // ref = await setupRef(`dbTests/${testId}/start`); -// // await ref.update({ updated: true }); -// // loggedContext = await retry(() => getLoggedContext("databaseRefOnUpdateTests", testId)); -// // }); - -// // afterAll(async () => { -// // await teardownRef(ref); -// // }); - -// // it("should not have event.app", () => { -// // expect(loggedContext?.app).toBeUndefined(); -// // }); - -// // it("should give refs access to admin data", async () => { -// // await ref.parent?.child("adminOnly").update({ allowed: 1 }); - -// // const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); -// // const adminData = adminDataSnapshot?.val(); - -// // expect(adminData).toEqual({ allowed: 1 }); -// // }); - -// // it("should have a correct ref url", () => { -// // expect(loggedContext?.url).toMatch( -// // new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) -// // ); -// // }); - -// // it("should have refs resources", () => { -// // expect(loggedContext?.resource.name).toMatch( -// // new RegExp( -// // `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` -// // ) -// // ); -// // }); - -// // it("should not include path", () => { -// // expect(loggedContext?.path).toBeUndefined(); -// // }); - -// // it("should have the right eventType", () => { -// // expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.update"); -// // }); - -// // it("should have eventId", () => { -// // expect(loggedContext?.eventId).toBeDefined(); -// // }); - -// // it("should have timestamp", () => { -// // expect(loggedContext?.timestamp).toBeDefined(); -// // }); - -// // it("should not have action", () => { -// // expect(loggedContext?.action).toBeUndefined(); -// // }); - -// // it("should have admin authType", () => { -// // expect(loggedContext?.authType).toEqual("ADMIN"); -// // }); - -// // it("should log onUpdate event with updated data", async () => { -// // const parsedData = JSON.parse(loggedContext?.data ?? {}); -// // expect(parsedData).toEqual({ updated: true }); -// // }); -// // }); - -// // describe("ref onWrite trigger", () => { -// // let ref: Reference; -// // let loggedContext: admin.firestore.DocumentData | undefined; - -// // beforeAll(async () => { -// // ref = await setupRef(`dbTests/${testId}/start`); - -// // loggedContext = await retry(() => getLoggedContext("databaseRefOnWriteTests", testId)); -// // }); - -// // afterAll(async () => { -// // await teardownRef(ref); -// // }); - -// // it("should not have event.app", () => { -// // expect(loggedContext?.app).toBeUndefined(); -// // }); - -// // it("should give refs access to admin data", async () => { -// // await ref.parent?.child("adminOnly").update({ allowed: 1 }); - -// // const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); -// // const adminData = adminDataSnapshot?.val(); - -// // expect(adminData).toEqual({ allowed: 1 }); -// // }); - -// // it("should have a correct ref url", () => { -// // expect(loggedContext?.url).toMatch( -// // new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) -// // ); -// // }); - -// // it("should have refs resources", () => { -// // expect(loggedContext?.resource.name).toMatch( -// // new RegExp( -// // `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` -// // ) -// // ); -// // }); - -// // it("should not include path", () => { -// // expect(loggedContext?.path).toBeUndefined(); -// // }); - -// // it("should have the right eventType", () => { -// // expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.write"); -// // }); - -// // it("should have eventId", () => { -// // expect(loggedContext?.eventId).toBeDefined(); -// // }); - -// // it("should have timestamp", () => { -// // expect(loggedContext?.timestamp).toBeDefined(); -// // }); - -// // it("should not have action", () => { -// // expect(loggedContext?.action).toBeUndefined(); -// // }); - -// // it("should have admin authType", () => { -// // expect(loggedContext?.authType).toEqual("ADMIN"); -// // }); -// // }); - -// }); +import * as admin from "firebase-admin"; +import { retry } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; +import { Reference } from "@firebase/database-types"; +import { logger } from "../../src/logger"; + +describe("Firebase Database (v1)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("databaseRefOnCreateTests").doc(testId).delete(); + await admin.firestore().collection("databaseRefOnDeleteTests").doc(testId).delete(); + await admin.firestore().collection("databaseRefOnUpdateTests").doc(testId).delete(); + await admin.firestore().collection("databaseRefOnWriteTests").doc(testId).delete(); + }); + + async function setupRef(refPath: string) { + const ref = admin.database().ref(refPath); + await ref.set({ ".sv": "timestamp" }); + return ref; + } + + async function teardownRef(ref: Reference) { + if (ref) { + try { + await ref.remove(); + } catch (err) { + logger.error("Teardown error", err); + } + } + } + + function getLoggedContext(collectionName: string, testId: string) { + return admin + .firestore() + .collection(collectionName) + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()); + } + + describe("ref onCreate trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + ref = await setupRef(`dbTests/${testId}/start`); + loggedContext = await retry(() => getLoggedContext("databaseRefOnCreateTests", testId)); + }); + + afterAll(async () => { + await teardownRef(ref); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + await ref.parent?.child("adminOnly").update({ allowed: 1 }); + + const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); + const adminData = adminDataSnapshot?.val(); + + expect(adminData).toEqual({ allowed: 1 }); + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch( + new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) + ); + }); + + it("should have refs resources", () => { + expect(loggedContext?.resource.name).toMatch( + new RegExp( + `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start` + ) + ); + }); + + it("should not include path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.create"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + + it("should have admin authType", () => { + expect(loggedContext?.authType).toEqual("ADMIN"); + }); + }); + + describe("ref onDelete trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + ref = await setupRef(`dbTests/${testId}/start`); + await ref.remove(); + loggedContext = await retry(() => getLoggedContext("databaseRefOnDeleteTests", testId)); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch( + new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) + ); + }); + + it("should have refs resources", () => { + expect(loggedContext?.resource.name).toMatch( + new RegExp( + `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` + ) + ); + }); + + it("should not include path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.delete"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + + it("should have admin authType", () => { + expect(loggedContext?.authType).toEqual("ADMIN"); + }); + }); + + describe("ref onUpdate trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + ref = await setupRef(`dbTests/${testId}/start`); + await ref.update({ updated: true }); + loggedContext = await retry(() => getLoggedContext("databaseRefOnUpdateTests", testId)); + }); + + afterAll(async () => { + await teardownRef(ref); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + await ref.parent?.child("adminOnly").update({ allowed: 1 }); + + const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); + const adminData = adminDataSnapshot?.val(); + + expect(adminData).toEqual({ allowed: 1 }); + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch( + new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) + ); + }); + + it("should have refs resources", () => { + expect(loggedContext?.resource.name).toMatch( + new RegExp( + `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` + ) + ); + }); + + it("should not include path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.update"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + + it("should have admin authType", () => { + expect(loggedContext?.authType).toEqual("ADMIN"); + }); + + it("should log onUpdate event with updated data", async () => { + const parsedData = JSON.parse(loggedContext?.data ?? {}); + expect(parsedData).toEqual({ updated: true }); + }); + }); + + describe("ref onWrite trigger", () => { + let ref: Reference; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + ref = await setupRef(`dbTests/${testId}/start`); + + loggedContext = await retry(() => getLoggedContext("databaseRefOnWriteTests", testId)); + }); + + afterAll(async () => { + await teardownRef(ref); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + await ref.parent?.child("adminOnly").update({ allowed: 1 }); + + const adminDataSnapshot = await ref.parent?.child("adminOnly").once("value"); + const adminData = adminDataSnapshot?.val(); + + expect(adminData).toEqual({ allowed: 1 }); + }); + + it("should have a correct ref url", () => { + expect(loggedContext?.url).toMatch( + new RegExp(`^https://${projectId}(-default-rtdb)*.firebaseio.com/dbTests/${testId}/start$`) + ); + }); + + it("should have refs resources", () => { + expect(loggedContext?.resource.name).toMatch( + new RegExp( + `^projects/_/instances/${projectId}(-default-rtdb)*/refs/dbTests/${testId}/start$` + ) + ); + }); + + it("should not include path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.database.ref.write"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + + it("should have admin authType", () => { + expect(loggedContext?.authType).toEqual("ADMIN"); + }); + }); + +}); From 5c94d12309539f7ae4bc690206a9b0520bdf3bbd Mon Sep 17 00:00:00 2001 From: HassanBahati Date: Wed, 20 Aug 2025 12:16:24 +0300 Subject: [PATCH 22/25] tests: fix tests --- .../functions/src/v1/https-tests.ts | 2 +- integration_test/functions/src/v1/index.ts | 16 +- integration_test/functions/src/v2/index.ts | 16 +- integration_test/tests/v1/auth.test.ts | 538 +++++++++--------- integration_test/tests/v1/firestore.test.ts | 496 ++++++++-------- integration_test/tests/v1/pubsub.test.ts | 234 ++++---- .../tests/v1/remoteConfig.test.ts | 127 +++-- integration_test/tests/v1/storage.test.ts | 370 ++++++------ integration_test/tests/v1/tasks.test.ts | 98 ++-- integration_test/tests/v1/testLab.test.ts | 107 ++-- integration_test/tests/v2/firestore.test.ts | 464 +++++++-------- integration_test/tests/v2/identity.test.ts | 260 ++++----- integration_test/tests/v2/pubsub.test.ts | 124 ++-- .../tests/v2/remoteConfig.test.ts | 119 ++-- integration_test/tests/v2/scheduler.test.ts | 113 ++-- integration_test/tests/v2/storage.test.ts | 334 +++++------ integration_test/tests/v2/tasks.test.ts | 98 ++-- integration_test/tests/v2/testLab.test.ts | 105 ++-- 18 files changed, 1846 insertions(+), 1775 deletions(-) diff --git a/integration_test/functions/src/v1/https-tests.ts b/integration_test/functions/src/v1/https-tests.ts index e74614862..ee5fa5050 100644 --- a/integration_test/functions/src/v1/https-tests.ts +++ b/integration_test/functions/src/v1/https-tests.ts @@ -1,5 +1,5 @@ import * as admin from "firebase-admin"; -import * as functions from "firebase-functions"; +import * as functions from "firebase-functions/v1"; import { REGION } from "../region"; import { sanitizeData } from "../utils"; diff --git a/integration_test/functions/src/v1/index.ts b/integration_test/functions/src/v1/index.ts index 815a84592..a0507265e 100644 --- a/integration_test/functions/src/v1/index.ts +++ b/integration_test/functions/src/v1/index.ts @@ -1,11 +1,11 @@ -// export * from "./analytics-tests"; -// export * from "./auth-tests"; +export * from "./analytics-tests"; +export * from "./auth-tests"; export * from "./database-tests"; -// export * from "./firestore-tests"; +export * from "./firestore-tests"; // Temporarily disable http test - will not work unless running on projects w/ permission to create public functions. // export * from "./https-tests"; -// export * from "./pubsub-tests"; -// export * from "./remoteConfig-tests"; -// export * from "./storage-tests"; -// export * from "./tasks-tests"; -// export * from "./testLab-tests"; +export * from "./pubsub-tests"; +export * from "./remoteConfig-tests"; +export * from "./storage-tests"; +export * from "./tasks-tests"; +export * from "./testLab-tests"; diff --git a/integration_test/functions/src/v2/index.ts b/integration_test/functions/src/v2/index.ts index ae089d815..323cd5bdb 100644 --- a/integration_test/functions/src/v2/index.ts +++ b/integration_test/functions/src/v2/index.ts @@ -2,19 +2,19 @@ import { setGlobalOptions } from "firebase-functions/v2"; import { REGION } from "../region"; setGlobalOptions({ region: REGION }); -// export * from "./alerts-tests"; +export * from "./alerts-tests"; export * from "./database-tests"; // export * from "./eventarc-tests"; -// export * from "./firestore-tests"; +export * from "./firestore-tests"; // Temporarily disable http test - will not work unless running on projects // w/ permission to create public functions. // export * from "./https-tests"; // TODO: cannot deploy multiple auth blocking funcs at once. Only have one of // v2 identity or v1 auth exported at once. // export * from "./identity-tests"; -// export * from "./pubsub-tests"; -// export * from "./scheduler-tests"; -// export * from "./storage-tests"; -// export * from "./tasks-tests"; -// export * from "./testLab-tests"; -// export * from "./remoteConfig-tests"; +export * from "./pubsub-tests"; +export * from "./scheduler-tests"; +export * from "./storage-tests"; +export * from "./tasks-tests"; +export * from "./testLab-tests"; +export * from "./remoteConfig-tests"; diff --git a/integration_test/tests/v1/auth.test.ts b/integration_test/tests/v1/auth.test.ts index 0e91dc856..3312198b6 100644 --- a/integration_test/tests/v1/auth.test.ts +++ b/integration_test/tests/v1/auth.test.ts @@ -1,269 +1,269 @@ -// import * as admin from "firebase-admin"; -// import { initializeApp } from "firebase/app"; -// import { createUserWithEmailAndPassword, getAuth, UserCredential } from "firebase/auth"; -// import { initializeFirebase } from "../firebaseSetup"; -// import { retry } from "../utils"; - -// describe("Firebase Auth (v1)", () => { -// let userIds: string[] = []; -// const projectId = process.env.PROJECT_ID; -// const testId = process.env.TEST_RUN_ID; -// const config = { -// apiKey: process.env.FIREBASE_API_KEY, -// authDomain: process.env.FIREBASE_AUTH_DOMAIN, -// databaseURL: process.env.DATABASE_URL, -// projectId, -// storageBucket: process.env.STORAGE_BUCKET, -// appId: process.env.FIREBASE_APP_ID, -// measurementId: process.env.FIREBASE_MEASUREMENT_ID, -// }; -// const app = initializeApp(config); - -// if (!testId || !projectId) { -// throw new Error("Environment configured incorrectly."); -// } - -// beforeAll(async () => { -// await initializeFirebase(); -// }); - -// afterAll(async () => { -// for (const userId in userIds) { -// await admin.firestore().collection("userProfiles").doc(userId).delete(); -// await admin.firestore().collection("authUserOnCreateTests").doc(userId).delete(); -// await admin.firestore().collection("authUserOnDeleteTests").doc(userId).delete(); -// await admin.firestore().collection("authBeforeCreateTests").doc(userId).delete(); -// await admin.firestore().collection("authBeforeSignInTests").doc(userId).delete(); -// } -// }); - -// describe("user onCreate trigger", () => { -// let userRecord: admin.auth.UserRecord; -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// userRecord = await admin.auth().createUser({ -// email: `${testId}@fake-create.com`, -// password: "secret", -// displayName: `${testId}`, -// }); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("authUserOnCreateTests") -// .doc(userRecord.uid) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); - -// userIds.push(userRecord.uid); -// }); - -// afterAll(async () => { -// await admin.auth().deleteUser(userRecord.uid); -// }); - -// it("should perform expected actions", async () => { -// const userProfile = await admin -// .firestore() -// .collection("userProfiles") -// .doc(userRecord.uid) -// .get(); -// expect(userProfile.exists).toBeTruthy(); -// }); - -// it("should have a project as resource", () => { -// expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); -// }); - -// it("should not have a path", () => { -// expect(loggedContext?.path).toBeUndefined(); -// }); - -// it("should have the correct eventType", () => { -// expect(loggedContext?.eventType).toEqual("google.firebase.auth.user.create"); -// }); - -// it("should have an eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have a timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); - -// it("should not have auth", () => { -// expect(loggedContext?.auth).toBeUndefined(); -// }); - -// it("should not have an action", () => { -// expect(loggedContext?.action).toBeUndefined(); -// }); - -// it("should have properly defined metadata", () => { -// const parsedMetadata = JSON.parse(loggedContext?.metadata); -// // TODO: better handle date format mismatch and precision -// const expectedCreationTime = new Date(userRecord.metadata.creationTime) -// .toISOString() -// .replace(/\.\d{3}/, ""); -// const expectedMetadata = { -// ...userRecord.metadata, -// creationTime: expectedCreationTime, -// }; - -// expect(expectedMetadata).toEqual(expect.objectContaining(parsedMetadata)); -// }); -// }); - -// describe("user onDelete trigger", () => { -// let userRecord: admin.auth.UserRecord; -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// userRecord = await admin.auth().createUser({ -// email: `${testId}@fake-delete.com`, -// password: "secret", -// displayName: `${testId}`, -// }); - -// await admin.auth().deleteUser(userRecord.uid); - -// loggedContext = await retry( -// () => -// admin -// .firestore() -// .collection("authUserOnDeleteTests") -// .doc(userRecord.uid) -// .get() -// .then((logSnapshot) => logSnapshot.data()), -// ); - -// userIds.push(userRecord.uid); -// }); - -// it("should have a project as resource", () => { -// expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); -// }); - -// it("should not have a path", () => { -// expect(loggedContext?.path).toBeUndefined(); -// }); - -// it("should have the correct eventType", async () => { -// expect(loggedContext?.eventType).toEqual("google.firebase.auth.user.delete"); -// }); - -// it("should have an eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have a timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); - -// it("should not have auth", () => { -// expect(loggedContext?.auth).toBeUndefined(); -// }); - -// it("should not have an action", () => { -// expect(loggedContext?.action).toBeUndefined(); -// }); -// }); - -// describe("user beforeCreate trigger", () => { -// let userRecord: UserCredential; -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// userRecord = await createUserWithEmailAndPassword( -// getAuth(app), -// `${testId}@fake-before-create.com`, -// "secret" -// ); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("authBeforeCreateTests") -// .doc(userRecord.user.uid) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); - -// userIds.push(userRecord.user.uid); -// }); - -// afterAll(async () => { -// await admin.auth().deleteUser(userRecord.user.uid); -// }); - -// it("should have a project as resource", () => { -// expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); -// }); - -// it("should have the correct eventType", () => { -// expect(loggedContext?.eventType).toEqual( -// "providers/cloud.auth/eventTypes/user.beforeCreate:password" -// ); -// }); - -// it("should have an eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have a timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); -// }); - -// describe("user beforeSignIn trigger", () => { -// let userRecord: UserCredential; -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// userRecord = await createUserWithEmailAndPassword( -// getAuth(app), -// `${testId}@fake-before-signin.com`, -// "secret" -// ); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("authBeforeSignInTests") -// .doc(userRecord.user.uid) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); - -// userIds.push(userRecord.user.uid); - -// if (!loggedContext) { -// throw new Error("loggedContext is undefined"); -// } -// }); - -// afterAll(async () => { -// await admin.auth().deleteUser(userRecord.user.uid); -// }); - -// it("should have a project as resource", () => { -// expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); -// }); - -// it("should have the correct eventType", () => { -// expect(loggedContext?.eventType).toEqual( -// "providers/cloud.auth/eventTypes/user.beforeSignIn:password" -// ); -// }); - -// it("should have an eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have a timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); -// }); -// }); +import * as admin from "firebase-admin"; +import { initializeApp } from "firebase/app"; +import { createUserWithEmailAndPassword, getAuth, UserCredential } from "firebase/auth"; +import { initializeFirebase } from "../firebaseSetup"; +import { retry } from "../utils"; + +describe("Firebase Auth (v1)", () => { + let userIds: string[] = []; + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + const config = { + apiKey: process.env.FIREBASE_API_KEY, + authDomain: process.env.FIREBASE_AUTH_DOMAIN, + databaseURL: process.env.DATABASE_URL, + projectId, + storageBucket: process.env.STORAGE_BUCKET, + appId: process.env.FIREBASE_APP_ID, + measurementId: process.env.FIREBASE_MEASUREMENT_ID, + }; + const app = initializeApp(config); + + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + for (const userId in userIds) { + await admin.firestore().collection("userProfiles").doc(userId).delete(); + await admin.firestore().collection("authUserOnCreateTests").doc(userId).delete(); + await admin.firestore().collection("authUserOnDeleteTests").doc(userId).delete(); + await admin.firestore().collection("authBeforeCreateTests").doc(userId).delete(); + await admin.firestore().collection("authBeforeSignInTests").doc(userId).delete(); + } + }); + + describe("user onCreate trigger", () => { + let userRecord: admin.auth.UserRecord; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + userRecord = await admin.auth().createUser({ + email: `${testId}@fake-create.com`, + password: "secret", + displayName: `${testId}`, + }); + + loggedContext = await retry(() => + admin + .firestore() + .collection("authUserOnCreateTests") + .doc(userRecord.uid) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + + userIds.push(userRecord.uid); + }); + + afterAll(async () => { + await admin.auth().deleteUser(userRecord.uid); + }); + + it("should perform expected actions", async () => { + const userProfile = await admin + .firestore() + .collection("userProfiles") + .doc(userRecord.uid) + .get(); + expect(userProfile.exists).toBeTruthy(); + }); + + it("should have a project as resource", () => { + expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); + }); + + it("should not have a path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.auth.user.create"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have auth", () => { + expect(loggedContext?.auth).toBeUndefined(); + }); + + it("should not have an action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + + it("should have properly defined metadata", () => { + const parsedMetadata = JSON.parse(loggedContext?.metadata); + // TODO: better handle date format mismatch and precision + const expectedCreationTime = new Date(userRecord.metadata.creationTime) + .toISOString() + .replace(/\.\d{3}/, ""); + const expectedMetadata = { + ...userRecord.metadata, + creationTime: expectedCreationTime, + }; + + expect(expectedMetadata).toEqual(expect.objectContaining(parsedMetadata)); + }); + }); + + describe("user onDelete trigger", () => { + let userRecord: admin.auth.UserRecord; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + userRecord = await admin.auth().createUser({ + email: `${testId}@fake-delete.com`, + password: "secret", + displayName: `${testId}`, + }); + + await admin.auth().deleteUser(userRecord.uid); + + loggedContext = await retry( + () => + admin + .firestore() + .collection("authUserOnDeleteTests") + .doc(userRecord.uid) + .get() + .then((logSnapshot) => logSnapshot.data()), + ); + + userIds.push(userRecord.uid); + }); + + it("should have a project as resource", () => { + expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); + }); + + it("should not have a path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the correct eventType", async () => { + expect(loggedContext?.eventType).toEqual("google.firebase.auth.user.delete"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have auth", () => { + expect(loggedContext?.auth).toBeUndefined(); + }); + + it("should not have an action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + }); + + describe("user beforeCreate trigger", () => { + let userRecord: UserCredential; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + userRecord = await createUserWithEmailAndPassword( + getAuth(app), + `${testId}@fake-before-create.com`, + "secret" + ); + + loggedContext = await retry(() => + admin + .firestore() + .collection("authBeforeCreateTests") + .doc(userRecord.user.uid) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + + userIds.push(userRecord.user.uid); + }); + + afterAll(async () => { + await admin.auth().deleteUser(userRecord.user.uid); + }); + + it("should have a project as resource", () => { + expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual( + "providers/cloud.auth/eventTypes/user.beforeCreate:password" + ); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + }); + + describe("user beforeSignIn trigger", () => { + let userRecord: UserCredential; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + userRecord = await createUserWithEmailAndPassword( + getAuth(app), + `${testId}@fake-before-signin.com`, + "secret" + ); + + loggedContext = await retry(() => + admin + .firestore() + .collection("authBeforeSignInTests") + .doc(userRecord.user.uid) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + + userIds.push(userRecord.user.uid); + + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + afterAll(async () => { + await admin.auth().deleteUser(userRecord.user.uid); + }); + + it("should have a project as resource", () => { + expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual( + "providers/cloud.auth/eventTypes/user.beforeSignIn:password" + ); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v1/firestore.test.ts b/integration_test/tests/v1/firestore.test.ts index ee6b8e445..1e3e77c40 100644 --- a/integration_test/tests/v1/firestore.test.ts +++ b/integration_test/tests/v1/firestore.test.ts @@ -1,248 +1,248 @@ -// import * as admin from "firebase-admin"; -// import { initializeFirebase } from "../firebaseSetup"; -// import { retry } from "../utils"; - -// describe("Cloud Firestore (v1)", () => { -// const projectId = process.env.PROJECT_ID; -// const testId = process.env.TEST_RUN_ID; - -// if (!testId || !projectId) { -// throw new Error("Environment configured incorrectly."); -// } - -// beforeAll(async () => { -// await initializeFirebase(); -// }); - -// afterAll(async () => { -// await admin.firestore().collection("firestoreDocumentOnCreateTests").doc(testId).delete(); -// await admin.firestore().collection("firestoreDocumentOnDeleteTests").doc(testId).delete(); -// await admin.firestore().collection("firestoreDocumentOnUpdateTests").doc(testId).delete(); -// await admin.firestore().collection("firestoreDocumentOnWriteTests").doc(testId).delete(); -// }); - -// describe("Document onCreate trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; -// let dataSnapshot: admin.firestore.DocumentSnapshot; -// let docRef: admin.firestore.DocumentReference; - -// beforeAll(async () => { -// docRef = admin.firestore().collection("tests").doc(testId); -// await docRef.set({ test: testId }); -// dataSnapshot = await docRef.get(); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("firestoreDocumentOnCreateTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// afterAll(async () => { -// await admin.firestore().collection("tests").doc(testId).delete(); -// }); - -// it("should not have event.app", () => { -// expect(loggedContext?.app).toBeUndefined(); -// }); - -// it("should give refs access to admin data", async () => { -// const result = await docRef.set({ allowed: 1 }, { merge: true }); -// expect(result).toBeTruthy(); -// }); - -// it("should have well-formed resource", () => { -// expect(loggedContext?.resource.name).toMatch( -// `projects/${projectId}/databases/(default)/documents/tests/${testId}` -// ); -// }); - -// it("should have the correct eventType", () => { -// expect(loggedContext?.eventType).toEqual("google.firestore.document.create"); -// }); - -// it("should have an eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have a timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); - -// it("should have the correct data", () => { -// expect(dataSnapshot.data()).toEqual({ test: testId }); -// }); -// }); - -// describe("Document onDelete trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; -// let dataSnapshot: admin.firestore.DocumentSnapshot; -// let docRef: admin.firestore.DocumentReference; - -// beforeAll(async () => { -// docRef = admin.firestore().collection("tests").doc(testId); -// await docRef.set({ test: testId }); -// dataSnapshot = await docRef.get(); - -// await docRef.delete(); - -// // Refresh snapshot -// dataSnapshot = await docRef.get(); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("firestoreDocumentOnDeleteTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// afterAll(async () => { -// await admin.firestore().collection("tests").doc(testId).delete(); -// }); - -// it("should not have event.app", () => { -// expect(loggedContext?.app).toBeUndefined(); -// }); - -// it("should have well-formed resource", () => { -// expect(loggedContext?.resource.name).toMatch( -// `projects/${projectId}/databases/(default)/documents/tests/${testId}` -// ); -// }); - -// it("should have the correct eventType", () => { -// expect(loggedContext?.eventType).toEqual("google.firestore.document.delete"); -// }); - -// it("should have an eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have a timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); - -// it("should not have the data", () => { -// expect(dataSnapshot.data()).toBeUndefined(); -// }); -// }); - -// describe("Document onUpdate trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; -// let dataSnapshot: admin.firestore.DocumentSnapshot; -// let docRef: admin.firestore.DocumentReference; - -// beforeAll(async () => { -// docRef = admin.firestore().collection("tests").doc(testId); -// await docRef.set({}); -// dataSnapshot = await docRef.get(); - -// await docRef.update({ test: testId }); - -// // Refresh snapshot -// dataSnapshot = await docRef.get(); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("firestoreDocumentOnUpdateTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// afterAll(async () => { -// await admin.firestore().collection("tests").doc(testId).delete(); -// }); - -// it("should not have event.app", () => { -// expect(loggedContext?.app).toBeUndefined(); -// }); - -// it("should have well-formed resource", () => { -// expect(loggedContext?.resource.name).toMatch( -// `projects/${projectId}/databases/(default)/documents/tests/${testId}` -// ); -// }); - -// it("should have the correct eventType", () => { -// expect(loggedContext?.eventType).toEqual("google.firestore.document.update"); -// }); - -// it("should have an eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have a timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); - -// it("should not have the data", () => { -// expect(dataSnapshot.data()).toStrictEqual({ test: testId }); -// }); -// }); - -// describe("Document onWrite trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; -// let dataSnapshot: admin.firestore.DocumentSnapshot; -// let docRef: admin.firestore.DocumentReference; - -// beforeAll(async () => { -// docRef = admin.firestore().collection("tests").doc(testId); -// await docRef.set({ test: testId }); -// dataSnapshot = await docRef.get(); - -// loggedContext = await retry( -// () => -// admin -// .firestore() -// .collection("firestoreDocumentOnWriteTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()), -// ); -// }); - -// afterAll(async () => { -// await admin.firestore().collection("tests").doc(testId).delete(); -// }); - -// it("should not have event.app", () => { -// expect(loggedContext?.app).toBeUndefined(); -// }); - -// it("should give refs access to admin data", async () => { -// const result = await docRef.set({ allowed: 1 }, { merge: true }); -// expect(result).toBeTruthy(); -// }); - -// it("should have well-formed resource", () => { -// expect(loggedContext?.resource.name).toMatch( -// `projects/${projectId}/databases/(default)/documents/tests/${testId}` -// ); -// }); - -// it("should have the correct eventType", () => { -// expect(loggedContext?.eventType).toEqual("google.firestore.document.write"); -// }); - -// it("should have an eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have a timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); - -// it("should have the correct data", () => { -// expect(dataSnapshot.data()).toEqual({ test: testId }); -// }); -// }); -// }); +import * as admin from "firebase-admin"; +import { initializeFirebase } from "../firebaseSetup"; +import { retry } from "../utils"; + +describe("Cloud Firestore (v1)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("firestoreDocumentOnCreateTests").doc(testId).delete(); + await admin.firestore().collection("firestoreDocumentOnDeleteTests").doc(testId).delete(); + await admin.firestore().collection("firestoreDocumentOnUpdateTests").doc(testId).delete(); + await admin.firestore().collection("firestoreDocumentOnWriteTests").doc(testId).delete(); + }); + + describe("Document onCreate trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({ test: testId }); + dataSnapshot = await docRef.get(); + + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreDocumentOnCreateTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + afterAll(async () => { + await admin.firestore().collection("tests").doc(testId).delete(); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + const result = await docRef.set({ allowed: 1 }, { merge: true }); + expect(result).toBeTruthy(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.resource.name).toMatch( + `projects/${projectId}/databases/(default)/documents/tests/${testId}` + ); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firestore.document.create"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should have the correct data", () => { + expect(dataSnapshot.data()).toEqual({ test: testId }); + }); + }); + + describe("Document onDelete trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({ test: testId }); + dataSnapshot = await docRef.get(); + + await docRef.delete(); + + // Refresh snapshot + dataSnapshot = await docRef.get(); + + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreDocumentOnDeleteTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + afterAll(async () => { + await admin.firestore().collection("tests").doc(testId).delete(); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.resource.name).toMatch( + `projects/${projectId}/databases/(default)/documents/tests/${testId}` + ); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firestore.document.delete"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have the data", () => { + expect(dataSnapshot.data()).toBeUndefined(); + }); + }); + + describe("Document onUpdate trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({}); + dataSnapshot = await docRef.get(); + + await docRef.update({ test: testId }); + + // Refresh snapshot + dataSnapshot = await docRef.get(); + + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreDocumentOnUpdateTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + afterAll(async () => { + await admin.firestore().collection("tests").doc(testId).delete(); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.resource.name).toMatch( + `projects/${projectId}/databases/(default)/documents/tests/${testId}` + ); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firestore.document.update"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have the data", () => { + expect(dataSnapshot.data()).toStrictEqual({ test: testId }); + }); + }); + + describe("Document onWrite trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({ test: testId }); + dataSnapshot = await docRef.get(); + + loggedContext = await retry( + () => + admin + .firestore() + .collection("firestoreDocumentOnWriteTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()), + ); + }); + + afterAll(async () => { + await admin.firestore().collection("tests").doc(testId).delete(); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + const result = await docRef.set({ allowed: 1 }, { merge: true }); + expect(result).toBeTruthy(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.resource.name).toMatch( + `projects/${projectId}/databases/(default)/documents/tests/${testId}` + ); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firestore.document.write"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should have the correct data", () => { + expect(dataSnapshot.data()).toEqual({ test: testId }); + }); + }); +}); diff --git a/integration_test/tests/v1/pubsub.test.ts b/integration_test/tests/v1/pubsub.test.ts index ffabd467a..98a0e17c1 100644 --- a/integration_test/tests/v1/pubsub.test.ts +++ b/integration_test/tests/v1/pubsub.test.ts @@ -1,113 +1,121 @@ -// import { PubSub } from "@google-cloud/pubsub"; -// import * as admin from "firebase-admin"; -// import { initializeFirebase } from "../firebaseSetup"; -// import { retry } from "../utils"; - -// describe("Pub/Sub (v1)", () => { -// const projectId = process.env.PROJECT_ID; -// const testId = process.env.TEST_RUN_ID; -// const region = process.env.REGION; -// const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; -// const topicName = `firebase-schedule-${testId}-v1-pubsubScheduleTests-${region}`; - -// if (!testId || !projectId || !region || !serviceAccountPath) { -// throw new Error("Environment configured incorrectly."); -// } - -// beforeAll(async () => { -// await initializeFirebase(); -// }); - -// afterAll(async () => { -// await admin.firestore().collection("pubsubOnPublishTests").doc(testId).delete(); -// await admin.firestore().collection("pubsubScheduleTests").doc(topicName).delete(); -// }); - -// describe("onPublish trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// const serviceAccount = await import(serviceAccountPath); -// const topic = new PubSub({ -// credentials: serviceAccount.default, -// projectId, -// }).topic("pubsubTests"); - -// await topic.publish(Buffer.from(JSON.stringify({ testId }))); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("pubsubOnPublishTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// it("should have a topic as resource", () => { -// expect(loggedContext?.resource.name).toEqual( -// `projects/${process.env.PROJECT_ID}/topics/pubsubTests` -// ); -// }); - -// it("should not have a path", () => { -// expect(loggedContext?.path).toBeUndefined(); -// }); - -// it("should have the correct eventType", () => { -// expect(loggedContext?.eventType).toEqual("google.pubsub.topic.publish"); -// }); - -// it("should have an eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); - -// it("should not have action", () => { -// expect(loggedContext?.action).toBeUndefined(); -// }); - -// it("should have admin auth", () => { -// expect(loggedContext?.auth).toBeUndefined(); -// }); - -// it("should have pubsub data", () => { -// const decodedMessage = JSON.parse(loggedContext?.message); -// const decoded = new Buffer(decodedMessage.data, "base64").toString(); -// const parsed = JSON.parse(decoded); -// expect(parsed.testId).toEqual(testId); -// }); -// }); - -// describe("schedule trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// const pubsub = new PubSub(); - -// const message = Buffer.from(JSON.stringify({ testId })); - -// await pubsub.topic(topicName).publish(message); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("pubsubScheduleTests") -// .doc(topicName) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// if (!loggedContext) { -// throw new Error("loggedContext is undefined"); -// } -// }); - -// it("should have been called", () => { -// expect(loggedContext).toBeDefined(); -// }); -// }); -// }); +import { PubSub } from "@google-cloud/pubsub"; +import * as admin from "firebase-admin"; +import { initializeFirebase } from "../firebaseSetup"; +import { retry } from "../utils"; + +describe("Pub/Sub (v1)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + const region = process.env.REGION; + const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; + const topicName = `firebase-schedule-${testId}-v1-pubsubScheduleTests-${region}`; + + if (!testId || !projectId || !region) { + throw new Error("Environment configured incorrectly."); + } + + if (!serviceAccountPath) { + console.warn("GOOGLE_APPLICATION_CREDENTIALS not set, skipping Pub/Sub tests"); + describe.skip("Pub/Sub (v1)", () => { + it("skipped due to missing credentials", () => {}); + }); + return; + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("pubsubOnPublishTests").doc(testId).delete(); + await admin.firestore().collection("pubsubScheduleTests").doc(topicName).delete(); + }); + + describe("onPublish trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const serviceAccount = await import(serviceAccountPath); + const topic = new PubSub({ + credentials: serviceAccount.default, + projectId, + }).topic("pubsubTests"); + + await topic.publish(Buffer.from(JSON.stringify({ testId }))); + + loggedContext = await retry(() => + admin + .firestore() + .collection("pubsubOnPublishTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + it("should have a topic as resource", () => { + expect(loggedContext?.resource.name).toEqual( + `projects/${process.env.PROJECT_ID}/topics/pubsubTests` + ); + }); + + it("should not have a path", () => { + expect(loggedContext?.path).toBeUndefined(); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual("google.pubsub.topic.publish"); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + + it("should not have action", () => { + expect(loggedContext?.action).toBeUndefined(); + }); + + it("should have admin auth", () => { + expect(loggedContext?.auth).toBeUndefined(); + }); + + it("should have pubsub data", () => { + const decodedMessage = JSON.parse(loggedContext?.message); + const decoded = new Buffer(decodedMessage.data, "base64").toString(); + const parsed = JSON.parse(decoded); + expect(parsed.testId).toEqual(testId); + }); + }); + + describe("schedule trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const pubsub = new PubSub(); + + const message = Buffer.from(JSON.stringify({ testId })); + + await pubsub.topic(topicName).publish(message); + + loggedContext = await retry(() => + admin + .firestore() + .collection("pubsubScheduleTests") + .doc(topicName) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + if (!loggedContext) { + throw new Error("loggedContext is undefined"); + } + }); + + it("should have been called", () => { + expect(loggedContext).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v1/remoteConfig.test.ts b/integration_test/tests/v1/remoteConfig.test.ts index 9f542ab1c..d8f727964 100644 --- a/integration_test/tests/v1/remoteConfig.test.ts +++ b/integration_test/tests/v1/remoteConfig.test.ts @@ -1,72 +1,77 @@ -// import * as admin from "firebase-admin"; -// import { retry } from "../utils"; -// import { initializeFirebase } from "../firebaseSetup"; -// import fetch from "node-fetch"; +import * as admin from "firebase-admin"; +import { retry } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; +import fetch from "node-fetch"; -// describe("Firebase Remote Config (v1)", () => { -// const projectId = process.env.PROJECT_ID; -// const testId = process.env.TEST_RUN_ID; +describe("Firebase Remote Config (v1)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; -// if (!testId || !projectId) { -// throw new Error("Environment configured incorrectly."); -// } + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } -// beforeAll(async () => { -// await initializeFirebase(); -// }); + beforeAll(async () => { + await initializeFirebase(); + }); -// afterAll(async () => { -// await admin.firestore().collection("remoteConfigOnUpdateTests").doc(testId).delete(); -// }); + afterAll(async () => { + await admin.firestore().collection("remoteConfigOnUpdateTests").doc(testId).delete(); + }); -// describe("onUpdate trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; + describe("onUpdate trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; -// beforeAll(async () => { -// const accessToken = await admin.credential.applicationDefault().getAccessToken(); -// const resp = await fetch( -// `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/remoteConfig`, -// { -// method: "PUT", -// headers: { -// Authorization: `Bearer ${accessToken.access_token}`, -// "Content-Type": "application/json; UTF-8", -// "Accept-Encoding": "gzip", -// "If-Match": "*", -// }, -// body: JSON.stringify({ version: { description: testId } }), -// } -// ); -// if (!resp.ok) { -// throw new Error(resp.statusText); -// } -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("remoteConfigOnUpdateTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); + beforeAll(async () => { + try { + const accessToken = await admin.credential.applicationDefault().getAccessToken(); + const resp = await fetch( + `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/remoteConfig`, + { + method: "PUT", + headers: { + Authorization: `Bearer ${accessToken.access_token}`, + "Content-Type": "application/json; UTF-8", + "Accept-Encoding": "gzip", + "If-Match": "*", + }, + body: JSON.stringify({ version: { description: testId } }), + } + ); + if (!resp.ok) { + throw new Error(resp.statusText); + } + loggedContext = await retry(() => + admin + .firestore() + .collection("remoteConfigOnUpdateTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + } catch (error) { + console.warn("RemoteConfig API access failed, skipping test:", (error as Error).message); + (this as any).skip(); + } + }); -// it("should have refs resources", () => -// expect(loggedContext?.resource.name).toMatch(`projects/${process.env.PROJECT_ID}`)); + it("should have refs resources", () => + expect(loggedContext?.resource.name).toMatch(`projects/${process.env.PROJECT_ID}`)); -// it("should have the right eventType", () => { -// expect(loggedContext?.eventType).toEqual("google.firebase.remoteconfig.update"); -// }); + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.firebase.remoteconfig.update"); + }); -// it("should have eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); -// it("should have timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); -// it("should not have auth", () => { -// expect(loggedContext?.auth).toBeUndefined(); -// }); -// }); -// }); + it("should not have auth", () => { + expect(loggedContext?.auth).toBeUndefined(); + }); + }); +}); diff --git a/integration_test/tests/v1/storage.test.ts b/integration_test/tests/v1/storage.test.ts index 2f8e4da33..a868683da 100644 --- a/integration_test/tests/v1/storage.test.ts +++ b/integration_test/tests/v1/storage.test.ts @@ -1,179 +1,191 @@ -// import * as admin from "firebase-admin"; -// import { retry, timeout } from "../utils"; -// import { initializeFirebase } from "../firebaseSetup"; - -// async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { -// const bucket = admin.storage().bucket(); - -// const file = bucket.file(fileName); -// await file.save(buffer, { -// metadata: { -// contentType: "text/plain", -// }, -// }); -// } - -// describe("Firebase Storage", () => { -// const testId = process.env.TEST_RUN_ID; -// if (!testId) { -// throw new Error("Environment configured incorrectly."); -// } - -// beforeAll(async () => { -// await initializeFirebase(); -// }); - -// afterAll(async () => { -// await admin.firestore().collection("storageOnFinalizeTests").doc(testId).delete(); -// await admin.firestore().collection("storageOnDeleteTests").doc(testId).delete(); -// await admin.firestore().collection("storageOnMetadataUpdateTests").doc(testId).delete(); -// }); - -// describe("object onFinalize trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// const testContent = testId; -// const buffer = Buffer.from(testContent, "utf-8"); - -// await uploadBufferToFirebase(buffer, testId + ".txt"); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("storageOnFinalizeTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// afterAll(async () => { -// const file = admin -// .storage() -// .bucket() -// .file(testId + ".txt"); - -// const [exists] = await file.exists(); -// if (exists) { -// await file.delete(); -// } -// }); - -// it("should not have event.app", () => { -// expect(loggedContext?.app).toBeUndefined(); -// }); - -// it("should have the right eventType", () => { -// expect(loggedContext?.eventType).toEqual("google.storage.object.finalize"); -// }); - -// it("should have eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); -// }); - -// // TODO: (b/372315689) Re-enable function once bug is fixed -// describe.skip("object onDelete trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// const testContent = testId; -// const buffer = Buffer.from(testContent, "utf-8"); - -// await uploadBufferToFirebase(buffer, testId + ".txt"); - -// await timeout(5000); // Short delay before delete - -// const file = admin -// .storage() -// .bucket() -// .file(testId + ".txt"); -// await file.delete(); - -// const loggedContext = await retry(() => -// admin -// .firestore() -// .collection("storageOnDeleteTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// it("should not have event.app", () => { -// expect(loggedContext?.app).toBeUndefined(); -// }); - -// it("should have the right eventType", () => { -// expect(loggedContext?.eventType).toEqual("google.storage.object.delete"); -// }); - -// it("should have eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); -// }); - -// describe("object onMetadataUpdate trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// const testContent = testId; -// const buffer = Buffer.from(testContent, "utf-8"); - -// await uploadBufferToFirebase(buffer, testId + ".txt"); - -// // Trigger metadata update -// const file = admin -// .storage() -// .bucket() -// .file(testId + ".txt"); -// await file.setMetadata({ contentType: "application/json" }); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("storageOnMetadataUpdateTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// afterAll(async () => { -// const file = admin -// .storage() -// .bucket() -// .file(testId + ".txt"); - -// const [exists] = await file.exists(); -// if (exists) { -// await file.delete(); -// } -// }); - -// it("should not have event.app", () => { -// expect(loggedContext?.app).toBeUndefined(); -// }); - -// it("should have the right eventType", () => { -// expect(loggedContext?.eventType).toEqual("google.storage.object.metadataUpdate"); -// }); - -// it("should have eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); -// }); -// }); +import * as admin from "firebase-admin"; +import { retry, timeout } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; + +async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { + const bucket = admin.storage().bucket(); + + const file = bucket.file(fileName); + await file.save(buffer, { + metadata: { + contentType: "text/plain", + }, + }); +} + +describe("Firebase Storage", () => { + const testId = process.env.TEST_RUN_ID; + if (!testId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("storageOnFinalizeTests").doc(testId).delete(); + await admin.firestore().collection("storageOnDeleteTests").doc(testId).delete(); + await admin.firestore().collection("storageOnMetadataUpdateTests").doc(testId).delete(); + }); + + describe("object onFinalize trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const testContent = testId; + const buffer = Buffer.from(testContent, "utf-8"); + + await uploadBufferToFirebase(buffer, testId + ".txt"); + + loggedContext = await retry(() => + admin + .firestore() + .collection("storageOnFinalizeTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + afterAll(async () => { + try { + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + + const [exists] = await file.exists(); + if (exists) { + await file.delete(); + } + } catch (error) { + console.warn("Failed to clean up storage file:", (error as Error).message); + } + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.storage.object.finalize"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + }); + + // TODO: (b/372315689) Re-enable function once bug is fixed + describe.skip("object onDelete trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const testContent = testId; + const buffer = Buffer.from(testContent, "utf-8"); + + await uploadBufferToFirebase(buffer, testId + ".txt"); + + await timeout(5000); // Short delay before delete + + try { + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + await file.delete(); + } catch (error) { + console.warn("Failed to delete storage file for onDelete test:", (error as Error).message); + } + + const loggedContext = await retry(() => + admin + .firestore() + .collection("storageOnDeleteTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.storage.object.delete"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + }); + + describe("object onMetadataUpdate trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const testContent = testId; + const buffer = Buffer.from(testContent, "utf-8"); + + await uploadBufferToFirebase(buffer, testId + ".txt"); + + // Trigger metadata update + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + await file.setMetadata({ contentType: "application/json" }); + + loggedContext = await retry(() => + admin + .firestore() + .collection("storageOnMetadataUpdateTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + afterAll(async () => { + try { + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + + const [exists] = await file.exists(); + if (exists) { + await file.delete(); + } + } catch (error) { + console.warn("Failed to clean up storage file:", (error as Error).message); + } + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have the right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.storage.object.metadataUpdate"); + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v1/tasks.test.ts b/integration_test/tests/v1/tasks.test.ts index ec7f41c3a..ac1fb2306 100644 --- a/integration_test/tests/v1/tasks.test.ts +++ b/integration_test/tests/v1/tasks.test.ts @@ -1,44 +1,54 @@ -// import * as admin from "firebase-admin"; -// import { initializeFirebase } from "../firebaseSetup"; -// import { createTask, retry } from "../utils"; - -// describe("Cloud Tasks (v1)", () => { -// const region = process.env.REGION; -// const testId = process.env.TEST_RUN_ID; -// const projectId = process.env.PROJECT_ID; -// const queueName = `${testId}-v1-tasksOnDispatchTests`; - -// if (!testId || !projectId || !region) { -// throw new Error("Environment configured incorrectly."); -// } - -// beforeAll(async () => { -// await initializeFirebase(); -// }); - -// afterAll(async () => { -// await admin.firestore().collection("tasksOnDispatchTests").doc(testId).delete(); -// }); - -// describe("onDispatch trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// const url = `https://${region}-${projectId}.cloudfunctions.net/${testId}-v1-tasksOnDispatchTests`; -// await createTask(projectId, queueName, region, url, { data: { testId } }); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("tasksOnDispatchTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// it("should have correct event id", () => { -// expect(loggedContext?.id).toBeDefined(); -// }); -// }); -// }); +import * as admin from "firebase-admin"; +import { initializeFirebase } from "../firebaseSetup"; +import { createTask, retry } from "../utils"; + +describe("Cloud Tasks (v1)", () => { + const region = process.env.REGION; + const testId = process.env.TEST_RUN_ID; + const projectId = process.env.PROJECT_ID; + const queueName = `${testId}-v1-tasksOnDispatchTests`; + + const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; + + if (!testId || !projectId || !region) { + throw new Error("Environment configured incorrectly."); + } + + if (!serviceAccountPath) { + console.warn("GOOGLE_APPLICATION_CREDENTIALS not set, skipping Tasks tests"); + describe.skip("Cloud Tasks (v1)", () => { + it("skipped due to missing credentials", () => {}); + }); + return; + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("tasksOnDispatchTests").doc(testId).delete(); + }); + + describe("onDispatch trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const url = `https://${region}-${projectId}.cloudfunctions.net/${testId}-v1-tasksOnDispatchTests`; + await createTask(projectId, queueName, region, url, { data: { testId } }); + + loggedContext = await retry(() => + admin + .firestore() + .collection("tasksOnDispatchTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + it("should have correct event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v1/testLab.test.ts b/integration_test/tests/v1/testLab.test.ts index 38532003b..eb963200f 100644 --- a/integration_test/tests/v1/testLab.test.ts +++ b/integration_test/tests/v1/testLab.test.ts @@ -1,51 +1,56 @@ -// import * as admin from "firebase-admin"; -// import { retry, startTestRun } from "../utils"; -// import { initializeFirebase } from "../firebaseSetup"; - -// describe("TestLab (v1)", () => { -// const projectId = process.env.PROJECT_ID; -// const testId = process.env.TEST_RUN_ID; - -// if (!testId || !projectId) { -// throw new Error("Environment configured incorrectly."); -// } - -// beforeAll(async () => { -// await initializeFirebase(); -// }); - -// afterAll(async () => { -// await admin.firestore().collection("testLabOnCompleteTests").doc(testId).delete(); -// }); - -// describe("test matrix onComplete trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// const accessToken = await admin.credential.applicationDefault().getAccessToken(); -// await startTestRun(projectId, testId, accessToken.access_token); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("testLabOnCompleteTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// it("should have eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have right eventType", () => { -// expect(loggedContext?.eventType).toEqual("google.testing.testMatrix.complete"); -// }); - -// it("should be in state 'INVALID'", () => { -// const matrix = JSON.parse(loggedContext?.matrix); -// expect(matrix?.state).toEqual("INVALID"); -// }); -// }); -// }); +import * as admin from "firebase-admin"; +import { retry, startTestRun } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; + +describe("TestLab (v1)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("testLabOnCompleteTests").doc(testId).delete(); + }); + + describe("test matrix onComplete trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + try { + const accessToken = await admin.credential.applicationDefault().getAccessToken(); + await startTestRun(projectId, testId, accessToken.access_token); + + loggedContext = await retry(() => + admin + .firestore() + .collection("testLabOnCompleteTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + } catch (error) { + console.warn("TestLab API access failed, skipping test:", (error as Error).message); + (this as any).skip(); + } + }); + + it("should have eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have right eventType", () => { + expect(loggedContext?.eventType).toEqual("google.testing.testMatrix.complete"); + }); + + it("should be in state 'INVALID'", () => { + const matrix = JSON.parse(loggedContext?.matrix); + expect(matrix?.state).toEqual("INVALID"); + }); + }); +}); diff --git a/integration_test/tests/v2/firestore.test.ts b/integration_test/tests/v2/firestore.test.ts index d61ec6701..4dd80c9d3 100644 --- a/integration_test/tests/v2/firestore.test.ts +++ b/integration_test/tests/v2/firestore.test.ts @@ -1,231 +1,233 @@ -// import * as admin from "firebase-admin"; -// import { retry } from "../utils"; -// import { initializeFirebase } from "../firebaseSetup"; - -// describe("Cloud Firestore (v2)", () => { -// const projectId = process.env.PROJECT_ID; -// const testId = process.env.TEST_RUN_ID; - -// if (!testId || !projectId) { -// throw new Error("Environment configured incorrectly."); -// } - -// beforeAll(async () => { -// await initializeFirebase(); -// }); - -// afterAll(async () => { -// await admin.firestore().collection("firestoreOnDocumentCreatedTests").doc(testId).delete(); -// await admin.firestore().collection("firestoreOnDocumentDeletedTests").doc(testId).delete(); -// await admin.firestore().collection("firestoreOnDocumentUpdatedTests").doc(testId).delete(); -// await admin.firestore().collection("firestoreOnDocumentWrittenTests").doc(testId).delete(); -// }); - -// describe("Document created trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; -// let dataSnapshot: admin.firestore.DocumentSnapshot; -// let docRef: admin.firestore.DocumentReference; - -// beforeAll(async () => { -// docRef = admin.firestore().collection("tests").doc(testId); -// await docRef.set({ test: testId }); -// dataSnapshot = await docRef.get(); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("firestoreOnDocumentCreatedTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// it("should not have event.app", () => { -// expect(loggedContext?.app).toBeUndefined(); -// }); - -// it("should give refs access to admin data", async () => { -// const result = await docRef.set({ allowed: 1 }, { merge: true }); -// expect(result).toBeTruthy(); -// }); - -// it("should have well-formed resource", () => { -// expect(loggedContext?.source).toMatch( -// `//firestore.googleapis.com/projects/${projectId}/databases/(default)` -// ); -// }); - -// it("should have the correct type", () => { -// expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.created"); -// }); - -// it("should have an id", () => { -// expect(loggedContext?.id).toBeDefined(); -// }); - -// it("should have a time", () => { -// expect(loggedContext?.time).toBeDefined(); -// }); - -// it("should have the correct data", () => { -// expect(dataSnapshot.data()).toEqual({ test: testId }); -// }); -// }); - -// describe("Document deleted trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; -// let dataSnapshot: admin.firestore.DocumentSnapshot; -// let docRef: admin.firestore.DocumentReference; - -// beforeAll(async () => { -// docRef = admin.firestore().collection("tests").doc(testId); -// await docRef.set({ test: testId }); -// dataSnapshot = await docRef.get(); - -// await docRef.delete(); - -// // Refresh snapshot -// dataSnapshot = await docRef.get(); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("firestoreOnDocumentDeletedTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// it("should not have event.app", () => { -// expect(loggedContext?.app).toBeUndefined(); -// }); - -// it("should have well-formed source", () => { -// expect(loggedContext?.source).toMatch( -// `//firestore.googleapis.com/projects/${projectId}/databases/(default)` -// ); -// }); - -// it("should have the correct type", () => { -// expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.deleted"); -// }); - -// it("should have an id", () => { -// expect(loggedContext?.id).toBeDefined(); -// }); - -// it("should have a time", () => { -// expect(loggedContext?.time).toBeDefined(); -// }); - -// it("should not have the data", () => { -// expect(dataSnapshot.data()).toBeUndefined(); -// }); -// }); - -// describe("Document updated trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; -// let dataSnapshot: admin.firestore.DocumentSnapshot; -// let docRef: admin.firestore.DocumentReference; - -// beforeAll(async () => { -// docRef = admin.firestore().collection("tests").doc(testId); -// await docRef.set({}); -// dataSnapshot = await docRef.get(); - -// await docRef.update({ test: testId }); - -// // Refresh snapshot -// dataSnapshot = await docRef.get(); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("firestoreOnDocumentUpdatedTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// it("should not have event.app", () => { -// expect(loggedContext?.app).toBeUndefined(); -// }); - -// it("should have well-formed resource", () => { -// expect(loggedContext?.source).toMatch( -// `//firestore.googleapis.com/projects/${projectId}/databases/(default)` -// ); -// }); - -// it("should have the correct type", () => { -// expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.updated"); -// }); - -// it("should have an id", () => { -// expect(loggedContext?.id).toBeDefined(); -// }); - -// it("should have a time", () => { -// expect(loggedContext?.time).toBeDefined(); -// }); - -// it("should have the correct data", () => { -// expect(dataSnapshot.data()).toStrictEqual({ test: testId }); -// }); -// }); - -// describe("Document written trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; -// let dataSnapshot: admin.firestore.DocumentSnapshot; -// let docRef: admin.firestore.DocumentReference; - -// beforeAll(async () => { -// docRef = admin.firestore().collection("tests").doc(testId); -// await docRef.set({ test: testId }); -// dataSnapshot = await docRef.get(); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("firestoreOnDocumentWrittenTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// it("should not have event.app", () => { -// expect(loggedContext?.app).toBeUndefined(); -// }); - -// it("should give refs access to admin data", async () => { -// const result = await docRef.set({ allowed: 1 }, { merge: true }); -// expect(result).toBeTruthy(); -// }); - -// it("should have well-formed resource", () => { -// expect(loggedContext?.source).toMatch( -// `//firestore.googleapis.com/projects/${projectId}/databases/(default)` -// ); -// }); - -// it("should have the correct type", () => { -// expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.written"); -// }); - -// it("should have an id", () => { -// expect(loggedContext?.id).toBeDefined(); -// }); - -// it("should have a time", () => { -// expect(loggedContext?.time).toBeDefined(); -// }); - -// it("should have the correct data", () => { -// expect(dataSnapshot.data()).toEqual({ test: testId }); -// }); -// }); -// }); +import * as admin from "firebase-admin"; +import { retry } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; + +describe("Cloud Firestore (v2)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("firestoreOnDocumentCreatedTests").doc(testId).delete(); + await admin.firestore().collection("firestoreOnDocumentDeletedTests").doc(testId).delete(); + await admin.firestore().collection("firestoreOnDocumentUpdatedTests").doc(testId).delete(); + await admin.firestore().collection("firestoreOnDocumentWrittenTests").doc(testId).delete(); + }); + + describe("Document created trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({ test: testId }); + dataSnapshot = await docRef.get(); + + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreOnDocumentCreatedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + const result = await docRef.set({ allowed: 1 }, { merge: true }); + expect(result).toBeTruthy(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.source).toMatch( + `//firestore.googleapis.com/projects/${projectId}/databases/(default)` + ); + }); + + it("should have the correct type", () => { + expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.created"); + }); + + it("should have an id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + + it("should have the correct data", () => { + expect(dataSnapshot.data()).toEqual({ test: testId }); + }); + }); + + describe("Document deleted trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({ test: testId }); + dataSnapshot = await docRef.get(); + + await docRef.delete(); + + // Refresh snapshot + dataSnapshot = await docRef.get(); + + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreOnDocumentDeletedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have well-formed source", () => { + expect(loggedContext?.source).toMatch( + `//firestore.googleapis.com/projects/${projectId}/databases/(default)` + ); + }); + + it("should have the correct type", () => { + expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.deleted"); + }); + + it("should have an id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + + it("should not have the data", () => { + expect(dataSnapshot.data()).toBeUndefined(); + }); + }); + + describe("Document updated trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({}); + dataSnapshot = await docRef.get(); + + await docRef.update({ test: testId }); + + // Refresh snapshot + dataSnapshot = await docRef.get(); + + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreOnDocumentUpdatedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.source).toMatch( + `//firestore.googleapis.com/projects/${projectId}/databases/(default)` + ); + }); + + it("should have the correct type", () => { + expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.updated"); + }); + + it("should have an id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + + it("should have the correct data", async () => { + // Retry getting the data snapshot to ensure the function has processed + const finalSnapshot = await retry(() => docRef.get()); + expect(finalSnapshot.data()).toStrictEqual({ test: testId }); + }); + }); + + describe("Document written trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + let dataSnapshot: admin.firestore.DocumentSnapshot; + let docRef: admin.firestore.DocumentReference; + + beforeAll(async () => { + docRef = admin.firestore().collection("tests").doc(testId); + await docRef.set({ test: testId }); + dataSnapshot = await docRef.get(); + + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreOnDocumentWrittenTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + it("should not have event.app", () => { + expect(loggedContext?.app).toBeUndefined(); + }); + + it("should give refs access to admin data", async () => { + const result = await docRef.set({ allowed: 1 }, { merge: true }); + expect(result).toBeTruthy(); + }); + + it("should have well-formed resource", () => { + expect(loggedContext?.source).toMatch( + `//firestore.googleapis.com/projects/${projectId}/databases/(default)` + ); + }); + + it("should have the correct type", () => { + expect(loggedContext?.type).toEqual("google.cloud.firestore.document.v1.written"); + }); + + it("should have an id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have a time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + + it("should have the correct data", () => { + expect(dataSnapshot.data()).toEqual({ test: testId }); + }); + }); +}); diff --git a/integration_test/tests/v2/identity.test.ts b/integration_test/tests/v2/identity.test.ts index a5b489b66..86edbd879 100644 --- a/integration_test/tests/v2/identity.test.ts +++ b/integration_test/tests/v2/identity.test.ts @@ -1,130 +1,130 @@ -// import * as admin from "firebase-admin"; -// import { retry } from "../utils"; -// import { initializeApp } from "firebase/app"; -// import { initializeFirebase } from "../firebaseSetup"; -// import { getAuth, createUserWithEmailAndPassword, UserCredential } from "firebase/auth"; - -// describe("Firebase Identity (v2)", () => { -// const userIds: string[] = []; -// const projectId = process.env.PROJECT_ID; -// const testId = process.env.TEST_RUN_ID; -// const config = { -// apiKey: process.env.FIREBASE_API_KEY, -// authDomain: process.env.FIREBASE_AUTH_DOMAIN, -// databaseURL: process.env.DATABASE_URL, -// projectId, -// storageBucket: process.env.STORAGE_BUCKET, -// appId: process.env.FIREBASE_APP_ID, -// measurementId: process.env.FIREBASE_MEASUREMENT_ID, -// }; -// const app = initializeApp(config); - -// if (!testId || !projectId) { -// throw new Error("Environment configured incorrectly."); -// } - -// beforeAll(async () => { -// await initializeFirebase(); -// }); - -// afterAll(async () => { -// for (const userId in userIds) { -// await admin.firestore().collection("userProfiles").doc(userId).delete(); -// await admin.firestore().collection("authUserOnCreateTests").doc(userId).delete(); -// await admin.firestore().collection("authUserOnDeleteTests").doc(userId).delete(); -// await admin.firestore().collection("authBeforeCreateTests").doc(userId).delete(); -// await admin.firestore().collection("authBeforeSignInTests").doc(userId).delete(); -// } -// }); -// describe("beforeUserCreated trigger", () => { -// let userRecord: UserCredential; -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// userRecord = await createUserWithEmailAndPassword( -// getAuth(app), -// `${testId}@fake-create.com`, -// "secret" -// ); - -// userIds.push(userRecord.user.uid); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("identityBeforeUserCreatedTests") -// .doc(userRecord.user.uid) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// afterAll(async () => { -// await admin.auth().deleteUser(userRecord.user.uid); -// }); - -// it("should have a project as resource", () => { -// expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); -// }); - -// it("should have the correct eventType", () => { -// expect(loggedContext?.eventType).toEqual( -// "providers/cloud.auth/eventTypes/user.beforeCreate:password" -// ); -// }); - -// it("should have an eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have a timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); -// }); - -// describe("identityBeforeUserSignedInTests trigger", () => { -// let userRecord: UserCredential; -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// userRecord = await createUserWithEmailAndPassword( -// getAuth(app), -// `${testId}@fake-before-signin.com`, -// "secret" -// ); - -// userIds.push(userRecord.user.uid); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("identityBeforeUserSignedInTests") -// .doc(userRecord.user.uid) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// afterAll(async () => { -// await admin.auth().deleteUser(userRecord.user.uid); -// }); - -// it("should have a project as resource", () => { -// expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); -// }); - -// it("should have the correct eventType", () => { -// expect(loggedContext?.eventType).toEqual( -// "providers/cloud.auth/eventTypes/user.beforeSignIn:password" -// ); -// }); - -// it("should have an eventId", () => { -// expect(loggedContext?.eventId).toBeDefined(); -// }); - -// it("should have a timestamp", () => { -// expect(loggedContext?.timestamp).toBeDefined(); -// }); -// }); -// }); +import * as admin from "firebase-admin"; +import { retry } from "../utils"; +import { initializeApp } from "firebase/app"; +import { initializeFirebase } from "../firebaseSetup"; +import { getAuth, createUserWithEmailAndPassword, UserCredential } from "firebase/auth"; + +describe("Firebase Identity (v2)", () => { + const userIds: string[] = []; + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + const config = { + apiKey: process.env.FIREBASE_API_KEY, + authDomain: process.env.FIREBASE_AUTH_DOMAIN, + databaseURL: process.env.DATABASE_URL, + projectId, + storageBucket: process.env.STORAGE_BUCKET, + appId: process.env.FIREBASE_APP_ID, + measurementId: process.env.FIREBASE_MEASUREMENT_ID, + }; + const app = initializeApp(config); + + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + for (const userId in userIds) { + await admin.firestore().collection("userProfiles").doc(userId).delete(); + await admin.firestore().collection("authUserOnCreateTests").doc(userId).delete(); + await admin.firestore().collection("authUserOnDeleteTests").doc(userId).delete(); + await admin.firestore().collection("authBeforeCreateTests").doc(userId).delete(); + await admin.firestore().collection("authBeforeSignInTests").doc(userId).delete(); + } + }); + describe("beforeUserCreated trigger", () => { + let userRecord: UserCredential; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + userRecord = await createUserWithEmailAndPassword( + getAuth(app), + `${testId}@fake-create.com`, + "secret" + ); + + userIds.push(userRecord.user.uid); + + loggedContext = await retry(() => + admin + .firestore() + .collection("identityBeforeUserCreatedTests") + .doc(userRecord.user.uid) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + afterAll(async () => { + await admin.auth().deleteUser(userRecord.user.uid); + }); + + it("should have a project as resource", () => { + expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual( + "providers/cloud.auth/eventTypes/user.beforeCreate:password" + ); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + }); + + describe("identityBeforeUserSignedInTests trigger", () => { + let userRecord: UserCredential; + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + userRecord = await createUserWithEmailAndPassword( + getAuth(app), + `${testId}@fake-before-signin.com`, + "secret" + ); + + userIds.push(userRecord.user.uid); + + loggedContext = await retry(() => + admin + .firestore() + .collection("identityBeforeUserSignedInTests") + .doc(userRecord.user.uid) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + afterAll(async () => { + await admin.auth().deleteUser(userRecord.user.uid); + }); + + it("should have a project as resource", () => { + expect(loggedContext?.resource.name).toMatch(`projects/${projectId}`); + }); + + it("should have the correct eventType", () => { + expect(loggedContext?.eventType).toEqual( + "providers/cloud.auth/eventTypes/user.beforeSignIn:password" + ); + }); + + it("should have an eventId", () => { + expect(loggedContext?.eventId).toBeDefined(); + }); + + it("should have a timestamp", () => { + expect(loggedContext?.timestamp).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v2/pubsub.test.ts b/integration_test/tests/v2/pubsub.test.ts index d08e3b908..5b21e72cc 100644 --- a/integration_test/tests/v2/pubsub.test.ts +++ b/integration_test/tests/v2/pubsub.test.ts @@ -1,71 +1,79 @@ -// import * as admin from "firebase-admin"; -// import { retry, timeout } from "../utils"; -// import { PubSub } from "@google-cloud/pubsub"; -// import { initializeFirebase } from "../firebaseSetup"; +import * as admin from "firebase-admin"; +import { retry, timeout } from "../utils"; +import { PubSub } from "@google-cloud/pubsub"; +import { initializeFirebase } from "../firebaseSetup"; -// describe("Pub/Sub (v2)", () => { -// const projectId = process.env.PROJECT_ID; -// const testId = process.env.TEST_RUN_ID; -// const region = process.env.REGION; -// const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; +describe("Pub/Sub (v2)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + const region = process.env.REGION; + const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; -// if (!testId || !projectId || !region || !serviceAccountPath) { -// throw new Error("Environment configured incorrectly."); -// } + if (!testId || !projectId || !region) { + throw new Error("Environment configured incorrectly."); + } -// beforeAll(async () => { -// await initializeFirebase(); -// }); + if (!serviceAccountPath) { + console.warn("GOOGLE_APPLICATION_CREDENTIALS not set, skipping Pub/Sub tests"); + describe.skip("Pub/Sub (v2)", () => { + it("skipped due to missing credentials", () => {}); + }); + return; + } -// afterAll(async () => { -// await admin.firestore().collection("pubsubOnMessagePublishedTests").doc(testId).delete(); -// }); + beforeAll(async () => { + await initializeFirebase(); + }); -// describe("onMessagePublished trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; + afterAll(async () => { + await admin.firestore().collection("pubsubOnMessagePublishedTests").doc(testId).delete(); + }); -// beforeAll(async () => { -// const serviceAccount = await import(serviceAccountPath); -// const topic = new PubSub({ -// credentials: serviceAccount.default, -// projectId, -// }).topic("custom_message_tests"); + describe("onMessagePublished trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; -// await topic.publish(Buffer.from(JSON.stringify({ testId }))); + beforeAll(async () => { + const serviceAccount = await import(serviceAccountPath); + const topic = new PubSub({ + credentials: serviceAccount.default, + projectId, + }).topic("custom_message_tests"); -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("pubsubOnMessagePublishedTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); + await topic.publish(Buffer.from(JSON.stringify({ testId }))); -// it("should have a topic as source", () => { -// expect(loggedContext?.source).toEqual( -// `//pubsub.googleapis.com/projects/${projectId}/topics/custom_message_tests` -// ); -// }); + loggedContext = await retry(() => + admin + .firestore() + .collection("pubsubOnMessagePublishedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); -// it("should have the correct event type", () => { -// expect(loggedContext?.type).toEqual("google.cloud.pubsub.topic.v1.messagePublished"); -// }); + it("should have a topic as source", () => { + expect(loggedContext?.source).toEqual( + `//pubsub.googleapis.com/projects/${projectId}/topics/custom_message_tests` + ); + }); -// it("should have an event id", () => { -// expect(loggedContext?.id).toBeDefined(); -// }); + it("should have the correct event type", () => { + expect(loggedContext?.type).toEqual("google.cloud.pubsub.topic.v1.messagePublished"); + }); -// it("should have time", () => { -// expect(loggedContext?.time).toBeDefined(); -// }); + it("should have an event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); -// it("should have pubsub data", () => { -// const decodedMessage = JSON.parse(loggedContext?.message); -// const decoded = new Buffer(decodedMessage.data, "base64").toString(); -// const parsed = JSON.parse(decoded); -// expect(parsed.testId).toEqual(testId); -// }); -// }); -// }); + it("should have time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + + it("should have pubsub data", () => { + const decodedMessage = JSON.parse(loggedContext?.message); + const decoded = new Buffer(decodedMessage.data, "base64").toString(); + const parsed = JSON.parse(decoded); + expect(parsed.testId).toEqual(testId); + }); + }); +}); diff --git a/integration_test/tests/v2/remoteConfig.test.ts b/integration_test/tests/v2/remoteConfig.test.ts index 1679dfd36..eefe18dc1 100644 --- a/integration_test/tests/v2/remoteConfig.test.ts +++ b/integration_test/tests/v2/remoteConfig.test.ts @@ -1,67 +1,72 @@ -// import * as admin from "firebase-admin"; -// import { retry } from "../utils"; -// import { initializeFirebase } from "../firebaseSetup"; -// import fetch from "node-fetch"; +import * as admin from "firebase-admin"; +import { retry } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; +import fetch from "node-fetch"; -// describe("Firebase Remote Config (v2)", () => { -// const projectId = process.env.PROJECT_ID; -// const testId = process.env.TEST_RUN_ID; +describe("Firebase Remote Config (v2)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; -// if (!testId || !projectId) { -// throw new Error("Environment configured incorrectly."); -// } + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } -// beforeAll(async () => { -// await initializeFirebase(); -// }); + beforeAll(async () => { + await initializeFirebase(); + }); -// afterAll(async () => { -// await admin.firestore().collection("remoteConfigOnConfigUpdatedTests").doc(testId).delete(); -// }); + afterAll(async () => { + await admin.firestore().collection("remoteConfigOnConfigUpdatedTests").doc(testId).delete(); + }); -// describe("onUpdated trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; + describe("onUpdated trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; -// beforeAll(async () => { -// const accessToken = await admin.credential.applicationDefault().getAccessToken(); -// const resp = await fetch( -// `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/remoteConfig`, -// { -// method: "PUT", -// headers: { -// Authorization: `Bearer ${accessToken.access_token}`, -// "Content-Type": "application/json; UTF-8", -// "Accept-Encoding": "gzip", -// "If-Match": "*", -// }, -// body: JSON.stringify({ version: { description: testId } }), -// } -// ); -// if (!resp.ok) { -// throw new Error(resp.statusText); -// } + beforeAll(async () => { + try { + const accessToken = await admin.credential.applicationDefault().getAccessToken(); + const resp = await fetch( + `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/remoteConfig`, + { + method: "PUT", + headers: { + Authorization: `Bearer ${accessToken.access_token}`, + "Content-Type": "application/json; UTF-8", + "Accept-Encoding": "gzip", + "If-Match": "*", + }, + body: JSON.stringify({ version: { description: testId } }), + } + ); + if (!resp.ok) { + throw new Error(resp.statusText); + } -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("remoteConfigOnConfigUpdatedTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); + loggedContext = await retry(() => + admin + .firestore() + .collection("remoteConfigOnConfigUpdatedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + } catch (error) { + console.warn("RemoteConfig API access failed, skipping test:", (error as Error).message); + (this as any).skip(); + } + }); -// it("should have the right event type", () => { -// // TODO: not sure if the nested remoteconfig.remoteconfig is expected? -// expect(loggedContext?.type).toEqual("google.firebase.remoteconfig.remoteConfig.v1.updated"); -// }); + it("should have the right event type", () => { + // TODO: not sure if the nested remoteconfig.remoteconfig is expected? + expect(loggedContext?.type).toEqual("google.firebase.remoteconfig.remoteConfig.v1.updated"); + }); -// it("should have event id", () => { -// expect(loggedContext?.id).toBeDefined(); -// }); + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); -// it("should have time", () => { -// expect(loggedContext?.time).toBeDefined(); -// }); -// }); -// }); + it("should have time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v2/scheduler.test.ts b/integration_test/tests/v2/scheduler.test.ts index 561db0236..be7ef371f 100644 --- a/integration_test/tests/v2/scheduler.test.ts +++ b/integration_test/tests/v2/scheduler.test.ts @@ -1,56 +1,57 @@ -// import * as admin from "firebase-admin"; -// import { retry } from "../utils"; -// import { initializeFirebase } from "../firebaseSetup"; - -// describe("Scheduler", () => { -// const projectId = process.env.PROJECT_ID; -// const region = process.env.REGION; -// const testId = process.env.TEST_RUN_ID; - -// if (!testId || !projectId || !region) { -// throw new Error("Environment configured incorrectly."); -// } - -// beforeAll(async () => { -// await initializeFirebase(); -// }); - -// afterAll(async () => { -// await admin.firestore().collection("schedulerOnScheduleV2Tests").doc(testId).delete(); -// }); - -// describe("onSchedule trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// const accessToken = await admin.credential.applicationDefault().getAccessToken(); -// const jobName = `firebase-schedule-${testId}-v2-schedule-${region}`; -// const response = await fetch( -// `https://cloudscheduler.googleapis.com/v1/projects/${projectId}/locations/us-central1/jobs/firebase-schedule-${testId}-v2-schedule-${region}:run`, -// { -// method: "POST", -// headers: { -// "Content-Type": "application/json", -// Authorization: `Bearer ${accessToken.access_token}`, -// }, -// } -// ); -// if (!response.ok) { -// throw new Error(`Failed request with status ${response.status}!`); -// } - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("schedulerOnScheduleV2Tests") -// .doc(jobName) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// it("should trigger when the scheduler fires", () => { -// expect(loggedContext?.success).toBeTruthy(); -// }); -// }); -// }); +import * as admin from "firebase-admin"; +import { retry } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; +import fetch from "node-fetch"; + +describe("Scheduler", () => { + const projectId = process.env.PROJECT_ID; + const region = process.env.REGION; + const testId = process.env.TEST_RUN_ID; + + if (!testId || !projectId || !region) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("schedulerOnScheduleV2Tests").doc(testId).delete(); + }); + + describe("onSchedule trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const accessToken = await admin.credential.applicationDefault().getAccessToken(); + const jobName = `firebase-schedule-${testId}-v2-schedule-${region}`; + const response = await fetch( + `https://cloudscheduler.googleapis.com/v1/projects/${projectId}/locations/us-central1/jobs/firebase-schedule-${testId}-v2-schedule-${region}:run`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${accessToken.access_token}`, + }, + } + ); + if (!response.ok) { + throw new Error(`Failed request with status ${response.status}!`); + } + + loggedContext = await retry(() => + admin + .firestore() + .collection("schedulerOnScheduleV2Tests") + .doc(jobName) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + it("should trigger when the scheduler fires", () => { + expect(loggedContext?.success).toBeTruthy(); + }); + }); +}); diff --git a/integration_test/tests/v2/storage.test.ts b/integration_test/tests/v2/storage.test.ts index 6961ab3cb..341b6ea7d 100644 --- a/integration_test/tests/v2/storage.test.ts +++ b/integration_test/tests/v2/storage.test.ts @@ -1,167 +1,167 @@ -// import * as admin from "firebase-admin"; -// import { initializeFirebase } from "../firebaseSetup"; -// import { retry, timeout } from "../utils"; - -// async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { -// const bucket = admin.storage().bucket(); - -// const file = bucket.file(fileName); -// await file.save(buffer, { -// metadata: { -// contentType: "text/plain", -// }, -// }); -// } - -// describe("Firebase Storage (v2)", () => { -// const testId = process.env.TEST_RUN_ID; - -// if (!testId) { -// throw new Error("Environment configured incorrectly."); -// } - -// beforeAll(async () => { -// await initializeFirebase(); -// }); - -// afterAll(async () => { -// await admin.firestore().collection("storageOnObjectFinalizedTests").doc(testId).delete(); -// await admin.firestore().collection("storageOnObjectDeletedTests").doc(testId).delete(); -// await admin.firestore().collection("storageOnObjectMetadataUpdatedTests").doc(testId).delete(); -// }); - -// describe("onObjectFinalized trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// const testContent = testId; -// const buffer = Buffer.from(testContent, "utf-8"); - -// await uploadBufferToFirebase(buffer, testId + ".txt"); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("storageOnObjectFinalizedTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// afterAll(async () => { -// const file = admin -// .storage() -// .bucket() -// .file(testId + ".txt"); - -// const [exists] = await file.exists(); -// if (exists) { -// await file.delete(); -// } -// }); - -// it("should have the right event type", () => { -// expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.finalized"); -// }); - -// it("should have event id", () => { -// expect(loggedContext?.id).toBeDefined(); -// }); - -// it("should have time", () => { -// expect(loggedContext?.time).toBeDefined(); -// }); -// }); - -// describe("onDeleted trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// const testContent = testId; -// const buffer = Buffer.from(testContent, "utf-8"); - -// await uploadBufferToFirebase(buffer, testId + ".txt"); - -// await timeout(5000); // Short delay before delete - -// const file = admin -// .storage() -// .bucket() -// .file(testId + ".txt"); -// await file.delete(); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("storageOnObjectDeletedTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// it("should have the right event type", () => { -// expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.deleted"); -// }); - -// it("should have event id", () => { -// expect(loggedContext?.id).toBeDefined(); -// }); - -// it("should have time", () => { -// expect(loggedContext?.time).toBeDefined(); -// }); -// }); - -// describe("onMetadataUpdated trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// const testContent = testId; -// const buffer = Buffer.from(testContent, "utf-8"); - -// await uploadBufferToFirebase(buffer, testId + ".txt"); - -// // Trigger metadata update -// const file = admin -// .storage() -// .bucket() -// .file(testId + ".txt"); -// await file.setMetadata({ contentType: "application/json" }); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("storageOnObjectMetadataUpdatedTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// afterAll(async () => { -// const file = admin -// .storage() -// .bucket() -// .file(testId + ".txt"); - -// const [exists] = await file.exists(); -// if (exists) { -// await file.delete(); -// } -// }); - -// it("should have the right event type", () => { -// expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.metadataUpdated"); -// }); - -// it("should have event id", () => { -// expect(loggedContext?.id).toBeDefined(); -// }); - -// it("should have time", () => { -// expect(loggedContext?.time).toBeDefined(); -// }); -// }); -// }); +import * as admin from "firebase-admin"; +import { initializeFirebase } from "../firebaseSetup"; +import { retry, timeout } from "../utils"; + +async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { + const bucket = admin.storage().bucket(); + + const file = bucket.file(fileName); + await file.save(buffer, { + metadata: { + contentType: "text/plain", + }, + }); +} + +describe("Firebase Storage (v2)", () => { + const testId = process.env.TEST_RUN_ID; + + if (!testId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("storageOnObjectFinalizedTests").doc(testId).delete(); + await admin.firestore().collection("storageOnObjectDeletedTests").doc(testId).delete(); + await admin.firestore().collection("storageOnObjectMetadataUpdatedTests").doc(testId).delete(); + }); + + describe("onObjectFinalized trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const testContent = testId; + const buffer = Buffer.from(testContent, "utf-8"); + + await uploadBufferToFirebase(buffer, testId + ".txt"); + + loggedContext = await retry(() => + admin + .firestore() + .collection("storageOnObjectFinalizedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + afterAll(async () => { + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + + const [exists] = await file.exists(); + if (exists) { + await file.delete(); + } + }); + + it("should have the right event type", () => { + expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.finalized"); + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + }); + + describe("onDeleted trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const testContent = testId; + const buffer = Buffer.from(testContent, "utf-8"); + + await uploadBufferToFirebase(buffer, testId + ".txt"); + + await timeout(5000); // Short delay before delete + + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + await file.delete(); + + loggedContext = await retry(() => + admin + .firestore() + .collection("storageOnObjectDeletedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + it("should have the right event type", () => { + expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.deleted"); + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + }); + + describe("onMetadataUpdated trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const testContent = testId; + const buffer = Buffer.from(testContent, "utf-8"); + + await uploadBufferToFirebase(buffer, testId + ".txt"); + + // Trigger metadata update + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + await file.setMetadata({ contentType: "application/json" }); + + loggedContext = await retry(() => + admin + .firestore() + .collection("storageOnObjectMetadataUpdatedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + afterAll(async () => { + const file = admin + .storage() + .bucket() + .file(testId + ".txt"); + + const [exists] = await file.exists(); + if (exists) { + await file.delete(); + } + }); + + it("should have the right event type", () => { + expect(loggedContext?.type).toEqual("google.cloud.storage.object.v1.metadataUpdated"); + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have time", () => { + expect(loggedContext?.time).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v2/tasks.test.ts b/integration_test/tests/v2/tasks.test.ts index 0e0c7664c..fbe01f25d 100644 --- a/integration_test/tests/v2/tasks.test.ts +++ b/integration_test/tests/v2/tasks.test.ts @@ -1,44 +1,54 @@ -// import * as admin from "firebase-admin"; -// import { initializeFirebase } from "../firebaseSetup"; -// import { createTask, retry } from "../utils"; - -// describe("Cloud Tasks (v2)", () => { -// const region = process.env.REGION; -// const testId = process.env.TEST_RUN_ID; -// const projectId = process.env.PROJECT_ID; -// const queueName = `${testId}-v2-tasksOnTaskDispatchedTests`; - -// if (!testId || !projectId || !region) { -// throw new Error("Environment configured incorrectly."); -// } - -// beforeAll(async () => { -// await initializeFirebase(); -// }); - -// afterAll(async () => { -// await admin.firestore().collection("tasksOnTaskDispatchedTests").doc(testId).delete(); -// }); - -// describe("onDispatch trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// const url = `https://${region}-${projectId}.cloudfunctions.net/${testId}-v2-tasksOnTaskDispatchedTests`; -// await createTask(projectId, queueName, region, url, { data: { testId } }); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("tasksOnTaskDispatchedTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// it("should have correct event id", () => { -// expect(loggedContext?.id).toBeDefined(); -// }); -// }); -// }); +import * as admin from "firebase-admin"; +import { initializeFirebase } from "../firebaseSetup"; +import { createTask, retry } from "../utils"; + +describe("Cloud Tasks (v2)", () => { + const region = process.env.REGION; + const testId = process.env.TEST_RUN_ID; + const projectId = process.env.PROJECT_ID; + const queueName = `${testId}-v2-tasksOnTaskDispatchedTests`; + + const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; + + if (!testId || !projectId || !region) { + throw new Error("Environment configured incorrectly."); + } + + if (!serviceAccountPath) { + console.warn("GOOGLE_APPLICATION_CREDENTIALS not set, skipping Tasks tests"); + describe.skip("Cloud Tasks (v2)", () => { + it("skipped due to missing credentials", () => {}); + }); + return; + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("tasksOnTaskDispatchedTests").doc(testId).delete(); + }); + + describe("onDispatch trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + const url = `https://${region}-${projectId}.cloudfunctions.net/${testId}-v2-tasksOnTaskDispatchedTests`; + await createTask(projectId, queueName, region, url, { data: { testId } }); + + loggedContext = await retry(() => + admin + .firestore() + .collection("tasksOnTaskDispatchedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + }); + + it("should have correct event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + }); +}); diff --git a/integration_test/tests/v2/testLab.test.ts b/integration_test/tests/v2/testLab.test.ts index 08310f7fe..19a46df19 100644 --- a/integration_test/tests/v2/testLab.test.ts +++ b/integration_test/tests/v2/testLab.test.ts @@ -1,50 +1,55 @@ -// import * as admin from "firebase-admin"; -// import { retry, startTestRun } from "../utils"; -// import { initializeFirebase } from "../firebaseSetup"; - -// describe("TestLab (v2)", () => { -// const projectId = process.env.PROJECT_ID; -// const testId = process.env.TEST_RUN_ID; - -// if (!testId || !projectId) { -// throw new Error("Environment configured incorrectly."); -// } - -// beforeAll(async () => { -// await initializeFirebase(); -// }); - -// afterAll(async () => { -// await admin.firestore().collection("testLabOnTestMatrixCompletedTests").doc(testId).delete(); -// }); - -// describe("test matrix onComplete trigger", () => { -// let loggedContext: admin.firestore.DocumentData | undefined; - -// beforeAll(async () => { -// const accessToken = await admin.credential.applicationDefault().getAccessToken(); -// await startTestRun(projectId, testId, accessToken.access_token); - -// loggedContext = await retry(() => -// admin -// .firestore() -// .collection("testLabOnTestMatrixCompletedTests") -// .doc(testId) -// .get() -// .then((logSnapshot) => logSnapshot.data()) -// ); -// }); - -// it("should have event id", () => { -// expect(loggedContext?.id).toBeDefined(); -// }); - -// it("should have right event type", () => { -// expect(loggedContext?.type).toEqual("google.firebase.testlab.testMatrix.v1.completed"); -// }); - -// it("should be in state 'INVALID'", () => { -// expect(loggedContext?.state).toEqual("INVALID"); -// }); -// }); -// }); +import * as admin from "firebase-admin"; +import { retry, startTestRun } from "../utils"; +import { initializeFirebase } from "../firebaseSetup"; + +describe("TestLab (v2)", () => { + const projectId = process.env.PROJECT_ID; + const testId = process.env.TEST_RUN_ID; + + if (!testId || !projectId) { + throw new Error("Environment configured incorrectly."); + } + + beforeAll(async () => { + await initializeFirebase(); + }); + + afterAll(async () => { + await admin.firestore().collection("testLabOnTestMatrixCompletedTests").doc(testId).delete(); + }); + + describe("test matrix onComplete trigger", () => { + let loggedContext: admin.firestore.DocumentData | undefined; + + beforeAll(async () => { + try { + const accessToken = await admin.credential.applicationDefault().getAccessToken(); + await startTestRun(projectId, testId, accessToken.access_token); + + loggedContext = await retry(() => + admin + .firestore() + .collection("testLabOnTestMatrixCompletedTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) + ); + } catch (error) { + console.warn("TestLab API access failed, skipping test:", (error as Error).message); + (this as any).skip(); + } + }); + + it("should have event id", () => { + expect(loggedContext?.id).toBeDefined(); + }); + + it("should have right event type", () => { + expect(loggedContext?.type).toEqual("google.firebase.testlab.testMatrix.v1.completed"); + }); + + it("should be in state 'INVALID'", () => { + expect(loggedContext?.state).toEqual("INVALID"); + }); + }); +}); From bf828c0870c62426dd7ae3bdf7b52e2f31f05934 Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Fri, 29 Aug 2025 16:58:36 +0100 Subject: [PATCH 23/25] chore(integration_tests): fix linting errors --- integration_test/.eslintrc.cjs | 48 + integration_test/deployment-utils.ts | 102 +- integration_test/global.d.ts | 12 +- integration_test/package-lock.json | 1104 ++++++++++++++++- integration_test/package.json | 1 + integration_test/run.ts | 10 +- integration_test/setup.ts | 5 +- integration_test/tests/firebaseSetup.ts | 2 +- integration_test/tests/v1/auth.test.ts | 25 +- integration_test/tests/v1/database.test.ts | 13 +- integration_test/tests/v1/firestore.test.ts | 19 +- integration_test/tests/v1/pubsub.test.ts | 8 +- .../tests/v1/remoteConfig.test.ts | 7 +- integration_test/tests/v1/storage.test.ts | 14 +- integration_test/tests/v1/tasks.test.ts | 8 +- integration_test/tests/v1/testLab.test.ts | 7 +- integration_test/tests/v2/database.test.ts | 14 +- integration_test/tests/v2/firestore.test.ts | 9 +- integration_test/tests/v2/identity.test.ts | 19 +- integration_test/tests/v2/pubsub.test.ts | 10 +- .../tests/v2/remoteConfig.test.ts | 16 +- integration_test/tests/v2/scheduler.test.ts | 4 +- integration_test/tests/v2/storage.test.ts | 4 +- integration_test/tests/v2/tasks.test.ts | 8 +- integration_test/tests/v2/testLab.test.ts | 16 +- integration_test/tsconfig.json | 10 +- integration_test/tsconfig.test.json | 3 +- 27 files changed, 1319 insertions(+), 179 deletions(-) create mode 100644 integration_test/.eslintrc.cjs diff --git a/integration_test/.eslintrc.cjs b/integration_test/.eslintrc.cjs new file mode 100644 index 000000000..b503606ab --- /dev/null +++ b/integration_test/.eslintrc.cjs @@ -0,0 +1,48 @@ +module.exports = { + root: true, + env: { + es6: true, + node: true, + jest: true, // This is crucial for Jest globals + }, + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/recommended-requiring-type-checking", + "plugin:jest/recommended", + "prettier", + ], + parser: "@typescript-eslint/parser", + parserOptions: { + project: ["./tsconfig.json", "./tsconfig.test.json"], + tsconfigRootDir: __dirname, + }, + plugins: ["@typescript-eslint", "jest", "prettier"], + rules: { + "prettier/prettier": "error", + "@typescript-eslint/no-unused-vars": "error", + + // Temporarily set these as warnings while we fix them + "@typescript-eslint/no-unsafe-argument": "warn", + "@typescript-eslint/no-unsafe-assignment": "warn", + "@typescript-eslint/no-unsafe-call": "warn", + "@typescript-eslint/no-unsafe-member-access": "warn", + "@typescript-eslint/no-unsafe-return": "warn", + "@typescript-eslint/no-explicit-any": "warn", + }, + overrides: [ + { + files: ["*.test.ts", "*.spec.ts"], + env: { + jest: true, + }, + }, + { + files: ["*.js", "*.cjs"], + rules: { + "@typescript-eslint/no-var-requires": "off", + }, + }, + ], + ignorePatterns: ["dist/", "functions/", "node_modules/"], +}; \ No newline at end of file diff --git a/integration_test/deployment-utils.ts b/integration_test/deployment-utils.ts index 14dc48631..ef63e998a 100644 --- a/integration_test/deployment-utils.ts +++ b/integration_test/deployment-utils.ts @@ -33,13 +33,13 @@ export async function getDeployedFunctions(client: FirebaseClient): Promise fn.name); } catch (error) { logger.warning("Could not list functions, assuming none deployed:", error); - + // Provide more detailed error information - if (error && typeof error === 'object' && 'message' in error) { + if (error && typeof error === "object" && "message" in error) { const errorMessage = String(error.message); logger.debug(" Error message:", errorMessage); - if ('status' in error) logger.debug(" Error status:", error.status); - if ('exit' in error) logger.debug(" Error exit code:", error.exit); - + if ("status" in error) logger.debug(" Error status:", error.status); + if ("exit" in error) logger.debug(" Error exit code:", error.exit); + // Check if it's an authentication error if (errorMessage.includes("not logged in") || errorMessage.includes("authentication")) { - logger.warning("This might be an authentication issue. Try running 'firebase login' first."); + logger.warning( + "This might be an authentication issue. Try running 'firebase login' first." + ); } - + // Check if it's a project access error if (errorMessage.includes("not found") || errorMessage.includes("access")) { - logger.warning("This might be a project access issue. Check if the project ID is correct and you have access to it."); + logger.warning( + "This might be a project access issue. Check if the project ID is correct and you have access to it." + ); } } - + return []; } } @@ -112,9 +116,7 @@ async function deleteFunctionWithRetry( retries: MAX_RETRIES, onFailedAttempt: (error) => { logger.error( - `Failed to delete ${functionName} (attempt ${error.attemptNumber}/${ - MAX_RETRIES + 1 - }):`, + `Failed to delete ${functionName} (attempt ${error.attemptNumber}/${MAX_RETRIES + 1}):`, error.message ); }, @@ -179,42 +181,42 @@ export async function deployFunctionsWithRetry( logger.deployment(`Deploying ${functionsToDeploy.length} functions with rate limiting...`); logger.deployment(`Functions to deploy:`, functionsToDeploy); logger.deployment(`Project ID: ${process.env.PROJECT_ID}`); - logger.deployment(`Region: ${process.env.REGION || 'us-central1'}`); + logger.deployment(`Region: ${process.env.REGION || "us-central1"}`); logger.deployment(`Runtime: ${process.env.TEST_RUNTIME}`); - + // Pre-deployment checks logger.group("Pre-deployment checks"); logger.debug(`- Project ID set: ${!!process.env.PROJECT_ID}`); logger.debug(`- Working directory: ${process.cwd()}`); - + // Import fs dynamically for ES modules - const fs = await import('fs'); - - logger.debug(`- Functions directory exists: ${fs.existsSync('./functions')}`); - logger.debug(`- Functions.yaml exists: ${fs.existsSync('./functions/functions.yaml')}`); - logger.debug(`- Package.json exists: ${fs.existsSync('./functions/package.json')}`); - + const fs = await import("fs"); + + logger.debug(`- Functions directory exists: ${fs.existsSync("./functions")}`); + logger.debug(`- Functions.yaml exists: ${fs.existsSync("./functions/functions.yaml")}`); + logger.debug(`- Package.json exists: ${fs.existsSync("./functions/package.json")}`); + if (!process.env.PROJECT_ID) { throw new Error("PROJECT_ID environment variable is not set"); } - - if (!fs.existsSync('./functions')) { + + if (!fs.existsSync("./functions")) { throw new Error("Functions directory does not exist"); } - - if (!fs.existsSync('./functions/functions.yaml')) { + + if (!fs.existsSync("./functions/functions.yaml")) { throw new Error("functions.yaml file does not exist in functions directory"); } - + // Check functions.yaml content try { - const functionsYaml = fs.readFileSync('./functions/functions.yaml', 'utf8'); + const functionsYaml = fs.readFileSync("./functions/functions.yaml", "utf8"); logger.debug(` - Functions.yaml content preview:`); logger.debug(` ${functionsYaml.substring(0, 200)}...`); } catch (error: any) { logger.warning(` - Error reading functions.yaml: ${error.message}`); } - + // Set up Firebase project configuration logger.debug(` - Setting up Firebase project configuration...`); process.env.FIREBASE_PROJECT = process.env.PROJECT_ID; @@ -241,7 +243,7 @@ export async function deployFunctionsWithRetry( logger.deployment(`Project ID: ${process.env.PROJECT_ID}`); logger.deployment(`Working directory: ${process.cwd()}`); logger.deployment(`Functions source: ${process.cwd()}/functions`); - + const deployOptions = { only: "functions", force: true, @@ -250,9 +252,9 @@ export async function deployFunctionsWithRetry( nonInteractive: true, cwd: process.cwd(), }; - + logger.debug(`Deploy options:`, JSON.stringify(deployOptions, null, 2)); - + try { await client.deploy(deployOptions); logger.success(`Deployment command completed successfully`); @@ -261,13 +263,13 @@ export async function deployFunctionsWithRetry( logger.error(` Error type: ${deployError.constructor.name}`); logger.error(` Error message: ${deployError.message}`); logger.error(` Error stack: ${deployError.stack}`); - + // Log all properties of the error object logger.debug(` Error properties:`); - Object.keys(deployError).forEach(key => { + Object.keys(deployError).forEach((key) => { try { const value = deployError[key]; - if (typeof value === 'object' && value !== null) { + if (typeof value === "object" && value !== null) { logger.debug(` ${key}: ${JSON.stringify(value, null, 4)}`); } else { logger.debug(` ${key}: ${value}`); @@ -276,7 +278,7 @@ export async function deployFunctionsWithRetry( logger.debug(` ${key}: [Error serializing property]`); } }); - + throw deployError; } }); @@ -287,7 +289,7 @@ export async function deployFunctionsWithRetry( logger.error(`Deployment failed (attempt ${error.attemptNumber}/${MAX_RETRIES + 1}):`); logger.error(` Error message: ${error.message}`); logger.error(` Error type: ${error.constructor.name}`); - + // Log detailed error information during retries if (error.children && error.children.length > 0) { logger.debug("Detailed deployment errors:"); @@ -304,7 +306,7 @@ export async function deployFunctionsWithRetry( } }); } - + // Log the full error structure for debugging logger.debug("Full error details:"); logger.debug(` - Message: ${error.message}`); @@ -312,12 +314,12 @@ export async function deployFunctionsWithRetry( logger.debug(` - Exit code: ${error.exit}`); logger.debug(` - Attempt: ${error.attemptNumber}`); logger.debug(` - Retries left: ${error.retriesLeft}`); - + // Log error context if available if (error.context) { logger.debug(` - Context: ${JSON.stringify(error.context, null, 2)}`); } - + // Log error body if available if (error.body) { logger.debug(` - Body: ${JSON.stringify(error.body, null, 2)}`); @@ -338,7 +340,7 @@ export async function deployFunctionsWithRetry( logger.error(` Error type: ${error.constructor.name}`); logger.error(` Error message: ${error.message}`); logger.error(` Error stack: ${error.stack}`); - + // Log detailed error information if (error.children && error.children.length > 0) { logger.debug("Detailed deployment errors:"); @@ -351,7 +353,7 @@ export async function deployFunctionsWithRetry( } }); } - + // Log the full error structure for debugging logger.debug("Final error details:"); logger.debug(` - Message: ${error.message}`); @@ -359,23 +361,23 @@ export async function deployFunctionsWithRetry( logger.debug(` - Exit code: ${error.exit}`); logger.debug(` - Attempt: ${error.attemptNumber}`); logger.debug(` - Retries left: ${error.retriesLeft}`); - + // Log error context if available if (error.context) { logger.debug(` - Context: ${JSON.stringify(error.context, null, 2)}`); } - + // Log error body if available if (error.body) { logger.debug(` - Body: ${JSON.stringify(error.body, null, 2)}`); } - + // Log all error properties logger.debug(` - All error properties:`); - Object.keys(error).forEach(key => { + Object.keys(error).forEach((key) => { try { const value = error[key]; - if (typeof value === 'object' && value !== null) { + if (typeof value === "object" && value !== null) { logger.debug(` ${key}: ${JSON.stringify(value, null, 4)}`); } else { logger.debug(` ${key}: ${value}`); @@ -384,7 +386,7 @@ export async function deployFunctionsWithRetry( logger.debug(` ${key}: [Error serializing property]`); } }); - + throw error; } } diff --git a/integration_test/global.d.ts b/integration_test/global.d.ts index 2fb5e98fb..be5563e55 100644 --- a/integration_test/global.d.ts +++ b/integration_test/global.d.ts @@ -1,13 +1,5 @@ +// / + declare module "firebase-tools"; declare module "firebase-tools/lib/deploy/functions/runtimes/index.js"; declare module "firebase-tools/lib/deploy/functions/runtimes/discovery/index.js"; - -// Jest globals -declare const describe: jest.Describe; -declare const it: jest.It; -declare const test: jest.It; -declare const expect: jest.Expect; -declare const beforeAll: jest.Lifecycle; -declare const afterAll: jest.Lifecycle; -declare const beforeEach: jest.Lifecycle; -declare const afterEach: jest.Lifecycle; diff --git a/integration_test/package-lock.json b/integration_test/package-lock.json index 9643c64d3..4c1e80b97 100644 --- a/integration_test/package-lock.json +++ b/integration_test/package-lock.json @@ -20,6 +20,7 @@ "@types/node-fetch": "^2.6.11", "chalk": "^4.1.2", "dotenv": "^17.2.1", + "eslint-plugin-jest": "^29.0.1", "jest": "^29.7.0", "p-limit": "^6.2.0", "p-retry": "^6.2.1", @@ -587,6 +588,169 @@ "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.2.10.tgz", "integrity": "sha512-0TJF/1ouBweCtyZC4oHwx+dHGn/lP16KfEO/3q22RDuZUsV2saTuYAwb6eK3gBLzVdXG4dj4xZilvmBYEM/WQg==" }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.34.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz", + "integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@fastify/busboy": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.0.0.tgz", @@ -2216,6 +2380,77 @@ "node": ">=6" } }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@inquirer/external-editor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.0.tgz", @@ -2793,6 +3028,44 @@ "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", "license": "MIT" }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@npmcli/fs": { "version": "2.1.2", "license": "ISC", @@ -3077,6 +3350,14 @@ "@types/node": "*" } }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", @@ -3159,7 +3440,9 @@ "dev": true }, "node_modules/@types/json-schema": { - "version": "7.0.14", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "license": "MIT" }, "node_modules/@types/jsonwebtoken": { @@ -3306,6 +3589,177 @@ "dev": true, "license": "MIT" }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.41.0.tgz", + "integrity": "sha512-b8V9SdGBQzQdjJ/IO3eDifGpDBJfvrNTp2QD9P2BeqWTGrRibgfgIlBSw6z3b6R7dPzg752tOs4u/7yCLxksSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.41.0", + "@typescript-eslint/types": "^8.41.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.41.0.tgz", + "integrity": "sha512-n6m05bXn/Cd6DZDGyrpXrELCPVaTnLdPToyhBoFkLIMznRUQUEQdSp96s/pcWSQdqOhrgR1mzJ+yItK7T+WPMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/visitor-keys": "8.41.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.41.0.tgz", + "integrity": "sha512-TDhxYFPUYRFxFhuU5hTIJk+auzM/wKvWgoNYOPcOf6i4ReYlOoYN8q1dV5kOTjNQNJgzWN3TUUQMtlLOcUgdUw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.41.0.tgz", + "integrity": "sha512-9EwxsWdVqh42afLbHP90n2VdHaWU/oWgbH2P0CfcNfdKL7CuKpwMQGjwev56vWu9cSKU7FWSu6r9zck6CVfnag==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.41.0.tgz", + "integrity": "sha512-D43UwUYJmGhuwHfY7MtNKRZMmfd8+p/eNSfFe6tH5mbVDto+VQCayeAt35rOx3Cs6wxD16DQtIKw/YXxt5E0UQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.41.0", + "@typescript-eslint/tsconfig-utils": "8.41.0", + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/visitor-keys": "8.41.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.41.0.tgz", + "integrity": "sha512-udbCVstxZ5jiPIXrdH+BZWnPatjlYwJuJkDA4Tbo3WyYLh8NvB+h/bKeSZHDOFKfphsZYJQqaFtLeXEqurQn1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.41.0", + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/typescript-estree": "8.41.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.41.0.tgz", + "integrity": "sha512-+GeGMebMCy0elMNg67LRNoVnUFPIm37iu5CmHESVx56/9Jsfdpsvbv605DQ81Pi/x11IdKUsS5nzgTYbCQU9fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.41.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/abbrev": { "version": "1.1.1", "license": "ISC", @@ -3336,6 +3790,31 @@ "node": ">= 0.6" } }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/agent-base": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", @@ -5504,31 +5983,280 @@ "version": "3.1.1", "license": "MIT", "engines": { - "node": ">=6" + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "9.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.34.0.tgz", + "integrity": "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.34.0", + "@eslint/plugin-kit": "^0.3.5", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jest": { + "version": "29.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.0.1.tgz", + "integrity": "sha512-EE44T0OSMCeXhDrrdsbKAhprobKkPtJTbQz5yEktysNpHeDZTAL1SfDTNKmcFfJkY6yrQLtTKZALrD3j/Gpmiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.0.0" + }, + "engines": { + "node": "^20.12.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "node_modules/eslint/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, "license": "MIT", + "peer": true, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "license": "MIT", + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, "engines": { - "node": ">=0.8.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esprima": { @@ -5544,6 +6272,34 @@ "node": ">=4" } }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", @@ -5874,12 +6630,37 @@ "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "license": "MIT" }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/fast-xml-parser": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.0.tgz", @@ -5902,6 +6683,16 @@ "fxparser": "src/cli/cli.js" } }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/faye-websocket": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", @@ -5945,6 +6736,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/filesize": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.4.0.tgz", @@ -6381,6 +7186,29 @@ "node": ">=20.0.0" } }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC", + "peer": true + }, "node_modules/fn.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", @@ -7140,6 +7968,46 @@ ], "license": "BSD-3-Clause" }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/import-lazy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", @@ -8452,6 +9320,14 @@ "bignumber.js": "^9.0.0" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -8480,6 +9356,14 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -8599,6 +9483,17 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -8678,6 +9573,21 @@ "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/libsodium": { "version": "0.7.13", "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.13.tgz", @@ -8798,6 +9708,14 @@ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -9087,6 +10005,16 @@ "dev": true, "license": "MIT" }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -9667,6 +10595,25 @@ "yaml": "^2.2.1" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -9857,6 +10804,20 @@ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -10174,6 +11135,17 @@ "node": ">=0.10.0" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -10449,6 +11421,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/queue-tick": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", @@ -10717,6 +11710,17 @@ "node": ">=14" } }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -10767,6 +11771,30 @@ "node": ">=0.12.0" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/rxjs": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", @@ -11725,6 +12753,19 @@ "node": ">= 14.0.0" } }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, "node_modules/ts-jest": { "version": "29.1.1", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", @@ -11798,6 +12839,20 @@ "node": ">=0.6.x" } }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -12215,6 +13270,17 @@ "node": ">= 12.0.0" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/integration_test/package.json b/integration_test/package.json index 3dd6987de..baf49f48f 100644 --- a/integration_test/package.json +++ b/integration_test/package.json @@ -22,6 +22,7 @@ "@types/node-fetch": "^2.6.11", "chalk": "^4.1.2", "dotenv": "^17.2.1", + "eslint-plugin-jest": "^29.0.1", "jest": "^29.7.0", "p-limit": "^6.2.0", "p-retry": "^6.2.1", diff --git a/integration_test/run.ts b/integration_test/run.ts index ca4efc755..62a89a489 100644 --- a/integration_test/run.ts +++ b/integration_test/run.ts @@ -23,7 +23,7 @@ let { FIREBASE_MEASUREMENT_ID, FIREBASE_AUTH_DOMAIN, FIREBASE_API_KEY, - GOOGLE_ANALYTICS_API_SECRET, + // GOOGLE_ANALYTICS_API_SECRET, TEST_RUNTIME, REGION = "us-central1", STORAGE_REGION = "us-central1", @@ -174,7 +174,7 @@ async function deployModifiedFunctions(): Promise { try { // Get the function names that will be deployed const functionNames = modifiedYaml ? Object.keys(modifiedYaml.endpoints) : []; - + logger.deployment("Functions to deploy:", functionNames); logger.deployment(`Total functions to deploy: ${functionNames.length}`); @@ -197,7 +197,7 @@ function cleanFiles(): void { try { const files = fs.readdirSync("."); const deletedFiles: string[] = []; - + files.forEach((file) => { // For Node if (file.match(`firebase-functions-${TEST_RUN_ID}.tgz`)) { @@ -311,7 +311,7 @@ async function runTests(): Promise { logger.info("Test output received:"); logger.debug(output); - + // Check if tests passed if (output.includes("PASS") && !output.includes("FAIL")) { logger.success("All tests completed successfully!"); @@ -319,7 +319,7 @@ async function runTests(): Promise { } else { logger.warning("Some tests may have failed. Check the output above."); } - + logger.info(`${humanReadableRuntime} Tests Completed.`); } catch (error) { logger.error("Error during testing:", error); diff --git a/integration_test/setup.ts b/integration_test/setup.ts index 0dbc217be..aae8da51c 100644 --- a/integration_test/setup.ts +++ b/integration_test/setup.ts @@ -141,10 +141,7 @@ function createRequirementsTxt(firebaseAdmin: string) { `firebase_functions.tar.gz` ); - requirementsContent = requirementsContent.replace( - /__FIREBASE_ADMIN__/g, - firebaseAdmin - ); + requirementsContent = requirementsContent.replace(/__FIREBASE_ADMIN__/g, firebaseAdmin); fs.writeFileSync(requirementsPath, requirementsContent); } diff --git a/integration_test/tests/firebaseSetup.ts b/integration_test/tests/firebaseSetup.ts index 85fc3f4f4..12badd682 100644 --- a/integration_test/tests/firebaseSetup.ts +++ b/integration_test/tests/firebaseSetup.ts @@ -4,7 +4,7 @@ import { logger } from "../src/logger"; /** * Initializes Firebase Admin SDK. */ -export async function initializeFirebase(): Promise { +export function initializeFirebase(): admin.app.App { if (admin.apps.length === 0) { try { // const serviceAccountPath = process.env.GOOGLE_APPLICATION_CREDENTIALS; diff --git a/integration_test/tests/v1/auth.test.ts b/integration_test/tests/v1/auth.test.ts index 3312198b6..9264d283f 100644 --- a/integration_test/tests/v1/auth.test.ts +++ b/integration_test/tests/v1/auth.test.ts @@ -5,7 +5,7 @@ import { initializeFirebase } from "../firebaseSetup"; import { retry } from "../utils"; describe("Firebase Auth (v1)", () => { - let userIds: string[] = []; + const userIds: string[] = []; const projectId = process.env.PROJECT_ID; const testId = process.env.TEST_RUN_ID; const config = { @@ -23,12 +23,12 @@ describe("Firebase Auth (v1)", () => { throw new Error("Environment configured incorrectly."); } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { - for (const userId in userIds) { + for (const userId of userIds) { await admin.firestore().collection("userProfiles").doc(userId).delete(); await admin.firestore().collection("authUserOnCreateTests").doc(userId).delete(); await admin.firestore().collection("authUserOnDeleteTests").doc(userId).delete(); @@ -129,14 +129,13 @@ describe("Firebase Auth (v1)", () => { await admin.auth().deleteUser(userRecord.uid); - loggedContext = await retry( - () => - admin - .firestore() - .collection("authUserOnDeleteTests") - .doc(userRecord.uid) - .get() - .then((logSnapshot) => logSnapshot.data()), + loggedContext = await retry(() => + admin + .firestore() + .collection("authUserOnDeleteTests") + .doc(userRecord.uid) + .get() + .then((logSnapshot) => logSnapshot.data()) ); userIds.push(userRecord.uid); @@ -150,7 +149,7 @@ describe("Firebase Auth (v1)", () => { expect(loggedContext?.path).toBeUndefined(); }); - it("should have the correct eventType", async () => { + it("should have the correct eventType", () => { expect(loggedContext?.eventType).toEqual("google.firebase.auth.user.delete"); }); diff --git a/integration_test/tests/v1/database.test.ts b/integration_test/tests/v1/database.test.ts index bfaf04103..fa4886063 100644 --- a/integration_test/tests/v1/database.test.ts +++ b/integration_test/tests/v1/database.test.ts @@ -12,8 +12,8 @@ describe("Firebase Database (v1)", () => { throw new Error("Environment configured incorrectly."); } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { @@ -39,8 +39,8 @@ describe("Firebase Database (v1)", () => { } } - function getLoggedContext(collectionName: string, testId: string) { - return admin + async function getLoggedContext(collectionName: string, testId: string) { + return await admin .firestore() .collection(collectionName) .doc(testId) @@ -231,8 +231,8 @@ describe("Firebase Database (v1)", () => { expect(loggedContext?.authType).toEqual("ADMIN"); }); - it("should log onUpdate event with updated data", async () => { - const parsedData = JSON.parse(loggedContext?.data ?? {}); + it("should log onUpdate event with updated data", () => { + const parsedData = JSON.parse(loggedContext?.data ?? "{}"); expect(parsedData).toEqual({ updated: true }); }); }); @@ -302,5 +302,4 @@ describe("Firebase Database (v1)", () => { expect(loggedContext?.authType).toEqual("ADMIN"); }); }); - }); diff --git a/integration_test/tests/v1/firestore.test.ts b/integration_test/tests/v1/firestore.test.ts index 1e3e77c40..104ff3552 100644 --- a/integration_test/tests/v1/firestore.test.ts +++ b/integration_test/tests/v1/firestore.test.ts @@ -10,8 +10,8 @@ describe("Cloud Firestore (v1)", () => { throw new Error("Environment configured incorrectly."); } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { @@ -199,14 +199,13 @@ describe("Cloud Firestore (v1)", () => { await docRef.set({ test: testId }); dataSnapshot = await docRef.get(); - loggedContext = await retry( - () => - admin - .firestore() - .collection("firestoreDocumentOnWriteTests") - .doc(testId) - .get() - .then((logSnapshot) => logSnapshot.data()), + loggedContext = await retry(() => + admin + .firestore() + .collection("firestoreDocumentOnWriteTests") + .doc(testId) + .get() + .then((logSnapshot) => logSnapshot.data()) ); }); diff --git a/integration_test/tests/v1/pubsub.test.ts b/integration_test/tests/v1/pubsub.test.ts index 98a0e17c1..dd42cb80c 100644 --- a/integration_test/tests/v1/pubsub.test.ts +++ b/integration_test/tests/v1/pubsub.test.ts @@ -17,13 +17,15 @@ describe("Pub/Sub (v1)", () => { if (!serviceAccountPath) { console.warn("GOOGLE_APPLICATION_CREDENTIALS not set, skipping Pub/Sub tests"); describe.skip("Pub/Sub (v1)", () => { - it("skipped due to missing credentials", () => {}); + it("skipped due to missing credentials", () => { + expect(true).toBe(true); // Placeholder assertion + }); }); return; } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { diff --git a/integration_test/tests/v1/remoteConfig.test.ts b/integration_test/tests/v1/remoteConfig.test.ts index d8f727964..76b78151f 100644 --- a/integration_test/tests/v1/remoteConfig.test.ts +++ b/integration_test/tests/v1/remoteConfig.test.ts @@ -11,8 +11,8 @@ describe("Firebase Remote Config (v1)", () => { throw new Error("Environment configured incorrectly."); } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { @@ -51,7 +51,8 @@ describe("Firebase Remote Config (v1)", () => { ); } catch (error) { console.warn("RemoteConfig API access failed, skipping test:", (error as Error).message); - (this as any).skip(); + // Skip the test suite if RemoteConfig API is not available + return; } }); diff --git a/integration_test/tests/v1/storage.test.ts b/integration_test/tests/v1/storage.test.ts index a868683da..b83869c25 100644 --- a/integration_test/tests/v1/storage.test.ts +++ b/integration_test/tests/v1/storage.test.ts @@ -1,5 +1,5 @@ import * as admin from "firebase-admin"; -import { retry, timeout } from "../utils"; +import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; async function uploadBufferToFirebase(buffer: Buffer, fileName: string) { @@ -19,8 +19,8 @@ describe("Firebase Storage", () => { throw new Error("Environment configured incorrectly."); } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { @@ -81,8 +81,7 @@ describe("Firebase Storage", () => { }); }); - // TODO: (b/372315689) Re-enable function once bug is fixed - describe.skip("object onDelete trigger", () => { + describe("object onDelete trigger", () => { let loggedContext: admin.firestore.DocumentData | undefined; beforeAll(async () => { @@ -91,7 +90,8 @@ describe("Firebase Storage", () => { await uploadBufferToFirebase(buffer, testId + ".txt"); - await timeout(5000); // Short delay before delete + // Short delay before delete to ensure file is properly uploaded + await new Promise((resolve) => setTimeout(resolve, 5000)); try { const file = admin @@ -103,7 +103,7 @@ describe("Firebase Storage", () => { console.warn("Failed to delete storage file for onDelete test:", (error as Error).message); } - const loggedContext = await retry(() => + loggedContext = await retry(() => admin .firestore() .collection("storageOnDeleteTests") diff --git a/integration_test/tests/v1/tasks.test.ts b/integration_test/tests/v1/tasks.test.ts index ac1fb2306..261a357f4 100644 --- a/integration_test/tests/v1/tasks.test.ts +++ b/integration_test/tests/v1/tasks.test.ts @@ -17,13 +17,15 @@ describe("Cloud Tasks (v1)", () => { if (!serviceAccountPath) { console.warn("GOOGLE_APPLICATION_CREDENTIALS not set, skipping Tasks tests"); describe.skip("Cloud Tasks (v1)", () => { - it("skipped due to missing credentials", () => {}); + it("skipped due to missing credentials", () => { + expect(true).toBe(true); // Placeholder assertion + }); }); return; } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { diff --git a/integration_test/tests/v1/testLab.test.ts b/integration_test/tests/v1/testLab.test.ts index eb963200f..cd16e8759 100644 --- a/integration_test/tests/v1/testLab.test.ts +++ b/integration_test/tests/v1/testLab.test.ts @@ -10,8 +10,8 @@ describe("TestLab (v1)", () => { throw new Error("Environment configured incorrectly."); } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { @@ -36,7 +36,8 @@ describe("TestLab (v1)", () => { ); } catch (error) { console.warn("TestLab API access failed, skipping test:", (error as Error).message); - (this as any).skip(); + // Skip the test suite if TestLab API is not available + return; } }); diff --git a/integration_test/tests/v2/database.test.ts b/integration_test/tests/v2/database.test.ts index 96e723d4b..fab34287d 100644 --- a/integration_test/tests/v2/database.test.ts +++ b/integration_test/tests/v2/database.test.ts @@ -12,19 +12,19 @@ describe("Firebase Database (v2)", () => { throw new Error("Environment configured incorrectly."); } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { console.log("🧹 Cleaning up test data..."); const collectionsToClean = [ "databaseCreatedTests", - "databaseDeletedTests", + "databaseDeletedTests", "databaseUpdatesTests", - "databaseWrittenTests" + "databaseWrittenTests", ]; - + for (const collection of collectionsToClean) { try { await admin.firestore().collection(collection).doc(testId).delete(); @@ -167,8 +167,8 @@ describe("Firebase Database (v2)", () => { expect(loggedContext?.time).toBeDefined(); }); - it("should have updated data", async () => { - const parsedData = JSON.parse(loggedContext?.data ?? {}); + it("should have updated data", () => { + const parsedData = JSON.parse(loggedContext?.data ?? "{}"); expect(parsedData).toEqual({ updated: true }); }); }); diff --git a/integration_test/tests/v2/firestore.test.ts b/integration_test/tests/v2/firestore.test.ts index 4dd80c9d3..94e790bb2 100644 --- a/integration_test/tests/v2/firestore.test.ts +++ b/integration_test/tests/v2/firestore.test.ts @@ -10,8 +10,8 @@ describe("Cloud Firestore (v2)", () => { throw new Error("Environment configured incorrectly."); } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { @@ -127,19 +127,14 @@ describe("Cloud Firestore (v2)", () => { describe("Document updated trigger", () => { let loggedContext: admin.firestore.DocumentData | undefined; - let dataSnapshot: admin.firestore.DocumentSnapshot; let docRef: admin.firestore.DocumentReference; beforeAll(async () => { docRef = admin.firestore().collection("tests").doc(testId); await docRef.set({}); - dataSnapshot = await docRef.get(); await docRef.update({ test: testId }); - // Refresh snapshot - dataSnapshot = await docRef.get(); - loggedContext = await retry(() => admin .firestore() diff --git a/integration_test/tests/v2/identity.test.ts b/integration_test/tests/v2/identity.test.ts index 86edbd879..11beb97df 100644 --- a/integration_test/tests/v2/identity.test.ts +++ b/integration_test/tests/v2/identity.test.ts @@ -4,6 +4,15 @@ import { initializeApp } from "firebase/app"; import { initializeFirebase } from "../firebaseSetup"; import { getAuth, createUserWithEmailAndPassword, UserCredential } from "firebase/auth"; +interface IdentityEventContext { + eventId: string; + eventType: string; + timestamp: string; + resource: { + name: string; + }; +} + describe("Firebase Identity (v2)", () => { const userIds: string[] = []; const projectId = process.env.PROJECT_ID; @@ -23,12 +32,12 @@ describe("Firebase Identity (v2)", () => { throw new Error("Environment configured incorrectly."); } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { - for (const userId in userIds) { + for (const userId of userIds) { await admin.firestore().collection("userProfiles").doc(userId).delete(); await admin.firestore().collection("authUserOnCreateTests").doc(userId).delete(); await admin.firestore().collection("authUserOnDeleteTests").doc(userId).delete(); @@ -38,7 +47,7 @@ describe("Firebase Identity (v2)", () => { }); describe("beforeUserCreated trigger", () => { let userRecord: UserCredential; - let loggedContext: admin.firestore.DocumentData | undefined; + let loggedContext: IdentityEventContext | undefined; beforeAll(async () => { userRecord = await createUserWithEmailAndPassword( @@ -55,7 +64,7 @@ describe("Firebase Identity (v2)", () => { .collection("identityBeforeUserCreatedTests") .doc(userRecord.user.uid) .get() - .then((logSnapshot) => logSnapshot.data()) + .then((logSnapshot) => logSnapshot.data() as IdentityEventContext | undefined) ); }); diff --git a/integration_test/tests/v2/pubsub.test.ts b/integration_test/tests/v2/pubsub.test.ts index 5b21e72cc..59609acbb 100644 --- a/integration_test/tests/v2/pubsub.test.ts +++ b/integration_test/tests/v2/pubsub.test.ts @@ -1,5 +1,5 @@ import * as admin from "firebase-admin"; -import { retry, timeout } from "../utils"; +import { retry } from "../utils"; import { PubSub } from "@google-cloud/pubsub"; import { initializeFirebase } from "../firebaseSetup"; @@ -16,13 +16,15 @@ describe("Pub/Sub (v2)", () => { if (!serviceAccountPath) { console.warn("GOOGLE_APPLICATION_CREDENTIALS not set, skipping Pub/Sub tests"); describe.skip("Pub/Sub (v2)", () => { - it("skipped due to missing credentials", () => {}); + it("skipped due to missing credentials", () => { + expect(true).toBe(true); + }); }); return; } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { diff --git a/integration_test/tests/v2/remoteConfig.test.ts b/integration_test/tests/v2/remoteConfig.test.ts index eefe18dc1..ecf3844db 100644 --- a/integration_test/tests/v2/remoteConfig.test.ts +++ b/integration_test/tests/v2/remoteConfig.test.ts @@ -11,8 +11,8 @@ describe("Firebase Remote Config (v2)", () => { throw new Error("Environment configured incorrectly."); } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { @@ -21,6 +21,7 @@ describe("Firebase Remote Config (v2)", () => { describe("onUpdated trigger", () => { let loggedContext: admin.firestore.DocumentData | undefined; + let shouldSkip = false; beforeAll(async () => { try { @@ -52,20 +53,29 @@ describe("Firebase Remote Config (v2)", () => { ); } catch (error) { console.warn("RemoteConfig API access failed, skipping test:", (error as Error).message); - (this as any).skip(); + shouldSkip = true; } }); it("should have the right event type", () => { + if (shouldSkip) { + return; + } // TODO: not sure if the nested remoteconfig.remoteconfig is expected? expect(loggedContext?.type).toEqual("google.firebase.remoteconfig.remoteConfig.v1.updated"); }); it("should have event id", () => { + if (shouldSkip) { + return; // Skip test when API not available + } expect(loggedContext?.id).toBeDefined(); }); it("should have time", () => { + if (shouldSkip) { + return; // Skip test when API not available + } expect(loggedContext?.time).toBeDefined(); }); }); diff --git a/integration_test/tests/v2/scheduler.test.ts b/integration_test/tests/v2/scheduler.test.ts index be7ef371f..1cddd3655 100644 --- a/integration_test/tests/v2/scheduler.test.ts +++ b/integration_test/tests/v2/scheduler.test.ts @@ -12,8 +12,8 @@ describe("Scheduler", () => { throw new Error("Environment configured incorrectly."); } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { diff --git a/integration_test/tests/v2/storage.test.ts b/integration_test/tests/v2/storage.test.ts index 341b6ea7d..765eb24cd 100644 --- a/integration_test/tests/v2/storage.test.ts +++ b/integration_test/tests/v2/storage.test.ts @@ -20,8 +20,8 @@ describe("Firebase Storage (v2)", () => { throw new Error("Environment configured incorrectly."); } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { diff --git a/integration_test/tests/v2/tasks.test.ts b/integration_test/tests/v2/tasks.test.ts index fbe01f25d..e908e8158 100644 --- a/integration_test/tests/v2/tasks.test.ts +++ b/integration_test/tests/v2/tasks.test.ts @@ -17,13 +17,15 @@ describe("Cloud Tasks (v2)", () => { if (!serviceAccountPath) { console.warn("GOOGLE_APPLICATION_CREDENTIALS not set, skipping Tasks tests"); describe.skip("Cloud Tasks (v2)", () => { - it("skipped due to missing credentials", () => {}); + it("skipped due to missing credentials", () => { + expect(true).toBe(true); + }); }); return; } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { diff --git a/integration_test/tests/v2/testLab.test.ts b/integration_test/tests/v2/testLab.test.ts index 19a46df19..267853083 100644 --- a/integration_test/tests/v2/testLab.test.ts +++ b/integration_test/tests/v2/testLab.test.ts @@ -10,8 +10,8 @@ describe("TestLab (v2)", () => { throw new Error("Environment configured incorrectly."); } - beforeAll(async () => { - await initializeFirebase(); + beforeAll(() => { + initializeFirebase(); }); afterAll(async () => { @@ -20,6 +20,7 @@ describe("TestLab (v2)", () => { describe("test matrix onComplete trigger", () => { let loggedContext: admin.firestore.DocumentData | undefined; + let shouldSkip = false; beforeAll(async () => { try { @@ -36,19 +37,28 @@ describe("TestLab (v2)", () => { ); } catch (error) { console.warn("TestLab API access failed, skipping test:", (error as Error).message); - (this as any).skip(); + shouldSkip = true; } }); it("should have event id", () => { + if (shouldSkip) { + return; + } expect(loggedContext?.id).toBeDefined(); }); it("should have right event type", () => { + if (shouldSkip) { + return; + } expect(loggedContext?.type).toEqual("google.firebase.testlab.testMatrix.v1.completed"); }); it("should be in state 'INVALID'", () => { + if (shouldSkip) { + return; + } expect(loggedContext?.state).toEqual("INVALID"); }); }); diff --git a/integration_test/tsconfig.json b/integration_test/tsconfig.json index 9e53c8d71..24dbf56e3 100644 --- a/integration_test/tsconfig.json +++ b/integration_test/tsconfig.json @@ -7,8 +7,10 @@ "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, - "moduleResolution": "node" + "moduleResolution": "node", + "types": ["jest", "node"], + "typeRoots": ["./node_modules/@types"] }, - "include": ["**/*.ts"], - "exclude": ["node_modules", "functions/*", "tests/*"] -} \ No newline at end of file + "include": ["**/*.ts", "**/*.js"], + "exclude": ["node_modules", "functions/*"] +} diff --git a/integration_test/tsconfig.test.json b/integration_test/tsconfig.test.json index e11b8b9bb..1f716e8b0 100644 --- a/integration_test/tsconfig.test.json +++ b/integration_test/tsconfig.test.json @@ -3,7 +3,8 @@ "compilerOptions": { "module": "ES2020", "moduleResolution": "Bundler", - "resolveJsonModule": true + "resolveJsonModule": true, + "types": ["jest", "node"] }, "include": ["**/*.ts"], "exclude": ["node_modules", "functions/*"] From 7d7f856297cb79a36dfbbe96d72c22c6f48d735c Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Fri, 29 Aug 2025 18:33:48 +0100 Subject: [PATCH 24/25] feat: add simple cleanup script --- integration_test/cleanup-functions.sh | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100755 integration_test/cleanup-functions.sh diff --git a/integration_test/cleanup-functions.sh b/integration_test/cleanup-functions.sh new file mode 100755 index 000000000..734aaec56 --- /dev/null +++ b/integration_test/cleanup-functions.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Script to manage Firebase Functions for a specific test run +# Usage: ./cleanup-functions.sh [list|count|delete] + +if [ $# -lt 1 ]; then + echo "Usage: $0 [list|count|delete]" + echo " test_run_id: The test run ID (e.g., t1756484284414)" + echo " action: list (default), count, or delete" + exit 1 +fi + +TEST_RUN_ID="$1" +ACTION="${2:-list}" +PROJECT_ID="functions-integration-tests" + +echo "Managing functions for test run: $TEST_RUN_ID" +echo "Project: $PROJECT_ID" +echo "Action: $ACTION" +echo "---" + +# Extract function names for the test run +FUNCTIONS=$(firebase functions:list --project "$PROJECT_ID" | grep "$TEST_RUN_ID" | cut -d'│' -f2 | sed 's/ //g' | grep -v "^$") + +if [ -z "$FUNCTIONS" ]; then + echo "No functions found for test run ID: $TEST_RUN_ID" + exit 0 +fi + +# Count functions +FUNCTION_COUNT=$(echo "$FUNCTIONS" | wc -l | tr -d ' ') + +case $ACTION in + "list") + echo "Found $FUNCTION_COUNT functions for test run $TEST_RUN_ID:" + echo "$FUNCTIONS" | nl + ;; + "count") + echo "Found $FUNCTION_COUNT functions for test run $TEST_RUN_ID" + ;; + "delete") + echo "Deleting $FUNCTION_COUNT functions for test run $TEST_RUN_ID..." + echo "$FUNCTIONS" | tr '\n' ' ' | xargs firebase functions:delete --project "$PROJECT_ID" --force + echo "Cleanup completed!" + ;; + *) + echo "Invalid action: $ACTION" + echo "Valid actions: list, count, delete" + exit 1 + ;; +esac From 55ba8a6becb04e510546e390e91d8d62cf54bf59 Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Mon, 1 Sep 2025 18:21:36 +0100 Subject: [PATCH 25/25] refactor(integration_test): factor out into smaller modules --- integration_test/deployment-utils.ts | 2 +- integration_test/run.backup.ts | 376 +++++++++++++++++++ integration_test/run.ts | 370 +----------------- integration_test/src/cleanup.ts | 65 ---- integration_test/src/cleanup/files.ts | 73 ++++ integration_test/src/cleanup/functions.ts | 22 ++ integration_test/src/cleanup/index.ts | 35 ++ integration_test/src/config.ts | 142 ------- integration_test/src/config/environment.ts | 103 +++++ integration_test/src/config/firebase.ts | 50 +++ integration_test/src/config/index.ts | 10 + integration_test/src/deployment.ts | 107 ------ integration_test/src/deployment/discovery.ts | 91 +++++ integration_test/src/deployment/functions.ts | 38 ++ integration_test/src/deployment/index.ts | 7 + integration_test/src/index.ts | 61 --- integration_test/src/main.ts | 86 +++++ integration_test/src/process.ts | 67 ---- integration_test/src/run.ts | 6 - integration_test/src/setup/index.ts | 49 +++ integration_test/src/setup/node.ts | 102 +++++ integration_test/src/setup/python.ts | 96 +++++ integration_test/src/testing/index.ts | 5 + integration_test/src/testing/runner.ts | 100 +++++ integration_test/src/{ => utils}/logger.ts | 0 integration_test/src/utils/shell.ts | 110 ++++++ integration_test/src/utils/types.ts | 86 +++++ integration_test/tests/firebaseSetup.ts | 2 +- integration_test/tests/v1/database.test.ts | 2 +- integration_test/tests/v2/database.test.ts | 2 +- 30 files changed, 1449 insertions(+), 816 deletions(-) create mode 100644 integration_test/run.backup.ts delete mode 100644 integration_test/src/cleanup.ts create mode 100644 integration_test/src/cleanup/files.ts create mode 100644 integration_test/src/cleanup/functions.ts create mode 100644 integration_test/src/cleanup/index.ts delete mode 100644 integration_test/src/config.ts create mode 100644 integration_test/src/config/environment.ts create mode 100644 integration_test/src/config/firebase.ts create mode 100644 integration_test/src/config/index.ts delete mode 100644 integration_test/src/deployment.ts create mode 100644 integration_test/src/deployment/discovery.ts create mode 100644 integration_test/src/deployment/functions.ts create mode 100644 integration_test/src/deployment/index.ts delete mode 100644 integration_test/src/index.ts create mode 100644 integration_test/src/main.ts delete mode 100644 integration_test/src/process.ts delete mode 100644 integration_test/src/run.ts create mode 100644 integration_test/src/setup/index.ts create mode 100644 integration_test/src/setup/node.ts create mode 100644 integration_test/src/setup/python.ts create mode 100644 integration_test/src/testing/index.ts create mode 100644 integration_test/src/testing/runner.ts rename integration_test/src/{ => utils}/logger.ts (100%) create mode 100644 integration_test/src/utils/shell.ts create mode 100644 integration_test/src/utils/types.ts diff --git a/integration_test/deployment-utils.ts b/integration_test/deployment-utils.ts index ef63e998a..5891fe8c8 100644 --- a/integration_test/deployment-utils.ts +++ b/integration_test/deployment-utils.ts @@ -1,6 +1,6 @@ import pRetry from "p-retry"; import pLimit from "p-limit"; -import { logger } from "./src/logger.js"; +import { logger } from "./src/utils/logger.js"; interface FirebaseClient { functions: { diff --git a/integration_test/run.backup.ts b/integration_test/run.backup.ts new file mode 100644 index 000000000..36dce4f16 --- /dev/null +++ b/integration_test/run.backup.ts @@ -0,0 +1,376 @@ +import fs from "fs"; +import yaml from "js-yaml"; +import { spawn } from "child_process"; +import portfinder from "portfinder"; +import client from "firebase-tools"; +import { getRuntimeDelegate } from "firebase-tools/lib/deploy/functions/runtimes/index.js"; +import { detectFromPort } from "firebase-tools/lib/deploy/functions/runtimes/discovery/index.js"; +import setup from "./setup.js"; +import * as dotenv from "dotenv"; +import { deployFunctionsWithRetry, postCleanup } from "./deployment-utils.js"; +import { logger } from "./src/utils/logger.js"; + +dotenv.config(); + +let { + DEBUG, + NODE_VERSION = "18", + FIREBASE_ADMIN, + PROJECT_ID, + DATABASE_URL, + STORAGE_BUCKET, + FIREBASE_APP_ID, + FIREBASE_MEASUREMENT_ID, + FIREBASE_AUTH_DOMAIN, + FIREBASE_API_KEY, + // GOOGLE_ANALYTICS_API_SECRET, + TEST_RUNTIME, + REGION = "us-central1", + STORAGE_REGION = "us-central1", +} = process.env; +const TEST_RUN_ID = `t${Date.now()}`; + +if ( + !PROJECT_ID || + !DATABASE_URL || + !STORAGE_BUCKET || + !FIREBASE_APP_ID || + !FIREBASE_MEASUREMENT_ID || + !FIREBASE_AUTH_DOMAIN || + !FIREBASE_API_KEY || + // !GOOGLE_ANALYTICS_API_SECRET || + !TEST_RUNTIME +) { + logger.error("Required environment variables are not set. Exiting..."); + process.exit(1); +} + +if (!["node", "python"].includes(TEST_RUNTIME)) { + logger.error("Invalid TEST_RUNTIME. Must be either 'node' or 'python'. Exiting..."); + process.exit(1); +} + +// TypeScript type guard to ensure TEST_RUNTIME is the correct type +const validRuntimes = ["node", "python"] as const; +type ValidRuntime = (typeof validRuntimes)[number]; +const runtime: ValidRuntime = TEST_RUNTIME as ValidRuntime; + +if (!FIREBASE_ADMIN && runtime === "node") { + FIREBASE_ADMIN = "^12.0.0"; +} else if (!FIREBASE_ADMIN && runtime === "python") { + FIREBASE_ADMIN = "6.5.0"; +} else if (!FIREBASE_ADMIN) { + throw new Error("FIREBASE_ADMIN is not set"); +} + +setup(runtime, TEST_RUN_ID, NODE_VERSION, FIREBASE_ADMIN); + +// Configure Firebase client with project ID +logger.info("Configuring Firebase client with project ID:", PROJECT_ID); +const firebaseClient = client; + +const config = { + projectId: PROJECT_ID, + projectDir: process.cwd(), + sourceDir: `${process.cwd()}/functions`, + runtime: runtime === "node" ? "nodejs18" : "python311", +}; + +logger.debug("Firebase config created: "); +logger.debug(JSON.stringify(config, null, 2)); + +const firebaseConfig = { + databaseURL: DATABASE_URL, + projectId: PROJECT_ID, + storageBucket: STORAGE_BUCKET, +}; + +const env = { + DEBUG, + FIRESTORE_PREFER_REST: "true", + GCLOUD_PROJECT: config.projectId, + FIREBASE_CONFIG: JSON.stringify(firebaseConfig), + REGION, + STORAGE_REGION, +}; + +interface EndpointConfig { + project?: string; + runtime?: string; + [key: string]: unknown; +} + +interface ModifiedYaml { + endpoints: Record; + specVersion: string; +} + +let modifiedYaml: ModifiedYaml | undefined; + +function generateUniqueHash(originalName: string): string { + // Function name can only contain letters, numbers and hyphens and be less than 100 chars. + const modifiedName = `${TEST_RUN_ID}-${originalName}`; + if (modifiedName.length > 100) { + throw new Error( + `Function name is too long. Original=${originalName}, Modified=${modifiedName}` + ); + } + return modifiedName; +} + +/** + * Discovers endpoints and modifies functions.yaml file. + * @returns A promise that resolves with a function to kill the server. + */ +async function discoverAndModifyEndpoints() { + logger.info("Discovering endpoints..."); + try { + const port = await portfinder.getPortPromise({ port: 9000 }); + const delegate = await getRuntimeDelegate(config); + const killServer = await delegate.serveAdmin(port.toString(), {}, env); + + logger.info("Started on port", port); + const originalYaml = (await detectFromPort( + port, + config.projectId, + config.runtime, + 10000 + )) as ModifiedYaml; + + modifiedYaml = { + ...originalYaml, + endpoints: Object.fromEntries( + Object.entries(originalYaml.endpoints).map(([key, value]) => { + const modifiedKey = generateUniqueHash(key); + const modifiedValue: EndpointConfig = { ...value }; + delete modifiedValue.project; + delete modifiedValue.runtime; + return [modifiedKey, modifiedValue]; + }) + ), + specVersion: "v1alpha1", + }; + + writeFunctionsYaml("./functions/functions.yaml", modifiedYaml); + + return killServer; + } catch (err) { + logger.error("Error discovering endpoints. Exiting.", err); + process.exit(1); + } +} + +function writeFunctionsYaml(filePath: string, data: any): void { + try { + fs.writeFileSync(filePath, yaml.dump(data)); + } catch (err) { + logger.error("Error writing functions.yaml. Exiting.", err); + process.exit(1); + } +} + +async function deployModifiedFunctions(): Promise { + logger.deployment(`Deploying functions with id: ${TEST_RUN_ID}`); + try { + // Get the function names that will be deployed + const functionNames = modifiedYaml ? Object.keys(modifiedYaml.endpoints) : []; + + logger.deployment("Functions to deploy:", functionNames); + logger.deployment(`Total functions to deploy: ${functionNames.length}`); + + // Deploy with rate limiting and retry logic + await deployFunctionsWithRetry(firebaseClient, functionNames); + + logger.success("Functions have been deployed successfully."); + logger.info("You can view your deployed functions in the Firebase Console:"); + logger.info(` https://console.firebase.google.com/project/${PROJECT_ID}/functions`); + } catch (err) { + logger.error("Error deploying functions. Exiting.", err); + throw err; + } +} + +function cleanFiles(): void { + logger.cleanup("Cleaning files..."); + const functionsDir = "functions"; + process.chdir(functionsDir); // go to functions + try { + const files = fs.readdirSync("."); + const deletedFiles: string[] = []; + + files.forEach((file) => { + // For Node + if (file.match(`firebase-functions-${TEST_RUN_ID}.tgz`)) { + fs.rmSync(file); + deletedFiles.push(file); + } + // For Python + if (file.match(`firebase_functions.tar.gz`)) { + fs.rmSync(file); + deletedFiles.push(file); + } + if (file.match("package.json")) { + fs.rmSync(file); + deletedFiles.push(file); + } + if (file.match("requirements.txt")) { + fs.rmSync(file); + deletedFiles.push(file); + } + if (file.match("firebase-debug.log")) { + fs.rmSync(file); + deletedFiles.push(file); + } + if (file.match("functions.yaml")) { + fs.rmSync(file); + deletedFiles.push(file); + } + }); + + // Check and delete directories + if (fs.existsSync("lib")) { + fs.rmSync("lib", { recursive: true, force: true }); + deletedFiles.push("lib/ (directory)"); + } + if (fs.existsSync("venv")) { + fs.rmSync("venv", { recursive: true, force: true }); + deletedFiles.push("venv/ (directory)"); + } + + if (deletedFiles.length > 0) { + logger.cleanup(`Deleted ${deletedFiles.length} files/directories:`); + deletedFiles.forEach((file, index) => { + logger.debug(` ${index + 1}. ${file}`); + }); + } else { + logger.info("No files to clean up"); + } + } catch (error) { + logger.error("Error occurred while cleaning files:", error); + } + + process.chdir("../"); // go back to integration_test +} + +const spawnAsync = (command: string, args: string[], options: any): Promise => { + return new Promise((resolve, reject) => { + const child = spawn(command, args, options); + + let output = ""; + let errorOutput = ""; + + if (child.stdout) { + child.stdout.on("data", (data) => { + output += data.toString(); + }); + } + + if (child.stderr) { + child.stderr.on("data", (data) => { + errorOutput += data.toString(); + }); + } + + child.on("error", reject); + + child.on("close", (code) => { + if (code === 0) { + resolve(output); + } else { + const errorMessage = `Command failed with exit code ${code}`; + const fullError = errorOutput ? `${errorMessage}\n\nSTDERR:\n${errorOutput}` : errorMessage; + reject(new Error(fullError)); + } + }); + + // Add timeout to prevent hanging + const timeout = setTimeout(() => { + child.kill(); + reject(new Error(`Command timed out after 5 minutes: ${command} ${args.join(" ")}`)); + }, 5 * 60 * 1000); // 5 minutes + + child.on("close", () => { + clearTimeout(timeout); + }); + }); +}; + +async function runTests(): Promise { + const humanReadableRuntime = TEST_RUNTIME === "node" ? "Node.js" : "Python"; + try { + logger.info(`Starting ${humanReadableRuntime} Tests...`); + logger.info("Running all integration tests"); + + // Run all tests + const output = await spawnAsync("npx", ["jest", "--verbose"], { + env: { + ...process.env, + TEST_RUN_ID, + }, + }); + + logger.info("Test output received:"); + logger.debug(output); + + // Check if tests passed + if (output.includes("PASS") && !output.includes("FAIL")) { + logger.success("All tests completed successfully!"); + logger.success("All function triggers are working correctly."); + } else { + logger.warning("Some tests may have failed. Check the output above."); + } + + logger.info(`${humanReadableRuntime} Tests Completed.`); + } catch (error) { + logger.error("Error during testing:", error); + throw error; + } +} + +async function handleCleanUp(): Promise { + logger.cleanup("Cleaning up..."); + try { + // Use our new post-cleanup utility with rate limiting + await postCleanup(firebaseClient, TEST_RUN_ID); + } catch (err) { + logger.error("Error during post-cleanup:", err); + // Don't throw here to ensure files are still cleaned + } + cleanFiles(); +} + +async function gracefulShutdown(): Promise { + logger.info("SIGINT received..."); + await handleCleanUp(); + process.exit(1); +} + +async function runIntegrationTests(): Promise { + process.on("SIGINT", gracefulShutdown); + + try { + // Skip pre-cleanup for now to test if the main flow works + logger.info("Skipping pre-cleanup for testing..."); + + const killServer = await discoverAndModifyEndpoints(); + await deployModifiedFunctions(); + await killServer(); + await runTests(); + } catch (err) { + logger.error("Error occurred during integration tests:", err); + // Re-throw the original error instead of wrapping it + throw err; + } finally { + await handleCleanUp(); + } +} + +runIntegrationTests() + .then(() => { + logger.success("Integration tests completed"); + process.exit(0); + }) + .catch((error) => { + logger.error("An error occurred during integration tests", error); + process.exit(1); + }); diff --git a/integration_test/run.ts b/integration_test/run.ts index 62a89a489..53ac8fb24 100644 --- a/integration_test/run.ts +++ b/integration_test/run.ts @@ -1,373 +1,15 @@ -import fs from "fs"; -import yaml from "js-yaml"; -import { spawn } from "child_process"; -import portfinder from "portfinder"; -import client from "firebase-tools"; -import { getRuntimeDelegate } from "firebase-tools/lib/deploy/functions/runtimes/index.js"; -import { detectFromPort } from "firebase-tools/lib/deploy/functions/runtimes/discovery/index.js"; -import setup from "./setup.js"; -import * as dotenv from "dotenv"; -import { deployFunctionsWithRetry, postCleanup } from "./deployment-utils.js"; -import { logger } from "./src/logger.js"; - -dotenv.config(); - -let { - DEBUG, - NODE_VERSION = "18", - FIREBASE_ADMIN, - PROJECT_ID, - DATABASE_URL, - STORAGE_BUCKET, - FIREBASE_APP_ID, - FIREBASE_MEASUREMENT_ID, - FIREBASE_AUTH_DOMAIN, - FIREBASE_API_KEY, - // GOOGLE_ANALYTICS_API_SECRET, - TEST_RUNTIME, - REGION = "us-central1", - STORAGE_REGION = "us-central1", -} = process.env; -const TEST_RUN_ID = `t${Date.now()}`; - -if ( - !PROJECT_ID || - !DATABASE_URL || - !STORAGE_BUCKET || - !FIREBASE_APP_ID || - !FIREBASE_MEASUREMENT_ID || - !FIREBASE_AUTH_DOMAIN || - !FIREBASE_API_KEY || - // !GOOGLE_ANALYTICS_API_SECRET || - !TEST_RUNTIME -) { - logger.error("Required environment variables are not set. Exiting..."); - process.exit(1); -} - -if (!["node", "python"].includes(TEST_RUNTIME)) { - logger.error("Invalid TEST_RUNTIME. Must be either 'node' or 'python'. Exiting..."); - process.exit(1); -} - -// TypeScript type guard to ensure TEST_RUNTIME is the correct type -const validRuntimes = ["node", "python"] as const; -type ValidRuntime = (typeof validRuntimes)[number]; -const runtime: ValidRuntime = TEST_RUNTIME as ValidRuntime; - -if (!FIREBASE_ADMIN && runtime === "node") { - FIREBASE_ADMIN = "^12.0.0"; -} else if (!FIREBASE_ADMIN && runtime === "python") { - FIREBASE_ADMIN = "6.5.0"; -} else if (!FIREBASE_ADMIN) { - throw new Error("FIREBASE_ADMIN is not set"); -} - -setup(runtime, TEST_RUN_ID, NODE_VERSION, FIREBASE_ADMIN); - -// Configure Firebase client with project ID -logger.info("Configuring Firebase client with project ID:", PROJECT_ID); -const firebaseClient = client; - -const config = { - projectId: PROJECT_ID, - projectDir: process.cwd(), - sourceDir: `${process.cwd()}/functions`, - runtime: runtime === "node" ? "nodejs18" : "python311", -}; - -logger.debug("Firebase config created: "); -logger.debug(JSON.stringify(config, null, 2)); - -const firebaseConfig = { - databaseURL: DATABASE_URL, - projectId: PROJECT_ID, - storageBucket: STORAGE_BUCKET, -}; - -const env = { - DEBUG, - FIRESTORE_PREFER_REST: "true", - GCLOUD_PROJECT: config.projectId, - FIREBASE_CONFIG: JSON.stringify(firebaseConfig), - REGION, - STORAGE_REGION, -}; - -interface EndpointConfig { - project?: string; - runtime?: string; - [key: string]: unknown; -} - -interface ModifiedYaml { - endpoints: Record; - specVersion: string; -} - -let modifiedYaml: ModifiedYaml | undefined; - -function generateUniqueHash(originalName: string): string { - // Function name can only contain letters, numbers and hyphens and be less than 100 chars. - const modifiedName = `${TEST_RUN_ID}-${originalName}`; - if (modifiedName.length > 100) { - throw new Error( - `Function name is too long. Original=${originalName}, Modified=${modifiedName}` - ); - } - return modifiedName; -} - /** - * Discovers endpoints and modifies functions.yaml file. - * @returns A promise that resolves with a function to kill the server. + * Bootstrap file for integration tests + * The main logic has been refactored into src/main.ts */ -async function discoverAndModifyEndpoints() { - logger.info("Discovering endpoints..."); - try { - const port = await portfinder.getPortPromise({ port: 9000 }); - const delegate = await getRuntimeDelegate(config); - const killServer = await delegate.serveAdmin(port.toString(), {}, env); - - logger.info("Started on port", port); - const originalYaml = (await detectFromPort( - port, - config.projectId, - config.runtime, - 10000 - )) as ModifiedYaml; - - modifiedYaml = { - ...originalYaml, - endpoints: Object.fromEntries( - Object.entries(originalYaml.endpoints).map(([key, value]) => { - const modifiedKey = generateUniqueHash(key); - const modifiedValue: EndpointConfig = { ...value }; - delete modifiedValue.project; - delete modifiedValue.runtime; - return [modifiedKey, modifiedValue]; - }) - ), - specVersion: "v1alpha1", - }; - - writeFunctionsYaml("./functions/functions.yaml", modifiedYaml); - - return killServer; - } catch (err) { - logger.error("Error discovering endpoints. Exiting.", err); - process.exit(1); - } -} - -function writeFunctionsYaml(filePath: string, data: any): void { - try { - fs.writeFileSync(filePath, yaml.dump(data)); - } catch (err) { - logger.error("Error writing functions.yaml. Exiting.", err); - process.exit(1); - } -} - -async function deployModifiedFunctions(): Promise { - logger.deployment(`Deploying functions with id: ${TEST_RUN_ID}`); - try { - // Get the function names that will be deployed - const functionNames = modifiedYaml ? Object.keys(modifiedYaml.endpoints) : []; - - logger.deployment("Functions to deploy:", functionNames); - logger.deployment(`Total functions to deploy: ${functionNames.length}`); - - // Deploy with rate limiting and retry logic - await deployFunctionsWithRetry(firebaseClient, functionNames); - - logger.success("Functions have been deployed successfully."); - logger.info("You can view your deployed functions in the Firebase Console:"); - logger.info(` https://console.firebase.google.com/project/${PROJECT_ID}/functions`); - } catch (err) { - logger.error("Error deploying functions. Exiting.", err); - throw err; - } -} - -function cleanFiles(): void { - logger.cleanup("Cleaning files..."); - const functionsDir = "functions"; - process.chdir(functionsDir); // go to functions - try { - const files = fs.readdirSync("."); - const deletedFiles: string[] = []; - - files.forEach((file) => { - // For Node - if (file.match(`firebase-functions-${TEST_RUN_ID}.tgz`)) { - fs.rmSync(file); - deletedFiles.push(file); - } - // For Python - if (file.match(`firebase_functions.tar.gz`)) { - fs.rmSync(file); - deletedFiles.push(file); - } - if (file.match("package.json")) { - fs.rmSync(file); - deletedFiles.push(file); - } - if (file.match("requirements.txt")) { - fs.rmSync(file); - deletedFiles.push(file); - } - if (file.match("firebase-debug.log")) { - fs.rmSync(file); - deletedFiles.push(file); - } - if (file.match("functions.yaml")) { - fs.rmSync(file); - deletedFiles.push(file); - } - }); - - // Check and delete directories - if (fs.existsSync("lib")) { - fs.rmSync("lib", { recursive: true, force: true }); - deletedFiles.push("lib/ (directory)"); - } - if (fs.existsSync("venv")) { - fs.rmSync("venv", { recursive: true, force: true }); - deletedFiles.push("venv/ (directory)"); - } - - if (deletedFiles.length > 0) { - logger.cleanup(`Deleted ${deletedFiles.length} files/directories:`); - deletedFiles.forEach((file, index) => { - logger.debug(` ${index + 1}. ${file}`); - }); - } else { - logger.info("No files to clean up"); - } - } catch (error) { - logger.error("Error occurred while cleaning files:", error); - } - - process.chdir("../"); // go back to integration_test -} - -const spawnAsync = (command: string, args: string[], options: any): Promise => { - return new Promise((resolve, reject) => { - const child = spawn(command, args, options); - - let output = ""; - let errorOutput = ""; - - if (child.stdout) { - child.stdout.on("data", (data) => { - output += data.toString(); - }); - } - - if (child.stderr) { - child.stderr.on("data", (data) => { - errorOutput += data.toString(); - }); - } - - child.on("error", reject); - - child.on("close", (code) => { - if (code === 0) { - resolve(output); - } else { - const errorMessage = `Command failed with exit code ${code}`; - const fullError = errorOutput ? `${errorMessage}\n\nSTDERR:\n${errorOutput}` : errorMessage; - reject(new Error(fullError)); - } - }); - - // Add timeout to prevent hanging - const timeout = setTimeout(() => { - child.kill(); - reject(new Error(`Command timed out after 5 minutes: ${command} ${args.join(" ")}`)); - }, 5 * 60 * 1000); // 5 minutes - - child.on("close", () => { - clearTimeout(timeout); - }); - }); -}; - -async function runTests(): Promise { - const humanReadableRuntime = TEST_RUNTIME === "node" ? "Node.js" : "Python"; - try { - logger.info(`Starting ${humanReadableRuntime} Tests...`); - logger.info("Running all integration tests"); - - // Run all tests - const output = await spawnAsync("npx", ["jest", "--verbose"], { - env: { - ...process.env, - TEST_RUN_ID, - }, - }); - - logger.info("Test output received:"); - logger.debug(output); - - // Check if tests passed - if (output.includes("PASS") && !output.includes("FAIL")) { - logger.success("All tests completed successfully!"); - logger.success("All function triggers are working correctly."); - } else { - logger.warning("Some tests may have failed. Check the output above."); - } - - logger.info(`${humanReadableRuntime} Tests Completed.`); - } catch (error) { - logger.error("Error during testing:", error); - throw error; - } -} - -async function handleCleanUp(): Promise { - logger.cleanup("Cleaning up..."); - try { - // Use our new post-cleanup utility with rate limiting - await postCleanup(firebaseClient, TEST_RUN_ID); - } catch (err) { - logger.error("Error during post-cleanup:", err); - // Don't throw here to ensure files are still cleaned - } - cleanFiles(); -} - -async function gracefulShutdown(): Promise { - logger.info("SIGINT received..."); - await handleCleanUp(); - process.exit(1); -} - -async function runIntegrationTests(): Promise { - process.on("SIGINT", gracefulShutdown); - - try { - // Skip pre-cleanup for now to test if the main flow works - logger.info("Skipping pre-cleanup for testing..."); - const killServer = await discoverAndModifyEndpoints(); - await deployModifiedFunctions(); - await killServer(); - await runTests(); - } catch (err) { - logger.error("Error occurred during integration tests:", err); - // Re-throw the original error instead of wrapping it - throw err; - } finally { - await handleCleanUp(); - } -} +import runIntegrationTests from "./src/main.js"; +import { logger } from "./src/utils/logger.js"; +// Run the integration tests runIntegrationTests() .then(() => { - logger.success("Integration tests completed"); + logger.success("Integration tests completed successfully"); process.exit(0); }) .catch((error) => { diff --git a/integration_test/src/cleanup.ts b/integration_test/src/cleanup.ts deleted file mode 100644 index fe4737842..000000000 --- a/integration_test/src/cleanup.ts +++ /dev/null @@ -1,65 +0,0 @@ -import fs from "fs"; -import { logError, logCleanup } from "./logger.js"; - -export function cleanFiles(testRunId: string): void { - logCleanup("Cleaning files..."); - const functionsDir = "functions"; - process.chdir(functionsDir); // go to functions - try { - const files = fs.readdirSync("."); - files.forEach((file) => { - // For Node - if (file.match(`firebase-functions-${testRunId}.tgz`)) { - fs.rmSync(file); - } - // For Python - if (file.match(`firebase_functions.tar.gz`)) { - fs.rmSync(file); - } - if (file.match("package.json")) { - fs.rmSync(file); - } - if (file.match("requirements.txt")) { - fs.rmSync(file); - } - if (file.match("firebase-debug.log")) { - fs.rmSync(file); - } - if (file.match("functions.yaml")) { - fs.rmSync(file); - } - }); - - fs.rmSync("lib", { recursive: true, force: true }); - fs.rmSync("venv", { recursive: true, force: true }); - } catch (error) { - logError("Error occurred while cleaning files:", error as Error); - } - - process.chdir("../"); // go back to integration_test -} - -export async function handleCleanUp(client: any, testRunId: string): Promise { - logCleanup("Cleaning up..."); - try { - // Import postCleanup from deployment-utils - const { postCleanup } = await import("../deployment-utils.js"); - await postCleanup(client, testRunId); - } catch (err) { - logError("Error during post-cleanup:", err as Error); - // Don't throw here to ensure files are still cleaned - } - cleanFiles(testRunId); -} - -export function gracefulShutdown(cleanupFn: () => Promise): void { - console.log("SIGINT received..."); - cleanupFn() - .then(() => { - process.exit(1); - }) - .catch((error) => { - logError("Error during graceful shutdown:", error); - process.exit(1); - }); -} diff --git a/integration_test/src/cleanup/files.ts b/integration_test/src/cleanup/files.ts new file mode 100644 index 000000000..b5d5c984d --- /dev/null +++ b/integration_test/src/cleanup/files.ts @@ -0,0 +1,73 @@ +/** + * File system cleanup functionality + */ + +import fs from "fs"; +import { logger } from "../utils/logger.js"; + +/** + * Clean up generated files and directories + */ +export function cleanFiles(testRunId: string): void { + logger.cleanup("Cleaning files..."); + const functionsDir = "functions"; + + process.chdir(functionsDir); // go to functions + + try { + const files = fs.readdirSync("."); + const deletedFiles: string[] = []; + + files.forEach((file) => { + // For Node.js + if (file.match(`firebase-functions-${testRunId}.tgz`)) { + fs.rmSync(file); + deletedFiles.push(file); + } + // For Python + if (file.match("firebase_functions.tar.gz")) { + fs.rmSync(file); + deletedFiles.push(file); + } + if (file.match("package.json")) { + fs.rmSync(file); + deletedFiles.push(file); + } + if (file.match("requirements.txt")) { + fs.rmSync(file); + deletedFiles.push(file); + } + if (file.match("firebase-debug.log")) { + fs.rmSync(file); + deletedFiles.push(file); + } + if (file.match("functions.yaml")) { + fs.rmSync(file); + deletedFiles.push(file); + } + }); + + // Check and delete directories + if (fs.existsSync("lib")) { + fs.rmSync("lib", { recursive: true, force: true }); + deletedFiles.push("lib/ (directory)"); + } + if (fs.existsSync("venv")) { + fs.rmSync("venv", { recursive: true, force: true }); + deletedFiles.push("venv/ (directory)"); + } + + if (deletedFiles.length > 0) { + logger.cleanup(`Deleted ${deletedFiles.length} files/directories:`); + deletedFiles.forEach((file, index) => { + logger.debug(` ${index + 1}. ${file}`); + }); + } else { + logger.info("No files to clean up"); + } + } catch (error) { + logger.error("Error occurred while cleaning files:", error as Error); + } + + process.chdir("../"); // go back to integration_test +} diff --git a/integration_test/src/cleanup/functions.ts b/integration_test/src/cleanup/functions.ts new file mode 100644 index 000000000..5b7d0a2c4 --- /dev/null +++ b/integration_test/src/cleanup/functions.ts @@ -0,0 +1,22 @@ +/** + * Deployed functions cleanup functionality + */ + +import { FirebaseClient } from "../utils/types.js"; +import { logger } from "../utils/logger.js"; +import { postCleanup } from "../../deployment-utils.js"; + +/** + * Clean up deployed test functions + */ +export async function cleanupDeployedFunctions( + client: FirebaseClient, + testRunId: string +): Promise { + try { + await postCleanup(client, testRunId); + } catch (err) { + logger.error("Error during function cleanup:", err as Error); + // Don't throw here to ensure files are still cleaned + } +} diff --git a/integration_test/src/cleanup/index.ts b/integration_test/src/cleanup/index.ts new file mode 100644 index 000000000..9c4376293 --- /dev/null +++ b/integration_test/src/cleanup/index.ts @@ -0,0 +1,35 @@ +/** + * Cleanup module orchestration + */ + +import { FirebaseClient } from "../utils/types.js"; +import { logger } from "../utils/logger.js"; +import { cleanFiles } from "./files.js"; +import { cleanupDeployedFunctions } from "./functions.js"; + +/** + * Handle all cleanup operations + */ +export async function handleCleanUp(client: FirebaseClient, testRunId: string): Promise { + logger.cleanup("Starting cleanup..."); + + // Clean up deployed functions first + await cleanupDeployedFunctions(client, testRunId); + + // Then clean up local files + cleanFiles(testRunId); + + logger.success("Cleanup completed"); +} + +/** + * Graceful shutdown handler + */ +export async function gracefulShutdown(cleanupFn: () => Promise): Promise { + logger.info("SIGINT received, initiating graceful shutdown..."); + await cleanupFn(); + process.exit(1); +} + +export { cleanFiles } from "./files.js"; +export { cleanupDeployedFunctions } from "./functions.js"; diff --git a/integration_test/src/config.ts b/integration_test/src/config.ts deleted file mode 100644 index ed1edc78a..000000000 --- a/integration_test/src/config.ts +++ /dev/null @@ -1,142 +0,0 @@ -import * as z from "zod/mini"; - -// Load English locale for better error messages -z.config(z.locales.en()); - -export interface TestConfig { - projectId: string; - testRunId: string; - runtime: "node" | "python"; - nodeVersion: string; - firebaseAdmin: string; - region: string; - storageRegion: string; - debug?: string; - databaseUrl: string; - storageBucket: string; - firebaseAppId: string; - firebaseMeasurementId: string; - firebaseAuthDomain: string; - firebaseApiKey: string; - googleAnalyticsApiSecret: string; -} - -// Environment validation schema -const environmentSchema = z.object({ - PROJECT_ID: z.string().check(z.minLength(1, "PROJECT_ID is required")), - DATABASE_URL: z.string().check(z.minLength(1, "DATABASE_URL is required")), - STORAGE_BUCKET: z.string().check(z.minLength(1, "STORAGE_BUCKET is required")), - FIREBASE_APP_ID: z.string().check(z.minLength(1, "FIREBASE_APP_ID is required")), - FIREBASE_MEASUREMENT_ID: z.string().check(z.minLength(1, "FIREBASE_MEASUREMENT_ID is required")), - FIREBASE_AUTH_DOMAIN: z.string().check(z.minLength(1, "FIREBASE_AUTH_DOMAIN is required")), - FIREBASE_API_KEY: z.string().check(z.minLength(1, "FIREBASE_API_KEY is required")), - GOOGLE_ANALYTICS_API_SECRET: z - .string() - .check(z.minLength(1, "GOOGLE_ANALYTICS_API_SECRET is required")), - TEST_RUNTIME: z.enum(["node", "python"]), - NODE_VERSION: z.optional(z.string()), - FIREBASE_ADMIN: z.optional(z.string()), - REGION: z.optional(z.string()), - STORAGE_REGION: z.optional(z.string()), - DEBUG: z.optional(z.string()), -}); - -/** - * Validates that all required environment variables are set and have valid values. - * Exits the process with code 1 if validation fails. - */ -export function validateEnvironment(): void { - try { - environmentSchema.parse(process.env); - } catch (error) { - console.error("Environment validation failed:"); - if (error && typeof error === "object" && "errors" in error) { - const zodError = error as { errors: Array<{ path: string[]; message: string }> }; - zodError.errors.forEach((err) => { - console.error(` ${err.path.join(".")}: ${err.message}`); - }); - } else { - console.error("Unexpected error during environment validation:", error); - } - process.exit(1); - } -} - -/** - * Loads and validates environment configuration, returning a typed config object. - * @returns TestConfig object with all validated environment variables - */ -export function loadConfig(): TestConfig { - // Validate environment first to ensure all required variables are set - const validatedEnv = environmentSchema.parse(process.env); - - // TypeScript type guard to ensure TEST_RUNTIME is the correct type - const validRuntimes = ["node", "python"] as const; - type ValidRuntime = (typeof validRuntimes)[number]; - const runtime: ValidRuntime = validatedEnv.TEST_RUNTIME; - - let firebaseAdmin = validatedEnv.FIREBASE_ADMIN; - if (!firebaseAdmin && runtime === "node") { - firebaseAdmin = "^12.0.0"; - } else if (!firebaseAdmin && runtime === "python") { - firebaseAdmin = "6.5.0"; - } else if (!firebaseAdmin) { - throw new Error("FIREBASE_ADMIN is not set"); - } - - const testRunId = `t${Date.now()}`; - - return { - projectId: validatedEnv.PROJECT_ID, - testRunId, - runtime, - nodeVersion: validatedEnv.NODE_VERSION ?? "18", - firebaseAdmin, - region: validatedEnv.REGION ?? "us-central1", - storageRegion: validatedEnv.STORAGE_REGION ?? "us-central1", - debug: validatedEnv.DEBUG, - databaseUrl: validatedEnv.DATABASE_URL, - storageBucket: validatedEnv.STORAGE_BUCKET, - firebaseAppId: validatedEnv.FIREBASE_APP_ID, - firebaseMeasurementId: validatedEnv.FIREBASE_MEASUREMENT_ID, - firebaseAuthDomain: validatedEnv.FIREBASE_AUTH_DOMAIN, - firebaseApiKey: validatedEnv.FIREBASE_API_KEY, - googleAnalyticsApiSecret: validatedEnv.GOOGLE_ANALYTICS_API_SECRET, - }; -} - -/** - * Creates Firebase configuration object for deployment. - * @param config - The test configuration object - * @returns Firebase configuration object - */ -export function createFirebaseConfig(config: TestConfig) { - return { - projectId: config.projectId, - projectDir: process.cwd(), - sourceDir: `${process.cwd()}/functions`, - runtime: config.runtime === "node" ? "nodejs18" : "python311", - }; -} - -/** - * Creates environment configuration for function deployment. - * @param config - The test configuration object - * @returns Environment configuration object - */ -export function createEnvironmentConfig(config: TestConfig) { - const firebaseConfig = { - databaseURL: config.databaseUrl, - projectId: config.projectId, - storageBucket: config.storageBucket, - }; - - return { - DEBUG: config.debug, - FIRESTORE_PREFER_REST: "true", - GCLOUD_PROJECT: config.projectId, - FIREBASE_CONFIG: JSON.stringify(firebaseConfig), - REGION: config.region, - STORAGE_REGION: config.storageRegion, - }; -} diff --git a/integration_test/src/config/environment.ts b/integration_test/src/config/environment.ts new file mode 100644 index 000000000..fedaa693a --- /dev/null +++ b/integration_test/src/config/environment.ts @@ -0,0 +1,103 @@ +/** + * Environment variable validation and loading + */ + +import { TestConfig, ValidRuntime, VALID_RUNTIMES } from "../utils/types.js"; +import { logger } from "../utils/logger.js"; + +interface EnvironmentVariables { + PROJECT_ID: string; + DATABASE_URL: string; + STORAGE_BUCKET: string; + FIREBASE_APP_ID: string; + FIREBASE_MEASUREMENT_ID: string; + FIREBASE_AUTH_DOMAIN: string; + FIREBASE_API_KEY: string; + TEST_RUNTIME: string; + NODE_VERSION?: string; + FIREBASE_ADMIN?: string; + REGION?: string; + STORAGE_REGION?: string; + DEBUG?: string; +} + +/** + * Validates that all required environment variables are set + * @throws Error if validation fails + */ +export function validateEnvironment(): EnvironmentVariables { + const required = [ + "PROJECT_ID", + "DATABASE_URL", + "STORAGE_BUCKET", + "FIREBASE_APP_ID", + "FIREBASE_MEASUREMENT_ID", + "FIREBASE_AUTH_DOMAIN", + "FIREBASE_API_KEY", + // "GOOGLE_ANALYTICS_API_SECRET", // Commented out like in original + "TEST_RUNTIME", + ]; + + const missing = required.filter((key) => !process.env[key]); + + if (missing.length > 0) { + logger.error(`Required environment variables are missing: ${missing.join(", ")}`); + process.exit(1); + } + + const testRuntime = process.env.TEST_RUNTIME as string; + if (!VALID_RUNTIMES.includes(testRuntime as ValidRuntime)) { + logger.error(`Invalid TEST_RUNTIME: ${testRuntime}. Must be either 'node' or 'python'.`); + process.exit(1); + } + + return { + PROJECT_ID: process.env.PROJECT_ID!, + DATABASE_URL: process.env.DATABASE_URL!, + STORAGE_BUCKET: process.env.STORAGE_BUCKET!, + FIREBASE_APP_ID: process.env.FIREBASE_APP_ID!, + FIREBASE_MEASUREMENT_ID: process.env.FIREBASE_MEASUREMENT_ID!, + FIREBASE_AUTH_DOMAIN: process.env.FIREBASE_AUTH_DOMAIN!, + FIREBASE_API_KEY: process.env.FIREBASE_API_KEY!, + TEST_RUNTIME: testRuntime, + NODE_VERSION: process.env.NODE_VERSION, + FIREBASE_ADMIN: process.env.FIREBASE_ADMIN, + REGION: process.env.REGION, + STORAGE_REGION: process.env.STORAGE_REGION, + DEBUG: process.env.DEBUG, + }; +} + +/** + * Loads and validates environment configuration + * @returns TestConfig object with all validated environment variables + */ +export function loadTestConfig(): TestConfig { + const env = validateEnvironment(); + const runtime = env.TEST_RUNTIME as ValidRuntime; + + // Determine Firebase Admin version based on runtime + let firebaseAdmin = env.FIREBASE_ADMIN; + if (!firebaseAdmin) { + firebaseAdmin = runtime === "node" ? "^12.0.0" : "6.5.0"; + } + + const testRunId = `t${Date.now()}`; + + return { + projectId: env.PROJECT_ID, + testRunId, + runtime, + nodeVersion: env.NODE_VERSION || "18", + firebaseAdmin, + region: env.REGION || "us-central1", + storageRegion: env.STORAGE_REGION || "us-central1", + debug: env.DEBUG, + databaseUrl: env.DATABASE_URL, + storageBucket: env.STORAGE_BUCKET, + firebaseAppId: env.FIREBASE_APP_ID, + firebaseMeasurementId: env.FIREBASE_MEASUREMENT_ID, + firebaseAuthDomain: env.FIREBASE_AUTH_DOMAIN, + firebaseApiKey: env.FIREBASE_API_KEY, + }; +} diff --git a/integration_test/src/config/firebase.ts b/integration_test/src/config/firebase.ts new file mode 100644 index 000000000..b973c42f5 --- /dev/null +++ b/integration_test/src/config/firebase.ts @@ -0,0 +1,50 @@ +/** + * Firebase-specific configuration + */ + +import { + TestConfig, + FirebaseConfig, + FirebaseProjectConfig, + EnvironmentConfig, +} from "../utils/types.js"; + +/** + * Creates Firebase configuration from test config + */ +export function createFirebaseConfig(config: TestConfig): FirebaseConfig { + return { + databaseURL: config.databaseUrl, + projectId: config.projectId, + storageBucket: config.storageBucket, + }; +} + +/** + * Creates Firebase project configuration for deployment + */ +export function createFirebaseProjectConfig(config: TestConfig): FirebaseProjectConfig { + return { + projectId: config.projectId, + projectDir: process.cwd(), + sourceDir: `${process.cwd()}/functions`, + runtime: config.runtime === "node" ? "nodejs18" : "python311", + }; +} + +/** + * Creates environment configuration for Firebase functions + */ +export function createEnvironmentConfig( + config: TestConfig, + firebaseConfig: FirebaseConfig +): EnvironmentConfig { + return { + DEBUG: config.debug, + FIRESTORE_PREFER_REST: "true", + GCLOUD_PROJECT: config.projectId, + FIREBASE_CONFIG: JSON.stringify(firebaseConfig), + REGION: config.region, + STORAGE_REGION: config.storageRegion, + }; +} diff --git a/integration_test/src/config/index.ts b/integration_test/src/config/index.ts new file mode 100644 index 000000000..111afced2 --- /dev/null +++ b/integration_test/src/config/index.ts @@ -0,0 +1,10 @@ +/** + * Configuration module exports + */ + +export { validateEnvironment, loadTestConfig } from "./environment.js"; +export { + createFirebaseConfig, + createFirebaseProjectConfig, + createEnvironmentConfig, +} from "./firebase.js"; diff --git a/integration_test/src/deployment.ts b/integration_test/src/deployment.ts deleted file mode 100644 index 8d49798d9..000000000 --- a/integration_test/src/deployment.ts +++ /dev/null @@ -1,107 +0,0 @@ -import fs from "fs"; -import yaml from "js-yaml"; -import portfinder from "portfinder"; -import { getRuntimeDelegate } from "firebase-tools/lib/deploy/functions/runtimes/index.js"; -import { detectFromPort } from "firebase-tools/lib/deploy/functions/runtimes/discovery/index.js"; -import { logError, logDeployment } from "./logger.js"; -import { TestConfig } from "./config.js"; - -export interface EndpointConfig { - project?: string; - runtime?: string; - [key: string]: unknown; -} - -export interface ModifiedYaml { - endpoints: Record; - specVersion: string; -} - -export function generateUniqueHash(originalName: string, testRunId: string): string { - // Function name can only contain letters, numbers and hyphens and be less than 100 chars. - const modifiedName = `${testRunId}-${originalName}`; - if (modifiedName.length > 100) { - throw new Error( - `Function name is too long. Original=${originalName}, Modified=${modifiedName}` - ); - } - return modifiedName; -} - -export function writeFunctionsYaml(filePath: string, data: any): void { - try { - fs.writeFileSync(filePath, yaml.dump(data)); - } catch (err) { - logError("Error writing functions.yaml. Exiting.", err as Error); - process.exit(1); - } -} - -/** - * Discovers endpoints and modifies functions.yaml file. - * @returns A promise that resolves with a function to kill the server. - */ -export async function discoverAndModifyEndpoints( - config: TestConfig, - firebaseConfig: any, - env: any -): Promise<{ killServer: () => void; modifiedYaml: ModifiedYaml }> { - logDeployment("Discovering endpoints..."); - try { - const port = await portfinder.getPortPromise({ port: 9000 }); - const delegate = await getRuntimeDelegate(firebaseConfig); - const killServer = await delegate.serveAdmin(port.toString(), {}, env); - - console.log("Started on port", port); - const originalYaml = (await detectFromPort( - port, - firebaseConfig.projectId, - firebaseConfig.runtime, - 10000 - )) as ModifiedYaml; - - const modifiedYaml: ModifiedYaml = { - ...originalYaml, - endpoints: Object.fromEntries( - Object.entries(originalYaml.endpoints).map(([key, value]) => { - const modifiedKey = generateUniqueHash(key, config.testRunId); - const modifiedValue: EndpointConfig = { ...value }; - delete modifiedValue.project; - delete modifiedValue.runtime; - return [modifiedKey, modifiedValue]; - }) - ), - specVersion: "v1alpha1", - }; - - writeFunctionsYaml("./functions/functions.yaml", modifiedYaml); - - return { killServer, modifiedYaml }; - } catch (err) { - logError("Error discovering endpoints. Exiting.", err as Error); - process.exit(1); - } -} - -export async function deployModifiedFunctions( - client: any, - modifiedYaml: ModifiedYaml, - testRunId: string -): Promise { - logDeployment(`Deploying functions with id: ${testRunId}`); - try { - // Get the function names that will be deployed - const functionNames = Object.keys(modifiedYaml.endpoints); - - // Import deployFunctionsWithRetry from deployment-utils - const { deployFunctionsWithRetry } = await import("../deployment-utils.js"); - - // Deploy with rate limiting and retry logic - await deployFunctionsWithRetry(client, functionNames); - - logDeployment("Functions have been deployed successfully."); - } catch (err) { - logError("Error deploying functions. Exiting.", err as Error); - throw err; - } -} diff --git a/integration_test/src/deployment/discovery.ts b/integration_test/src/deployment/discovery.ts new file mode 100644 index 000000000..61bac5843 --- /dev/null +++ b/integration_test/src/deployment/discovery.ts @@ -0,0 +1,91 @@ +/** + * Endpoint discovery functionality + */ + +import fs from "fs"; +import yaml from "js-yaml"; +import portfinder from "portfinder"; +import { getRuntimeDelegate } from "firebase-tools/lib/deploy/functions/runtimes/index.js"; +import { detectFromPort } from "firebase-tools/lib/deploy/functions/runtimes/discovery/index.js"; +import { + ModifiedYaml, + EndpointConfig, + FirebaseProjectConfig, + EnvironmentConfig, +} from "../utils/types.js"; +import { logger } from "../utils/logger.js"; + +/** + * Generate unique hash for function names + */ +export function generateUniqueHash(originalName: string, testRunId: string): string { + // Function name can only contain letters, numbers and hyphens and be less than 100 chars + const modifiedName = `${testRunId}-${originalName}`; + if (modifiedName.length > 100) { + throw new Error( + `Function name is too long. Original=${originalName}, Modified=${modifiedName}` + ); + } + return modifiedName; +} + +/** + * Write functions.yaml file + */ +export function writeFunctionsYaml(filePath: string, data: ModifiedYaml): void { + try { + fs.writeFileSync(filePath, yaml.dump(data)); + logger.success(`Functions YAML written to ${filePath}`); + } catch (err) { + logger.error("Error writing functions.yaml", err as Error); + throw err; + } +} + +/** + * Discover endpoints and modify functions.yaml file + */ +export async function discoverAndModifyEndpoints( + config: FirebaseProjectConfig, + env: EnvironmentConfig, + testRunId: string +): Promise<{ killServer: () => void; modifiedYaml: ModifiedYaml }> { + logger.info("Discovering endpoints..."); + + try { + const port = await portfinder.getPortPromise({ port: 9000 }); + const delegate = await getRuntimeDelegate(config); + const killServer = await delegate.serveAdmin(port.toString(), {}, env); + + logger.info(`Admin server started on port ${port}`); + + const originalYaml = (await detectFromPort( + port, + config.projectId, + config.runtime, + 10000 + )) as ModifiedYaml; + + // Modify endpoint names with unique test run ID + const modifiedYaml: ModifiedYaml = { + ...originalYaml, + endpoints: Object.fromEntries( + Object.entries(originalYaml.endpoints).map(([key, value]) => { + const modifiedKey = generateUniqueHash(key, testRunId); + const modifiedValue: EndpointConfig = { ...value }; + delete modifiedValue.project; + delete modifiedValue.runtime; + return [modifiedKey, modifiedValue]; + }) + ), + specVersion: "v1alpha1", + }; + + writeFunctionsYaml("./functions/functions.yaml", modifiedYaml); + + return { killServer, modifiedYaml }; + } catch (err) { + logger.error("Error discovering endpoints", err as Error); + throw err; + } +} diff --git a/integration_test/src/deployment/functions.ts b/integration_test/src/deployment/functions.ts new file mode 100644 index 000000000..70a4c0cd3 --- /dev/null +++ b/integration_test/src/deployment/functions.ts @@ -0,0 +1,38 @@ +/** + * Function deployment with rate limiting and retry logic + */ + +import { FirebaseClient, ModifiedYaml } from "../utils/types.js"; +import { logger } from "../utils/logger.js"; +import { deployFunctionsWithRetry } from "../../deployment-utils.js"; + +/** + * Deploy modified functions to Firebase + */ +export async function deployModifiedFunctions( + client: FirebaseClient, + modifiedYaml: ModifiedYaml, + testRunId: string +): Promise { + logger.deployment(`Deploying functions with id: ${testRunId}`); + + try { + // Get the function names that will be deployed + const functionNames = modifiedYaml ? Object.keys(modifiedYaml.endpoints) : []; + + logger.deployment(`Functions to deploy: ${functionNames.join(", ")}`); + logger.deployment(`Total functions to deploy: ${functionNames.length}`); + + // Deploy with rate limiting and retry logic + await deployFunctionsWithRetry(client, functionNames); + + logger.success("Functions have been deployed successfully."); + logger.info("You can view your deployed functions in the Firebase Console:"); + logger.info( + ` https://console.firebase.google.com/project/${process.env.PROJECT_ID}/functions` + ); + } catch (err) { + logger.error("Error deploying functions", err as Error); + throw err; + } +} diff --git a/integration_test/src/deployment/index.ts b/integration_test/src/deployment/index.ts new file mode 100644 index 000000000..2da727d6d --- /dev/null +++ b/integration_test/src/deployment/index.ts @@ -0,0 +1,7 @@ +/** + * Deployment module exports + */ + +export { discoverAndModifyEndpoints, generateUniqueHash, writeFunctionsYaml } from "./discovery.js"; + +export { deployModifiedFunctions } from "./functions.js"; diff --git a/integration_test/src/index.ts b/integration_test/src/index.ts deleted file mode 100644 index f31b94a35..000000000 --- a/integration_test/src/index.ts +++ /dev/null @@ -1,61 +0,0 @@ -import * as dotenv from "dotenv"; -import client from "firebase-tools"; -import setup from "../setup.js"; -import { - validateEnvironment, - loadConfig, - createFirebaseConfig, - createEnvironmentConfig, -} from "./config"; -import { logInfo, logError } from "./logger"; -import { handleCleanUp, gracefulShutdown } from "./cleanup"; -import { discoverAndModifyEndpoints, deployModifiedFunctions } from "./deployment.js"; -import { runTests } from "./process"; - -export async function runIntegrationTests(): Promise { - // Load environment variables - dotenv.config(); - - // Validate environment - validateEnvironment(); - - // Load configuration - const config = loadConfig(); - - // Setup SDK and functions - setup(config.runtime, config.testRunId, config.nodeVersion, config.firebaseAdmin); - - // Create Firebase and environment configs - const firebaseConfig = createFirebaseConfig(config); - const env = createEnvironmentConfig(config); - - logInfo("Firebase config created: "); - logInfo(JSON.stringify(firebaseConfig, null, 2)); - - // Set up graceful shutdown - const cleanupFn = () => handleCleanUp(client, config.testRunId); - process.on("SIGINT", () => gracefulShutdown(cleanupFn)); - - try { - // Skip pre-cleanup for now to test if the main flow works - logInfo("⏭️ Skipping pre-cleanup for testing..."); - - const { killServer, modifiedYaml } = await discoverAndModifyEndpoints( - config, - firebaseConfig, - env - ); - await deployModifiedFunctions(client, modifiedYaml, config.testRunId); - killServer(); - await runTests(config.testRunId); - } catch (err) { - logError("Error occurred during integration tests:", err as Error); - // Re-throw the original error instead of wrapping it - throw err; - } finally { - await cleanupFn(); - } -} - -// Export the main function for use in run.ts -export { runIntegrationTests as default }; diff --git a/integration_test/src/main.ts b/integration_test/src/main.ts new file mode 100644 index 000000000..6a063965e --- /dev/null +++ b/integration_test/src/main.ts @@ -0,0 +1,86 @@ +/** + * Main orchestrator for integration tests + */ + +import * as dotenv from "dotenv"; +import client from "firebase-tools"; +import { FirebaseClient } from "./utils/types.js"; +import { logger } from "./utils/logger.js"; +import { + loadTestConfig, + createFirebaseConfig, + createFirebaseProjectConfig, + createEnvironmentConfig, +} from "./config/index.js"; +import { setup } from "./setup/index.js"; +import { discoverAndModifyEndpoints, deployModifiedFunctions } from "./deployment/index.js"; +import { runTests } from "./testing/index.js"; +import { handleCleanUp, gracefulShutdown } from "./cleanup/index.js"; + +/** + * Main function to run integration tests + */ +export async function runIntegrationTests(): Promise { + // Load environment variables + dotenv.config(); + + // Load and validate configuration + const config = loadTestConfig(); + + logger.info("Starting integration tests"); + logger.info(`Test Run ID: ${config.testRunId}`); + logger.info(`Runtime: ${config.runtime}`); + logger.info(`Project ID: ${config.projectId}`); + + // Setup SDK and functions + setup(config.runtime, config.testRunId, config.nodeVersion, config.firebaseAdmin); + + // Create Firebase configurations + const firebaseConfig = createFirebaseConfig(config); + const firebaseProjectConfig = createFirebaseProjectConfig(config); + const environmentConfig = createEnvironmentConfig(config, firebaseConfig); + + // Configure Firebase client + logger.info("Configuring Firebase client with project ID:", config.projectId); + const firebaseClient = client as FirebaseClient; + + logger.debug("Firebase config created:"); + logger.debug(JSON.stringify(firebaseProjectConfig, null, 2)); + + // Set up graceful shutdown handler + const cleanupFn = () => handleCleanUp(firebaseClient, config.testRunId); + process.on("SIGINT", () => gracefulShutdown(cleanupFn)); + + try { + // Skip pre-cleanup for now to test if the main flow works + logger.info("Skipping pre-cleanup for testing..."); + + // Discover and modify endpoints + const { killServer, modifiedYaml } = await discoverAndModifyEndpoints( + firebaseProjectConfig, + environmentConfig, + config.testRunId + ); + + // Deploy functions + await deployModifiedFunctions(firebaseClient, modifiedYaml, config.testRunId); + + // Kill the admin server + killServer(); + + // Run tests + const testResult = await runTests(config.testRunId, config.runtime); + + if (!testResult.passed) { + throw new Error("Some tests failed"); + } + } catch (err) { + logger.error("Error occurred during integration tests:", err as Error); + throw err; + } finally { + await cleanupFn(); + } +} + +// Export for use in run.ts +export default runIntegrationTests; diff --git a/integration_test/src/process.ts b/integration_test/src/process.ts deleted file mode 100644 index 3f8dc1588..000000000 --- a/integration_test/src/process.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { spawn } from "child_process"; -import { logError, logDebug } from "./logger.js"; - -export const spawnAsync = (command: string, args: string[], options: any): Promise => { - return new Promise((resolve, reject) => { - const child = spawn(command, args, options); - - let output = ""; - let errorOutput = ""; - - if (child.stdout) { - child.stdout.on("data", (data) => { - output += data.toString(); - }); - } - - if (child.stderr) { - child.stderr.on("data", (data) => { - errorOutput += data.toString(); - }); - } - - child.on("error", reject); - - child.on("close", (code) => { - if (code === 0) { - resolve(output); - } else { - const errorMessage = `Command failed with exit code ${code}`; - const fullError = errorOutput ? `${errorMessage}\n\nSTDERR:\n${errorOutput}` : errorMessage; - reject(new Error(fullError)); - } - }); - - // Add timeout to prevent hanging - const timeout = setTimeout(() => { - child.kill(); - reject(new Error(`Command timed out after 5 minutes: ${command} ${args.join(" ")}`)); - }, 5 * 60 * 1000); // 5 minutes - - child.on("close", () => { - clearTimeout(timeout); - }); - }); -}; - -export async function runTests(testRunId: string): Promise { - const humanReadableRuntime = process.env.TEST_RUNTIME === "node" ? "Node.js" : "Python"; - try { - console.log(`Starting ${humanReadableRuntime} Tests...`); - logDebug("About to run: npm test"); - - const output = await spawnAsync("npm", ["test"], { - env: { - ...process.env, - TEST_RUN_ID: testRunId, - }, - }); - - console.log("📋 Test output received:"); - console.log(output); - console.log(`${humanReadableRuntime} Tests Completed.`); - } catch (error) { - logError("❌ Error during testing:", error as Error); - throw error; - } -} diff --git a/integration_test/src/run.ts b/integration_test/src/run.ts deleted file mode 100644 index d6f2ccb4b..000000000 --- a/integration_test/src/run.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { runIntegrationTests } from "./index"; - -runIntegrationTests().catch((error) => { - console.error("An error occurred during integration tests", error); - process.exit(1); -}); diff --git a/integration_test/src/setup/index.ts b/integration_test/src/setup/index.ts new file mode 100644 index 000000000..0359b01f3 --- /dev/null +++ b/integration_test/src/setup/index.ts @@ -0,0 +1,49 @@ +/** + * Setup orchestration module + */ + +import { ValidRuntime } from "../utils/types.js"; +import { + buildNodeSdk, + createPackageJson, + installNodeDependencies, + buildNodeFunctions, +} from "./node.js"; +import { buildPythonSdk, createRequirementsTxt, installPythonDependencies } from "./python.js"; + +/** + * Main setup function that orchestrates SDK building and function setup + */ +export function setup( + testRuntime: ValidRuntime, + testRunId: string, + nodeVersion: string, + firebaseAdmin: string +): void { + if (testRuntime === "node") { + setupNode(testRunId, nodeVersion, firebaseAdmin); + } else if (testRuntime === "python") { + setupPython(firebaseAdmin); + } +} + +/** + * Setup for Node.js runtime + */ +function setupNode(testRunId: string, nodeVersion: string, firebaseAdmin: string): void { + buildNodeSdk(testRunId); + createPackageJson(testRunId, nodeVersion, firebaseAdmin); + installNodeDependencies(); + buildNodeFunctions(); +} + +/** + * Setup for Python runtime + */ +function setupPython(firebaseAdmin: string): void { + buildPythonSdk(); + createRequirementsTxt(firebaseAdmin); + installPythonDependencies(); +} + +export default setup; diff --git a/integration_test/src/setup/node.ts b/integration_test/src/setup/node.ts new file mode 100644 index 000000000..b4d5ee901 --- /dev/null +++ b/integration_test/src/setup/node.ts @@ -0,0 +1,102 @@ +/** + * Node.js specific setup functions + */ + +import { execSync } from "child_process"; +import fs from "fs"; +import path from "path"; +import { logger } from "../utils/logger.js"; + +/** + * Build Node.js SDK package + */ +export function buildNodeSdk(testRunId: string): void { + logger.info("Building Node.js SDK..."); + const currentDir = process.cwd(); + + process.chdir(path.join(currentDir, "..")); // go up to root + + // Remove existing firebase-functions-*.tgz files + const files = fs.readdirSync("."); + files.forEach((file) => { + if (file.match(/^firebase-functions-.*\.tgz$/)) { + fs.rmSync(file); + } + }); + + // Build the package + execSync("npm run build:pack", { stdio: "inherit" }); + + // Move the generated tarball package to functions + const generatedFile = fs + .readdirSync(".") + .find((file) => file.match(/^firebase-functions-.*\.tgz$/)); + + if (generatedFile) { + const targetPath = path.join( + "integration_test", + "functions", + `firebase-functions-${testRunId}.tgz` + ); + fs.renameSync(generatedFile, targetPath); + logger.success(`SDK moved to ${targetPath}`); + } + + process.chdir(currentDir); // go back to integration_test +} + +/** + * Create package.json from template + */ +export function createPackageJson( + testRunId: string, + nodeVersion: string, + firebaseAdmin: string +): void { + logger.info("Creating package.json..."); + const currentDir = process.cwd(); + const packageJsonTemplatePath = `${currentDir}/package.json.template`; + const packageJsonPath = `${currentDir}/functions/package.json`; + + fs.copyFileSync(packageJsonTemplatePath, packageJsonPath); + + let packageJsonContent = fs.readFileSync(packageJsonPath, "utf8"); + packageJsonContent = packageJsonContent.replace( + /__SDK_TARBALL__/g, + `firebase-functions-${testRunId}.tgz` + ); + packageJsonContent = packageJsonContent.replace(/__NODE_VERSION__/g, nodeVersion); + packageJsonContent = packageJsonContent.replace(/__FIREBASE_ADMIN__/g, firebaseAdmin); + + fs.writeFileSync(packageJsonPath, packageJsonContent); +} + +/** + * Install Node.js dependencies + */ +export function installNodeDependencies(): void { + logger.info("Installing Node.js dependencies..."); + const functionsDir = "functions"; + + process.chdir(functionsDir); // go to functions + + const modulePath = path.join("node_modules", "firebase-functions"); + if (fs.existsSync(modulePath)) { + execSync(`rm -rf ${modulePath}`, { stdio: "inherit" }); + } + + execSync("npm install", { stdio: "inherit" }); + process.chdir("../"); // go back to integration_test +} + +/** + * Build Node.js functions + */ +export function buildNodeFunctions(): void { + logger.info("Building Node.js functions..."); + const currentDir = process.cwd(); + + process.chdir(path.join(currentDir, "functions")); // go to functions + execSync("npm run build", { stdio: "inherit" }); + process.chdir(currentDir); // go back to integration_test +} diff --git a/integration_test/src/setup/python.ts b/integration_test/src/setup/python.ts new file mode 100644 index 000000000..d6973aed7 --- /dev/null +++ b/integration_test/src/setup/python.ts @@ -0,0 +1,96 @@ +/** + * Python specific setup functions + */ + +import { execSync } from "child_process"; +import fs from "fs"; +import path from "path"; +import { logger } from "../utils/logger.js"; + +/** + * Build Python SDK package + */ +export function buildPythonSdk(): void { + logger.info("Building Python SDK..."); + const currentDir = process.cwd(); + + process.chdir(path.join(currentDir, "..")); // go up to root + + // Remove existing build + fs.rmSync("dist", { recursive: true, force: true }); + + // Remove existing venv + fs.rmSync("venv", { recursive: true, force: true }); + + // Make virtual environment for building + execSync("python3 -m venv venv", { stdio: "inherit" }); + + // Build the package + execSync("source venv/bin/activate && python -m pip install --upgrade build", { + stdio: "inherit", + shell: "bash", + }); + + execSync("source venv/bin/activate && python -m build -s", { + stdio: "inherit", + shell: "bash", + }); + + // Move the generated tarball package to functions + const generatedFile = fs + .readdirSync("dist") + .find((file) => file.match(/^firebase_functions-.*\.tar\.gz$/)); + + if (generatedFile) { + const targetPath = path.join("integration_test", "functions", "firebase_functions.tar.gz"); + fs.renameSync(path.join("dist", generatedFile), targetPath); + logger.success(`SDK moved to ${targetPath}`); + } + + process.chdir(currentDir); // go back to integration_test +} + +/** + * Create requirements.txt from template + */ +export function createRequirementsTxt(firebaseAdmin: string): void { + logger.info("Creating requirements.txt..."); + const currentDir = process.cwd(); + const requirementsTemplatePath = `${currentDir}/requirements.txt.template`; + const requirementsPath = `${currentDir}/functions/requirements.txt`; + + fs.copyFileSync(requirementsTemplatePath, requirementsPath); + + let requirementsContent = fs.readFileSync(requirementsPath, "utf8"); + requirementsContent = requirementsContent.replace( + /__LOCAL_FIREBASE_FUNCTIONS__/g, + "firebase_functions.tar.gz" + ); + requirementsContent = requirementsContent.replace(/__FIREBASE_ADMIN__/g, firebaseAdmin); + + fs.writeFileSync(requirementsPath, requirementsContent); +} + +/** + * Install Python dependencies + */ +export function installPythonDependencies(): void { + logger.info("Installing Python dependencies..."); + const functionsDir = "functions"; + + process.chdir(functionsDir); // go to functions + + const venvPath = path.join("venv"); + if (fs.existsSync(venvPath)) { + execSync(`rm -rf ${venvPath}`, { stdio: "inherit" }); + } + + execSync("python3 -m venv venv", { stdio: "inherit" }); + + execSync("source venv/bin/activate && python3 -m pip install -r requirements.txt", { + stdio: "inherit", + shell: "bash", + }); + + process.chdir("../"); // go back to integration_test +} diff --git a/integration_test/src/testing/index.ts b/integration_test/src/testing/index.ts new file mode 100644 index 000000000..c89aa2e55 --- /dev/null +++ b/integration_test/src/testing/index.ts @@ -0,0 +1,5 @@ +/** + * Testing module exports + */ + +export { runTests, spawnAsync } from "./runner.js"; diff --git a/integration_test/src/testing/runner.ts b/integration_test/src/testing/runner.ts new file mode 100644 index 000000000..51cc0955d --- /dev/null +++ b/integration_test/src/testing/runner.ts @@ -0,0 +1,100 @@ +/** + * Test execution functionality + */ + +import { spawn } from "child_process"; +import { TestResult } from "../utils/types.js"; +import { logger } from "../utils/logger.js"; + +/** + * Spawn a command asynchronously with timeout support + */ +export function spawnAsync(command: string, args: string[], options: any): Promise { + return new Promise((resolve, reject) => { + const child = spawn(command, args, options); + + let output = ""; + let errorOutput = ""; + + if (child.stdout) { + child.stdout.on("data", (data) => { + output += data.toString(); + }); + } + + if (child.stderr) { + child.stderr.on("data", (data) => { + errorOutput += data.toString(); + }); + } + + child.on("error", reject); + + child.on("close", (code) => { + if (code === 0) { + resolve(output); + } else { + const errorMessage = `Command failed with exit code ${code}`; + const fullError = errorOutput ? `${errorMessage}\n\nSTDERR:\n${errorOutput}` : errorMessage; + reject(new Error(fullError)); + } + }); + + // Add timeout to prevent hanging (5 minutes) + const timeout = setTimeout(() => { + child.kill(); + reject(new Error(`Command timed out after 5 minutes: ${command} ${args.join(" ")}`)); + }, 5 * 60 * 1000); + + child.on("close", () => { + clearTimeout(timeout); + }); + }); +} + +/** + * Run integration tests using Jest + */ +export async function runTests(testRunId: string, runtime: string): Promise { + const humanReadableRuntime = runtime === "node" ? "Node.js" : "Python"; + + try { + logger.info(`Starting ${humanReadableRuntime} Tests...`); + logger.info("Running all integration tests"); + + // Run all tests with Jest + const output = await spawnAsync("npx", ["jest", "--verbose"], { + env: { + ...process.env, + TEST_RUN_ID: testRunId, + }, + }); + + logger.info("Test output received:"); + logger.debug(output); + + // Check if tests passed + const passed = output.includes("PASS") && !output.includes("FAIL"); + + if (passed) { + logger.success("All tests completed successfully!"); + logger.success("All function triggers are working correctly."); + } else { + logger.warning("Some tests may have failed. Check the output above."); + } + + logger.info(`${humanReadableRuntime} Tests Completed.`); + + return { + passed, + output, + }; + } catch (error) { + logger.error("Error during testing:", error as Error); + return { + passed: false, + output: "", + error: error as Error, + }; + } +} diff --git a/integration_test/src/logger.ts b/integration_test/src/utils/logger.ts similarity index 100% rename from integration_test/src/logger.ts rename to integration_test/src/utils/logger.ts diff --git a/integration_test/src/utils/shell.ts b/integration_test/src/utils/shell.ts new file mode 100644 index 000000000..5822ac061 --- /dev/null +++ b/integration_test/src/utils/shell.ts @@ -0,0 +1,110 @@ +/** + * Shell command utilities + */ + +import { spawn, SpawnOptions } from "child_process"; + +export interface ShellResult { + stdout: string; + stderr: string; + exitCode: number; +} + +/** + * Execute a shell command with proper error handling + */ +export function execCommand( + command: string, + args: string[] = [], + options: SpawnOptions = {} +): Promise { + return new Promise((resolve, reject) => { + const child = spawn(command, args, options); + + let stdout = ""; + let stderr = ""; + + if (child.stdout) { + child.stdout.on("data", (data) => { + stdout += data.toString(); + }); + } + + if (child.stderr) { + child.stderr.on("data", (data) => { + stderr += data.toString(); + }); + } + + child.on("error", (error) => { + reject(error); + }); + + child.on("close", (exitCode) => { + resolve({ + stdout, + stderr, + exitCode: exitCode || 0, + }); + }); + }); +} + +/** + * Execute a command with timeout support + */ +export function execCommandWithTimeout( + command: string, + args: string[] = [], + options: SpawnOptions = {}, + timeoutMs: number = 5 * 60 * 1000 // 5 minutes default +): Promise { + return new Promise((resolve, reject) => { + const child = spawn(command, args, options); + + let stdout = ""; + let stderr = ""; + let timedOut = false; + + const timeout = setTimeout(() => { + timedOut = true; + child.kill("SIGTERM"); + setTimeout(() => { + if (child.killed === false) { + child.kill("SIGKILL"); + } + }, 5000); + }, timeoutMs); + + if (child.stdout) { + child.stdout.on("data", (data) => { + stdout += data.toString(); + }); + } + + if (child.stderr) { + child.stderr.on("data", (data) => { + stderr += data.toString(); + }); + } + + child.on("error", (error) => { + clearTimeout(timeout); + reject(error); + }); + + child.on("close", (exitCode) => { + clearTimeout(timeout); + + if (timedOut) { + reject(new Error(`Command timed out after ${timeoutMs}ms: ${command} ${args.join(" ")}`)); + } else { + resolve({ + stdout, + stderr, + exitCode: exitCode || 0, + }); + } + }); + }); +} diff --git a/integration_test/src/utils/types.ts b/integration_test/src/utils/types.ts new file mode 100644 index 000000000..724071258 --- /dev/null +++ b/integration_test/src/utils/types.ts @@ -0,0 +1,86 @@ +/** + * Shared TypeScript interfaces and types for the integration test suite + */ + +export interface TestConfig { + projectId: string; + testRunId: string; + runtime: "node" | "python"; + nodeVersion: string; + firebaseAdmin: string; + region: string; + storageRegion: string; + debug?: string; + databaseUrl: string; + storageBucket: string; + firebaseAppId: string; + firebaseMeasurementId: string; + firebaseAuthDomain: string; + firebaseApiKey: string; +} + +export interface FirebaseConfig { + databaseURL: string; + projectId: string; + storageBucket: string; +} + +export interface FirebaseProjectConfig { + projectId: string; + projectDir: string; + sourceDir: string; + runtime: string; +} + +export interface EnvironmentConfig { + DEBUG?: string; + FIRESTORE_PREFER_REST: string; + GCLOUD_PROJECT: string; + FIREBASE_CONFIG: string; + REGION: string; + STORAGE_REGION: string; +} + +export interface EndpointConfig { + project?: string; + runtime?: string; + [key: string]: unknown; +} + +export interface ModifiedYaml { + endpoints: Record; + specVersion: string; +} + +export interface FirebaseClient { + functions: { + list: (options?: any) => Promise<{ name: string }[]>; + delete(names: string[], options: any): Promise; + }; + deploy: (options: any) => Promise; +} + +export type ValidRuntime = "node" | "python"; +export const VALID_RUNTIMES: readonly ValidRuntime[] = ["node", "python"] as const; + +export interface DeployOptions { + only: string; + force: boolean; + project: string; + debug: boolean; + nonInteractive: boolean; + cwd: string; +} + +export interface FunctionListOptions { + project: string; + config: string; + nonInteractive: boolean; + cwd: string; +} + +export interface TestResult { + passed: boolean; + output: string; + error?: Error; +} diff --git a/integration_test/tests/firebaseSetup.ts b/integration_test/tests/firebaseSetup.ts index 12badd682..7d59a445e 100644 --- a/integration_test/tests/firebaseSetup.ts +++ b/integration_test/tests/firebaseSetup.ts @@ -1,5 +1,5 @@ import * as admin from "firebase-admin"; -import { logger } from "../src/logger"; +import { logger } from "../src/utils/logger"; /** * Initializes Firebase Admin SDK. diff --git a/integration_test/tests/v1/database.test.ts b/integration_test/tests/v1/database.test.ts index fa4886063..959f8e89e 100644 --- a/integration_test/tests/v1/database.test.ts +++ b/integration_test/tests/v1/database.test.ts @@ -2,7 +2,7 @@ import * as admin from "firebase-admin"; import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; import { Reference } from "@firebase/database-types"; -import { logger } from "../../src/logger"; +import { logger } from "../../src/utils/logger"; describe("Firebase Database (v1)", () => { const projectId = process.env.PROJECT_ID; diff --git a/integration_test/tests/v2/database.test.ts b/integration_test/tests/v2/database.test.ts index fab34287d..e9ed0b401 100644 --- a/integration_test/tests/v2/database.test.ts +++ b/integration_test/tests/v2/database.test.ts @@ -2,7 +2,7 @@ import * as admin from "firebase-admin"; import { retry } from "../utils"; import { initializeFirebase } from "../firebaseSetup"; import { Reference } from "@firebase/database-types"; -import { logger } from "../../src/logger"; +import { logger } from "../../src/utils/logger"; describe("Firebase Database (v2)", () => { const projectId = process.env.PROJECT_ID;