diff --git a/.changeset/cold-carpets-sing.md b/.changeset/cold-carpets-sing.md deleted file mode 100644 index e291792fb5b..00000000000 --- a/.changeset/cold-carpets-sing.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@firebase/firestore": patch ---- - -Fixed leak of grpc-js resources on terminate. diff --git a/.changeset/good-seals-promise.md b/.changeset/good-seals-promise.md deleted file mode 100644 index a0644ae48f3..00000000000 --- a/.changeset/good-seals-promise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@firebase/app': patch ---- - -Catch possible error in Safari browsers. diff --git a/.changeset/itchy-chicken-cry.md b/.changeset/itchy-chicken-cry.md deleted file mode 100644 index a845151cc84..00000000000 --- a/.changeset/itchy-chicken-cry.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/long-rats-walk.md b/.changeset/long-rats-walk.md deleted file mode 100644 index a845151cc84..00000000000 --- a/.changeset/long-rats-walk.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/olive-points-fold.md b/.changeset/olive-points-fold.md new file mode 100644 index 00000000000..eb58ac3f922 --- /dev/null +++ b/.changeset/olive-points-fold.md @@ -0,0 +1,7 @@ +--- +'firebase': minor +'@firebase/vertexai-preview': patch +'@firebase/app': patch +--- + +Add the preview version of the VertexAI SDK. diff --git a/.changeset/quick-peas-guess.md b/.changeset/quick-peas-guess.md deleted file mode 100644 index a845151cc84..00000000000 --- a/.changeset/quick-peas-guess.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/serious-rivers-attend.md b/.changeset/serious-rivers-attend.md new file mode 100644 index 00000000000..8946e84cb72 --- /dev/null +++ b/.changeset/serious-rivers-attend.md @@ -0,0 +1,5 @@ +--- +"@firebase/webchannel-wrapper": patch +--- + +fix: Update webchannel-wrapper to fix webchannel multi-byte character decoding bug in fetch streams. diff --git a/.changeset/shaggy-garlics-leave.md b/.changeset/shaggy-garlics-leave.md deleted file mode 100644 index b48961d7e6a..00000000000 --- a/.changeset/shaggy-garlics-leave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@firebase/firestore": patch ---- - -Support special characters in query paths sent to `getCountFromServer(...)`, `getCount(...)` (lite API), and `getDocs(...)` (lite API). diff --git a/.changeset/thick-spoons-check.md b/.changeset/thick-spoons-check.md new file mode 100644 index 00000000000..dce3dcdd8ab --- /dev/null +++ b/.changeset/thick-spoons-check.md @@ -0,0 +1,6 @@ +--- +"@firebase/firestore": patch +"@firebase/webchannel-wrapper": major +--- + +Use closure-net as a dependency of webchannel-wrapper and Firestore. diff --git a/.changeset/tiny-pots-sit.md b/.changeset/tiny-pots-sit.md new file mode 100644 index 00000000000..da79ec8f1bf --- /dev/null +++ b/.changeset/tiny-pots-sit.md @@ -0,0 +1,52 @@ +--- +'@firebase/analytics': patch +'@firebase/analytics-compat': patch +'@firebase/analytics-interop-types': patch +'@firebase/analytics-types': patch +'@firebase/app': patch +'@firebase/app-check': patch +'@firebase/app-check-compat': patch +'@firebase/app-check-interop-types': patch +'@firebase/app-check-types': patch +'@firebase/app-compat': patch +'@firebase/app-types': patch +'@firebase/auth': patch +'@firebase/auth-compat': patch +'@firebase/auth-interop-types': patch +'@firebase/auth-types': patch +'@firebase/component': patch +'@firebase/database': patch +'@firebase/database-compat': patch +'@firebase/database-types': patch +'firebase': patch +'@firebase/firestore': patch +'@firebase/firestore-compat': patch +'@firebase/firestore-types': patch +'@firebase/functions': patch +'@firebase/functions-compat': patch +'@firebase/functions-types': patch +'@firebase/installations': patch +'@firebase/installations-compat': patch +'@firebase/installations-types': patch +'@firebase/logger': patch +'@firebase/messaging': patch +'@firebase/messaging-compat': patch +'@firebase/messaging-interop-types': patch +'@firebase/performance': patch +'@firebase/performance-compat': patch +'@firebase/performance-types': patch +'@firebase/remote-config': patch +'@firebase/remote-config-compat': patch +'@firebase/remote-config-types': patch +'@firebase/rules-unit-testing': patch +'@firebase/storage': patch +'@firebase/storage-compat': patch +'@firebase/storage-types': patch +'@firebase/template': patch +'@firebase/template-types': patch +'@firebase/util': patch +'@firebase/vertexai-preview': patch +'@firebase/webchannel-wrapper': patch +--- + +Bump all packages so staging works. diff --git a/.changeset/witty-comics-rule.md b/.changeset/witty-comics-rule.md deleted file mode 100644 index 0b6b1bc3175..00000000000 --- a/.changeset/witty-comics-rule.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'firebase': patch -'@firebase/firestore': patch ---- - -Tweak the automatic index creation parameters to use more optimal values for the platform/browser detected at runtime. diff --git a/.changeset/yellow-houses-happen.md b/.changeset/yellow-houses-happen.md deleted file mode 100644 index 66858c86adf..00000000000 --- a/.changeset/yellow-houses-happen.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@firebase/firestore': patch -'firebase': patch ---- - -Update the `isEqual` function for arrayUnion, arrayRemove and increment. diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 94e109f7a1b..01949c5e354 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -11,9 +11,9 @@ * @firebase/jssdk-global-approvers # Database Code -packages/database @maneesht @jsdt @jmwski @firebase/jssdk-global-approvers -packages/database-compat @maneesht @jsdt @jmwski @firebase/jssdk-global-approvers -packages/database-types @maneesht @jsdt @jmwski @firebase/jssdk-global-approvers +packages/database @maneesht @aashishpatil-g @firebase/jssdk-global-approvers +packages/database-compat @maneesht @aashishpatil-g @firebase/jssdk-global-approvers +packages/database-types @maneesht @aashishpatil-g @firebase/jssdk-global-approvers # Firestore Code packages/firestore @firebase/firestore-js-team @firebase/jssdk-global-approvers @@ -34,10 +34,10 @@ packages/messaging-interop-types @zwu52 @firebase/jssdk-global-approvers integration/messaging @zwu52 @firebase/jssdk-global-approvers # Auth Code -packages/auth @lisajian @Xiaoshouzi-gh @renkelvin @sam-gc @firebase/jssdk-global-approvers -packages/auth-compat @lisajian @Xiaoshouzi-gh @renkelvin @sam-gc @firebase/jssdk-global-approvers -packages/auth-types @lisajian @Xiaoshouzi-gh @renkelvin @sam-gc @firebase/jssdk-global-approvers -packages/auth-interop-types @lisajian @Xiaoshouzi-gh @renkelvin @sam-gc @firebase/jssdk-global-approvers +packages/auth @lisajian @Xiaoshouzi-gh @sam-gc @firebase/jssdk-global-approvers +packages/auth-compat @lisajian @Xiaoshouzi-gh @sam-gc @firebase/jssdk-global-approvers +packages/auth-types @lisajian @Xiaoshouzi-gh @sam-gc @firebase/jssdk-global-approvers +packages/auth-interop-types @lisajian @Xiaoshouzi-gh @sam-gc @firebase/jssdk-global-approvers # Testing Code packages/rules-unit-testing @avolkovi @sam-gc @yuchenshi @firebase/jssdk-global-approvers @@ -71,7 +71,7 @@ packages/app-check-interop-types @hsubox76 @firebase/jssdk-global-approvers # Documentation Changes packages/firebase/index.d.ts @egilmorez @firebase/jssdk-global-approvers scripts/docgen/content-sources/ @egilmorez @firebase/jssdk-global-approvers -docs-devsite/ @egilmorez @markarndt @kevinthecheung +docs-devsite/ @firebase/firebase-techwriters # Changeset .changeset @firebase/jssdk-changeset-approvers @firebase/firestore-js-team @firebase/jssdk-global-approvers diff --git a/.github/ISSUE_TEMPLATE/bug_report_v2.yaml b/.github/ISSUE_TEMPLATE/bug_report_v2.yaml index 13e644e5c42..30041068b61 100644 --- a/.github/ISSUE_TEMPLATE/bug_report_v2.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report_v2.yaml @@ -71,6 +71,7 @@ body: - Performance - Remote-Config - Storage + - VertexAI validations: required: true - type: textarea diff --git a/.github/workflows/canary-deploy.yml b/.github/workflows/canary-deploy.yml index 02871078f44..8b359aaccdf 100644 --- a/.github/workflows/canary-deploy.yml +++ b/.github/workflows/canary-deploy.yml @@ -31,10 +31,10 @@ jobs: with: # Canary release script requires git history and tags. fetch-depth: 0 - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Yarn install run: yarn - name: Deploy canary @@ -73,6 +73,7 @@ jobs: NPM_TOKEN_STORAGE_TYPES: ${{secrets.NPM_TOKEN_STORAGE_TYPES}} NPM_TOKEN_TESTING: ${{secrets.NPM_TOKEN_TESTING}} NPM_TOKEN_UTIL: ${{secrets.NPM_TOKEN_UTIL}} + NPM_TOKEN_VERTEXAI: ${{secrets.NPM_TOKEN_VERTEXAI}} NPM_TOKEN_WEBCHANNEL_WRAPPER: ${{secrets.NPM_TOKEN_WEBCHANNEL_WRAPPER}} NPM_TOKEN_FIREBASE: ${{secrets.NPM_TOKEN_FIREBASE}} NPM_TOKEN_APP_COMPAT: ${{ secrets.NPM_TOKEN_APP_COMPAT }} diff --git a/.github/workflows/check-changeset.yml b/.github/workflows/check-changeset.yml index bd1de9b3cb8..ca76fe7a76b 100644 --- a/.github/workflows/check-changeset.yml +++ b/.github/workflows/check-changeset.yml @@ -34,10 +34,10 @@ jobs: with: # This makes Actions fetch all Git history so check_changeset script can diff properly. fetch-depth: 0 - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Yarn install run: yarn - name: Run changeset script @@ -47,7 +47,10 @@ jobs: yarn ts-node-script scripts/ci/check_changeset.ts id: check-changeset - name: Print changeset checker output - run: echo "${{steps.check-changeset.outputs.CHANGESET_ERROR_MESSAGE}}" + run: | + cat << 'eof_delimiter_that_will_never_occur_in_CHANGESET_ERROR_MESSAGE' + ${{steps.check-changeset.outputs.CHANGESET_ERROR_MESSAGE}} + eof_delimiter_that_will_never_occur_in_CHANGESET_ERROR_MESSAGE - name: Print blocking failure status run: echo "${{steps.check-changeset.outputs.BLOCKING_FAILURE}}" - name: Find Comment diff --git a/.github/workflows/check-docs.yml b/.github/workflows/check-docs.yml index 9c44c22214a..aefab2506e3 100644 --- a/.github/workflows/check-docs.yml +++ b/.github/workflows/check-docs.yml @@ -27,10 +27,10 @@ jobs: with: # get all history for the diff fetch-depth: 0 - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Yarn install run: yarn - name: Run doc generation (devsite docs) diff --git a/.github/workflows/check-pkg-paths.yml b/.github/workflows/check-pkg-paths.yml index 2182a3502c6..8ca54225e10 100644 --- a/.github/workflows/check-pkg-paths.yml +++ b/.github/workflows/check-pkg-paths.yml @@ -27,10 +27,10 @@ jobs: with: # This makes Actions fetch all Git history so run-changed script can diff properly. fetch-depth: 0 - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Yarn install run: yarn - name: Yarn build diff --git a/.github/workflows/deploy-config.yml b/.github/workflows/deploy-config.yml index ebb607c5417..3a2d935dd28 100644 --- a/.github/workflows/deploy-config.yml +++ b/.github/workflows/deploy-config.yml @@ -27,6 +27,7 @@ jobs: test: name: Deploy Firebase Project Rules and Functions runs-on: ubuntu-latest + if: (github.actor != 'dependabot[bot]') steps: - name: Checkout Repo @@ -34,10 +35,10 @@ jobs: with: # This makes Actions fetch all Git history so run-changed script can diff properly. fetch-depth: 0 - - name: Set up node (18) + - name: Set up node (20) uses: actions/setup-node@v3 with: - node-version: 18.x + node-version: 20.x - name: Yarn install run: yarn - name: Deploy project config if needed diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index d844e4e34ea..80a555f7840 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -36,10 +36,10 @@ jobs: steps: - name: Checkout Repo uses: actions/checkout@master - - name: Set up Node (18) + - name: Set up Node (20) uses: actions/setup-node@master with: - node-version: 18.x + node-version: 20.x - name: install Chrome stable run: | sudo apt-get update diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 1e77356832d..7434a9cab4c 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -31,10 +31,10 @@ jobs: with: # get all history for the diff fetch-depth: 0 - - name: Set up node (16) + - name: Set up node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Yarn install run: yarn - name: Run formatting script diff --git a/.github/workflows/health-metrics-pull-request.yml b/.github/workflows/health-metrics-pull-request.yml index 6bbfc8b93c2..2148c6d5abf 100644 --- a/.github/workflows/health-metrics-pull-request.yml +++ b/.github/workflows/health-metrics-pull-request.yml @@ -35,13 +35,13 @@ env: jobs: binary-size: name: Binary Size - if: github.event_name == 'push' || !(github.event.pull_request.head.repo.fork) + if: (github.event_name == 'push' || !(github.event.pull_request.head.repo.fork)) && (github.actor != 'dependabot[bot]') runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - uses: 'google-github-actions/auth@v0' with: credentials_json: '${{ secrets.GCP_SA_KEY }}' @@ -52,13 +52,13 @@ jobs: run: yarn size-report modular-export-size: name: Binary Size For Modular Exports - if: github.event_name == 'push' || !(github.event.pull_request.head.repo.fork) + if: (github.event_name == 'push' || !(github.event.pull_request.head.repo.fork)) && (github.actor != 'dependabot[bot]') runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - uses: 'google-github-actions/auth@v0' with: credentials_json: '${{ secrets.GCP_SA_KEY }}' diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 50664c261cb..80851d9834a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,10 +23,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up node (16) + - name: Set up node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: yarn install run: yarn - name: yarn lint diff --git a/.github/workflows/prerelease-manual-deploy.yml b/.github/workflows/prerelease-manual-deploy.yml index a1b0af0e258..a1dfc08d847 100644 --- a/.github/workflows/prerelease-manual-deploy.yml +++ b/.github/workflows/prerelease-manual-deploy.yml @@ -34,10 +34,10 @@ jobs: with: # Canary release script requires git history and tags. fetch-depth: 0 - - name: Set up node (16) + - name: Set up node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Yarn install run: yarn - name: Deploy prerelease @@ -76,6 +76,8 @@ jobs: NPM_TOKEN_STORAGE_TYPES: ${{secrets.NPM_TOKEN_STORAGE_TYPES}} NPM_TOKEN_TESTING: ${{secrets.NPM_TOKEN_TESTING}} NPM_TOKEN_UTIL: ${{secrets.NPM_TOKEN_UTIL}} + NPM_TOKEN_VERTEXAI: ${{secrets.NPM_TOKEN_VERTEXAI}} + NPM_TOKEN_VERTEXAI_PREVIEW: ${{secrets.NPM_TOKEN_VERTEXAI_PREVIEW}} NPM_TOKEN_WEBCHANNEL_WRAPPER: ${{secrets.NPM_TOKEN_WEBCHANNEL_WRAPPER}} NPM_TOKEN_FIREBASE: ${{secrets.NPM_TOKEN_FIREBASE}} NPM_TOKEN_APP_COMPAT: ${{ secrets.NPM_TOKEN_APP_COMPAT }} diff --git a/.github/workflows/release-log.yml b/.github/workflows/release-log.yml index 235a0d142ce..780e3e97b52 100644 --- a/.github/workflows/release-log.yml +++ b/.github/workflows/release-log.yml @@ -28,10 +28,10 @@ jobs: - name: Checkout Repo uses: actions/checkout@master - - name: Setup Node.js 16.x + - name: Setup Node.js 20.x uses: actions/setup-node@master with: - node-version: 16.x + node-version: 20.x - name: Get PR number and send to tracker. run: node scripts/ci/log-changesets.js diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml index 02dc8e3cef5..04ebbd8b926 100644 --- a/.github/workflows/release-pr.yml +++ b/.github/workflows/release-pr.yml @@ -32,10 +32,10 @@ jobs: # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits fetch-depth: 0 - - name: Setup Node.js 16.x + - name: Setup Node.js 20.x uses: actions/setup-node@master with: - node-version: 16.x + node-version: 20.x - name: Install Dependencies run: yarn diff --git a/.github/workflows/release-prod.yml b/.github/workflows/release-prod.yml index 684f405a9ac..6dcedb0b04a 100644 --- a/.github/workflows/release-prod.yml +++ b/.github/workflows/release-prod.yml @@ -32,10 +32,10 @@ jobs: contents: write steps: - - name: Set up node (16) + - name: Set up node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Checkout release branch (with history) uses: actions/checkout@master with: @@ -86,6 +86,8 @@ jobs: NPM_TOKEN_STORAGE_TYPES: ${{secrets.NPM_TOKEN_STORAGE_TYPES}} NPM_TOKEN_TESTING: ${{secrets.NPM_TOKEN_TESTING}} NPM_TOKEN_UTIL: ${{secrets.NPM_TOKEN_UTIL}} + NPM_TOKEN_VERTEXAI: ${{secrets.NPM_TOKEN_VERTEXAI}} + NPM_TOKEN_VERTEXAI_PREVIEW: ${{secrets.NPM_TOKEN_VERTEXAI_PREVIEW}} NPM_TOKEN_WEBCHANNEL_WRAPPER: ${{secrets.NPM_TOKEN_WEBCHANNEL_WRAPPER}} NPM_TOKEN_FIREBASE: ${{secrets.NPM_TOKEN_FIREBASE}} NPM_TOKEN_APP_COMPAT: ${{ secrets.NPM_TOKEN_APP_COMPAT }} diff --git a/.github/workflows/release-staging.yml b/.github/workflows/release-staging.yml index 5b0e2a7cb5f..32eca1f036d 100644 --- a/.github/workflows/release-staging.yml +++ b/.github/workflows/release-staging.yml @@ -46,10 +46,10 @@ jobs: # Block this workflow if run on a non-release branch. if: github.event.inputs.release-branch == 'release' || endsWith(github.event.inputs.release-branch, '-releasebranch') steps: - - name: Set up node (16) + - name: Set up node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Merge master into release uses: actions/github-script@v6 with: @@ -112,6 +112,8 @@ jobs: NPM_TOKEN_STORAGE_TYPES: ${{secrets.NPM_TOKEN_STORAGE_TYPES}} NPM_TOKEN_TESTING: ${{secrets.NPM_TOKEN_TESTING}} NPM_TOKEN_UTIL: ${{secrets.NPM_TOKEN_UTIL}} + NPM_TOKEN_VERTEXAI: ${{secrets.NPM_TOKEN_VERTEXAI}} + NPM_TOKEN_VERTEXAI_PREVIEW: ${{secrets.NPM_TOKEN_VERTEXAI_PREVIEW}} NPM_TOKEN_WEBCHANNEL_WRAPPER: ${{secrets.NPM_TOKEN_WEBCHANNEL_WRAPPER}} NPM_TOKEN_FIREBASE: ${{secrets.NPM_TOKEN_FIREBASE}} NPM_TOKEN_APP_COMPAT: ${{ secrets.NPM_TOKEN_APP_COMPAT }} diff --git a/.github/workflows/release-tweet.yml b/.github/workflows/release-tweet.yml index af6379ceb18..edd2634637b 100644 --- a/.github/workflows/release-tweet.yml +++ b/.github/workflows/release-tweet.yml @@ -34,10 +34,10 @@ jobs: steps: - name: Checkout Repo uses: actions/checkout@master - - name: Setup Node.js 16.x + - name: Setup Node.js 20.x uses: actions/setup-node@master with: - node-version: 16.x + node-version: 20.x - name: Poll release notes page on devsite run: node scripts/ci/poll_release_notes.js env: diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 10d67c00930..1a5cc20a2ef 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -24,7 +24,7 @@ env: # The default behavior of chromedriver uses the older Chrome download URLs. We need to override # the beahvior to use the new URLs. CHROMEDRIVER_CDNURL: https://googlechromelabs.github.io/ - CHROMEDRIVER_CDNBINARIESURL: https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/ + CHROMEDRIVER_CDNBINARIESURL: https://storage.googleapis.com/chrome-for-testing-public CHROME_VALIDATED_VERSION: linux-120.0.6099.71 CHROME_VERSION_MISMATCH_MESSAGE: "The Chrome version doesn't match the previously validated version. Consider updating CHROME_VALIDATED_VERSION in the GitHub workflow if tests pass." artifactRetentionDays: 14 @@ -42,10 +42,10 @@ jobs: run: | npx @puppeteer/browsers install chrome@stable - uses: actions/checkout@v3 - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Test setup and yarn install run: | cp config/ci.config.json config/project.json @@ -81,10 +81,10 @@ jobs: name: build.tar.gz - name: Unzip build artifact run: tar xf build.tar.gz - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Test setup and yarn install run: | cp config/ci.config.json config/project.json @@ -132,10 +132,10 @@ jobs: name: build.tar.gz - name: Unzip build artifact run: tar xf build.tar.gz - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Test setup and yarn install run: | cp config/ci.config.json config/project.json @@ -161,9 +161,6 @@ jobs: name: (Firestore) Node.js and Browser (Chrome) Tests needs: build runs-on: ubuntu-latest - if: false - # Disable test for now since it's failing 100% of the time since - # https://github.com/firebase/firebase-js-sdk/pull/7453 and it needs to be investigated. steps: # install Chrome so the correct version of webdriver can be installed by chromedriver when setting up the repo - name: install Chrome stable @@ -175,10 +172,10 @@ jobs: name: build.tar.gz - name: Unzip build artifact run: tar xf build.tar.gz - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Test setup and yarn install run: | cp config/ci.config.json config/project.json @@ -219,10 +216,10 @@ jobs: name: build.tar.gz - name: Unzip build artifact run: tar xf build.tar.gz - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - run: cp config/ci.config.json config/project.json - run: yarn - run: yarn build:${{ matrix.persistence }} diff --git a/.github/workflows/test-changed-auth.yml b/.github/workflows/test-changed-auth.yml index 2eba81a8e99..d2f11f2bf2f 100644 --- a/.github/workflows/test-changed-auth.yml +++ b/.github/workflows/test-changed-auth.yml @@ -22,7 +22,7 @@ env: # The default behavior of chromedriver uses the older Chrome download URLs. We need to override # the beahvior to use the new URLs. CHROMEDRIVER_CDNURL: https://googlechromelabs.github.io/ - CHROMEDRIVER_CDNBINARIESURL: https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/ + CHROMEDRIVER_CDNBINARIESURL: https://storage.googleapis.com/chrome-for-testing-public CHROME_VALIDATED_VERSION: linux-120.0.6099.71 # Bump Node memory limit NODE_OPTIONS: "--max_old_space_size=4096" @@ -56,10 +56,10 @@ jobs: with: # This makes Actions fetch all Git history so run-changed script can diff properly. fetch-depth: 0 - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Test setup and yarn install run: | cp config/ci.config.json config/project.json @@ -88,10 +88,10 @@ jobs: with: # This makes Actions fetch all Git history so run-changed script can diff properly. fetch-depth: 0 - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Test setup and yarn install run: | cp config/ci.config.json config/project.json diff --git a/.github/workflows/test-changed-fcm-integration.yml b/.github/workflows/test-changed-fcm-integration.yml index bac3a772428..affb4639b1b 100644 --- a/.github/workflows/test-changed-fcm-integration.yml +++ b/.github/workflows/test-changed-fcm-integration.yml @@ -38,10 +38,10 @@ jobs: with: # This makes Actions fetch all Git history so run-changed script can diff properly. fetch-depth: 0 - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Test setup and yarn install run: | cp config/ci.config.json config/project.json diff --git a/.github/workflows/test-changed-firestore-integration.yml b/.github/workflows/test-changed-firestore-integration.yml index 106aef667e7..85e9c7e3eaa 100644 --- a/.github/workflows/test-changed-firestore-integration.yml +++ b/.github/workflows/test-changed-firestore-integration.yml @@ -24,6 +24,8 @@ jobs: test: name: Test Firestore Integration If Changed runs-on: ubuntu-latest + env: + run_terraform_steps: ${{ secrets.JSSDK_ACTIONS_SA_KEY != '' }} steps: - name: Checkout Repo @@ -32,20 +34,23 @@ jobs: # This makes Actions fetch all Git history so run-changed script can diff properly. fetch-depth: 0 - uses: 'google-github-actions/auth@v0' + if: ${{ fromJSON(env.run_terraform_steps) }} with: credentials_json: '${{ secrets.JSSDK_ACTIONS_SA_KEY }}' - + # create composite indexes with Terraform - - name: Setup Terraform + - name: Setup Terraform + if: ${{ fromJSON(env.run_terraform_steps) }} uses: hashicorp/setup-terraform@v2 - name: Terraform Init + if: ${{ fromJSON(env.run_terraform_steps) }} run: | cp config/ci.config.json config/project.json cd packages/firestore terraform init continue-on-error: true - name: Terraform Apply - if: github.event_name == 'pull_request' + if: github.event_name == 'pull_request' && fromJSON(env.run_terraform_steps) run: | cd packages/firestore @@ -63,10 +68,10 @@ jobs: rm -f "$output_file" continue-on-error: true - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: install Chrome stable run: | sudo apt-get update diff --git a/.github/workflows/test-changed-firestore.yml b/.github/workflows/test-changed-firestore.yml index c34e4e79dce..9f241898e0e 100644 --- a/.github/workflows/test-changed-firestore.yml +++ b/.github/workflows/test-changed-firestore.yml @@ -37,10 +37,10 @@ jobs: with: # This makes Actions fetch all Git history so run-changed script can diff properly. fetch-depth: 0 - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: install Chrome stable run: | sudo apt-get update @@ -84,10 +84,10 @@ jobs: needs: build if: ${{ needs.build.outputs.changed == 'true'}} steps: - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: install Chrome stable run: | sudo apt-get update @@ -112,10 +112,10 @@ jobs: needs: build if: ${{ needs.build.outputs.changed == 'true'}} steps: - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: install Chrome stable run: | sudo apt-get update @@ -142,10 +142,10 @@ jobs: needs: build if: ${{ github.event_name != 'pull_request' }} steps: - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: install Chrome stable run: | sudo apt-get update @@ -180,10 +180,10 @@ jobs: run: | sudo apt-get update sudo apt-get install firefox - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Download build archive uses: actions/download-artifact@v3 with: @@ -219,10 +219,10 @@ jobs: name: build.tar.gz - name: Unzip build artifact run: tar xf build.tar.gz - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Test setup and yarn install run: cp config/ci.config.json config/project.json - name: Run tests diff --git a/.github/workflows/test-changed-misc.yml b/.github/workflows/test-changed-misc.yml index 3e87f5f5584..e189ff4fecf 100644 --- a/.github/workflows/test-changed-misc.yml +++ b/.github/workflows/test-changed-misc.yml @@ -31,10 +31,10 @@ jobs: with: # This makes Actions fetch all Git history so run-changed script can diff properly. fetch-depth: 0 - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: install Chrome stable run: | sudo apt-get update diff --git a/.github/workflows/test-changed.yml b/.github/workflows/test-changed.yml index f0cf68f7315..ac45286b0c8 100644 --- a/.github/workflows/test-changed.yml +++ b/.github/workflows/test-changed.yml @@ -31,10 +31,10 @@ jobs: with: # This makes Actions fetch all Git history so run-changed script can diff properly. fetch-depth: 0 - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: install Chrome stable run: | sudo apt-get update @@ -60,10 +60,10 @@ jobs: uses: actions/checkout@master with: fetch-depth: 0 - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: install Firefox stable run: | sudo apt-get update diff --git a/.github/workflows/test-firebase-integration.yml b/.github/workflows/test-firebase-integration.yml index 9eb15ab78d2..f6b1eb3c4b3 100644 --- a/.github/workflows/test-firebase-integration.yml +++ b/.github/workflows/test-firebase-integration.yml @@ -31,10 +31,10 @@ jobs: with: # This makes Actions fetch all Git history so run-changed script can diff properly. fetch-depth: 0 - - name: Set up Node (16) + - name: Set up Node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: install Chrome stable run: | sudo apt-get update diff --git a/.github/workflows/update-api-reports.yml b/.github/workflows/update-api-reports.yml index e4f90c98607..f49c548e3cc 100644 --- a/.github/workflows/update-api-reports.yml +++ b/.github/workflows/update-api-reports.yml @@ -30,10 +30,10 @@ jobs: # checkout HEAD commit instead of merge commit ref: ${{ github.event.pull_request.head.ref }} token: ${{ github.token }} - - name: Set up node (16) + - name: Set up node (20) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x - name: Yarn install run: yarn - name: Update API reports diff --git a/.gitignore b/.gitignore index c2e2136eece..e15c88b7ae7 100644 --- a/.gitignore +++ b/.gitignore @@ -98,3 +98,6 @@ toc/ .terraform.lock.hcl *.tfstate *.tfstate.* + +# generated test case text data +mocks-lookup.ts \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000000..e69de29bb2d diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b9cc6c21260..d504afe7833 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -154,7 +154,7 @@ That's it! Thank you for your contribution! #### Adding changeset to PR The repository uses changesets to associate PR contributions with major and minor version releases -adn patch releases. If your change is a feature or a behavioral change (either of which should +and patch releases. If your change is a feature or a behavioral change (either of which should correspond to a version bump) then you will need to generate a changeset in your PR to track the change. @@ -165,8 +165,7 @@ repository: yarn changeset ``` -You will be asked to create a description (here's an -[example]((https://github.com/firebase/firebase-js-sdk/pull/3284#issuecomment-649718617)). You +You will be asked to create a description (here's an [example](https://github.com/firebase/firebase-js-sdk/pull/3284#issuecomment-649718617)). You should include the version bump for your package as well as the description for the change. Valid version bump types are major, minor or patch, where: diff --git a/LICENSE b/LICENSE index d636db9ddaf..4627db48cf6 100644 --- a/LICENSE +++ b/LICENSE @@ -203,6 +203,23 @@ which is licensed under BSD-3-Clause, both licenses given below. See the License for the specific language governing permissions and limitations under the License. +------------------------------------------------------------------------------- + +For tslib. + +file: [source code root]/packages/firebase + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + ------------------------------------------------------------------------------ For Google protobuf source. diff --git a/README.md b/README.md index c46b1ee21e4..dadbc48ec36 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,8 @@ Please see [Environment Support](https://firebase.google.com/support/guides/envi #### Node.js Before you can start working on the Firebase JS SDK, you need to have Node.js -installed on your machine. As of June 13th, 2023 the team has been testing with Node.js versions -between `16.4.0` and `16.16.0`, but the required verison of Node.js may change as we update -our dependencies. +installed on your machine. As of April 19th, 2024 the team has been testing with Node.js version +`20.12.2`, but the required verison of Node.js may change as we update our dependencies. To download Node.js visit https://nodejs.org/en/download/. @@ -64,7 +63,7 @@ $ yarn -v $ java -version ``` -Your `node` version should be between `16.4.0` and `16.6.0`, your `yarn` version should +Your `node` version should be `20.12.2`, your `yarn` version should be between `1.0.0` and `1.22.11`, and your `java` version should be `11.0` or greater. _NOTE: We will update the documentation as new versions are required, however diff --git a/common/api-review/analytics.api.md b/common/api-review/analytics.api.md index 7b6e9cfb182..58cb8d4a0ce 100644 --- a/common/api-review/analytics.api.md +++ b/common/api-review/analytics.api.md @@ -25,7 +25,9 @@ export interface AnalyticsSettings { export interface ConsentSettings { // (undocumented) [key: string]: unknown; + ad_personalization?: ConsentStatusString; ad_storage?: ConsentStatusString; + ad_user_data?: ConsentStatusString; analytics_storage?: ConsentStatusString; functionality_storage?: ConsentStatusString; personalization_storage?: ConsentStatusString; diff --git a/common/api-review/app.api.md b/common/api-review/app.api.md index 52f134dac16..e226940ef1b 100644 --- a/common/api-review/app.api.md +++ b/common/api-review/app.api.md @@ -71,6 +71,19 @@ export interface FirebaseOptions { storageBucket?: string; } +// @public +export interface FirebaseServerApp extends FirebaseApp { + name: string; + readonly settings: FirebaseServerAppSettings; +} + +// @public +export interface FirebaseServerAppSettings extends FirebaseAppSettings { + authIdToken?: string; + name?: undefined; + releaseOnDeref?: object; +} + // @internal (undocumented) export interface _FirebaseService { // (undocumented) @@ -96,6 +109,15 @@ export function initializeApp(options: FirebaseOptions, config?: FirebaseAppSett // @public export function initializeApp(): FirebaseApp; +// @public +export function initializeServerApp(options: FirebaseOptions | FirebaseApp, config: FirebaseServerAppSettings): FirebaseServerApp; + +// @internal (undocumented) +export function _isFirebaseApp(obj: FirebaseApp | FirebaseOptions): obj is FirebaseApp; + +// @internal (undocumented) +export function _isFirebaseServerApp(obj: FirebaseApp | FirebaseServerApp): obj is FirebaseServerApp; + // @public export function onLog(logCallback: LogCallback | null, options?: LogOptions): void; @@ -111,6 +133,9 @@ export function _removeServiceInstance(app: FirebaseApp, name: T // @public export const SDK_VERSION: string; +// @internal (undocumented) +export const _serverApps: Map; + // @public export function setLogLevel(logLevel: LogLevelString): void; diff --git a/common/api-review/firestore.api.md b/common/api-review/firestore.api.md index ee4fcc842ff..f79ef52442e 100644 --- a/common/api-review/firestore.api.md +++ b/common/api-review/firestore.api.md @@ -350,6 +350,9 @@ export function limit(limit: number): QueryLimitConstraint; // @public export function limitToLast(limit: number): QueryLimitConstraint; +// @public +export type ListenSource = 'default' | 'cache'; + // @public export function loadBundle(firestore: Firestore, bundleData: ReadableStream | ArrayBuffer | string): LoadBundleTask; @@ -651,6 +654,7 @@ export function snapshotEqual(le // @public export interface SnapshotListenOptions { readonly includeMetadataChanges?: boolean; + readonly source?: ListenSource; } // @public diff --git a/common/api-review/vertexai-preview.api.md b/common/api-review/vertexai-preview.api.md new file mode 100644 index 00000000000..b3ae09e8dc7 --- /dev/null +++ b/common/api-review/vertexai-preview.api.md @@ -0,0 +1,614 @@ +## API Report File for "@firebase/vertexai-preview" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { AppCheckTokenResult } from '@firebase/app-check-interop-types'; +import { FirebaseApp } from '@firebase/app'; +import { FirebaseAuthTokenData } from '@firebase/auth-interop-types'; + +// @public +export interface BaseParams { + // (undocumented) + generationConfig?: GenerationConfig; + // (undocumented) + safetySettings?: SafetySetting[]; +} + +// @public +export enum BlockReason { + // (undocumented) + BLOCKED_REASON_UNSPECIFIED = "BLOCKED_REASON_UNSPECIFIED", + // (undocumented) + OTHER = "OTHER", + // (undocumented) + SAFETY = "SAFETY" +} + +// @public +export class ChatSession { + // Warning: (ae-forgotten-export) The symbol "ApiSettings" needs to be exported by the entry point index.d.ts + constructor(apiSettings: ApiSettings, model: string, params?: StartChatParams | undefined, requestOptions?: RequestOptions | undefined); + getHistory(): Promise; + // (undocumented) + model: string; + // (undocumented) + params?: StartChatParams | undefined; + // (undocumented) + requestOptions?: RequestOptions | undefined; + sendMessage(request: string | Array): Promise; + sendMessageStream(request: string | Array): Promise; + } + +// @public +export interface Citation { + // (undocumented) + endIndex?: number; + // (undocumented) + license?: string; + // (undocumented) + publicationDate?: Date_2; + // (undocumented) + startIndex?: number; + // (undocumented) + title?: string; + // (undocumented) + uri?: string; +} + +// @public +export interface CitationMetadata { + // (undocumented) + citations: Citation[]; +} + +// @public +export interface Content { + // (undocumented) + parts: Part[]; + // (undocumented) + role: Role; +} + +// @public +export interface CountTokensRequest { + // (undocumented) + contents: Content[]; +} + +// @public +export interface CountTokensResponse { + totalBillableCharacters?: number; + totalTokens: number; +} + +// @public +interface Date_2 { + // (undocumented) + day: number; + // (undocumented) + month: number; + // (undocumented) + year: number; +} + +export { Date_2 as Date } + +// @public +export interface EnhancedGenerateContentResponse extends GenerateContentResponse { + // (undocumented) + functionCalls: () => FunctionCall[] | undefined; + text: () => string; +} + +// @public +export interface FileData { + // (undocumented) + fileUri: string; + // (undocumented) + mimeType: string; +} + +// @public +export interface FileDataPart { + // (undocumented) + fileData: FileData; + // (undocumented) + functionCall?: never; + // (undocumented) + functionResponse?: never; + // (undocumented) + inlineData?: never; + // (undocumented) + text?: never; +} + +// @public +export enum FinishReason { + // (undocumented) + FINISH_REASON_UNSPECIFIED = "FINISH_REASON_UNSPECIFIED", + // (undocumented) + MAX_TOKENS = "MAX_TOKENS", + // (undocumented) + OTHER = "OTHER", + // (undocumented) + RECITATION = "RECITATION", + // (undocumented) + SAFETY = "SAFETY", + // (undocumented) + STOP = "STOP" +} + +// @public +export interface FunctionCall { + // (undocumented) + args: object; + // (undocumented) + name: string; +} + +// @public (undocumented) +export interface FunctionCallingConfig { + // (undocumented) + allowedFunctionNames?: string[]; + // (undocumented) + mode?: FunctionCallingMode; +} + +// @public (undocumented) +export enum FunctionCallingMode { + // (undocumented) + ANY = "ANY", + // (undocumented) + AUTO = "AUTO", + // (undocumented) + MODE_UNSPECIFIED = "MODE_UNSPECIFIED", + // (undocumented) + NONE = "NONE" +} + +// @public +export interface FunctionCallPart { + // (undocumented) + functionCall: FunctionCall; + // (undocumented) + functionResponse?: never; + // (undocumented) + inlineData?: never; + // (undocumented) + text?: never; +} + +// @public +export interface FunctionDeclaration { + description?: string; + name: string; + parameters?: FunctionDeclarationSchema; +} + +// @public +export interface FunctionDeclarationSchema { + description?: string; + properties: { + [k: string]: FunctionDeclarationSchemaProperty; + }; + required?: string[]; + type: FunctionDeclarationSchemaType; +} + +// @public +export interface FunctionDeclarationSchemaProperty { + description?: string; + enum?: string[]; + example?: unknown; + format?: string; + items?: FunctionDeclarationSchema; + nullable?: boolean; + properties?: { + [k: string]: FunctionDeclarationSchema; + }; + required?: string[]; + type?: FunctionDeclarationSchemaType; +} + +// @public +export enum FunctionDeclarationSchemaType { + ARRAY = "ARRAY", + BOOLEAN = "BOOLEAN", + INTEGER = "INTEGER", + NUMBER = "NUMBER", + OBJECT = "OBJECT", + STRING = "STRING" +} + +// @public +export interface FunctionDeclarationsTool { + functionDeclarations?: FunctionDeclaration[]; +} + +// @public +export interface FunctionResponse { + // (undocumented) + name: string; + // (undocumented) + response: object; +} + +// @public +export interface FunctionResponsePart { + // (undocumented) + functionCall?: never; + // (undocumented) + functionResponse: FunctionResponse; + // (undocumented) + inlineData?: never; + // (undocumented) + text?: never; +} + +// @public +export interface GenerateContentCandidate { + // (undocumented) + citationMetadata?: CitationMetadata; + // (undocumented) + content: Content; + // (undocumented) + finishMessage?: string; + // (undocumented) + finishReason?: FinishReason; + // (undocumented) + groundingMetadata?: GroundingMetadata; + // (undocumented) + index: number; + // (undocumented) + safetyRatings?: SafetyRating[]; +} + +// @public +export interface GenerateContentRequest extends BaseParams { + // (undocumented) + contents: Content[]; + // (undocumented) + systemInstruction?: string | Part | Content; + // (undocumented) + toolConfig?: ToolConfig; + // (undocumented) + tools?: Tool[]; +} + +// @public +export interface GenerateContentResponse { + // (undocumented) + candidates?: GenerateContentCandidate[]; + // (undocumented) + promptFeedback?: PromptFeedback; + // (undocumented) + usageMetadata?: UsageMetadata; +} + +// @public +export interface GenerateContentResult { + // (undocumented) + response: EnhancedGenerateContentResponse; +} + +// @public +export interface GenerateContentStreamResult { + // (undocumented) + response: Promise; + // (undocumented) + stream: AsyncGenerator; +} + +// @public +export interface GenerationConfig { + // (undocumented) + candidateCount?: number; + // (undocumented) + frequencyPenalty?: number; + // (undocumented) + maxOutputTokens?: number; + // (undocumented) + presencePenalty?: number; + responseMimeType?: string; + // (undocumented) + stopSequences?: string[]; + // (undocumented) + temperature?: number; + // (undocumented) + topK?: number; + // (undocumented) + topP?: number; +} + +// @public +export interface GenerativeContentBlob { + data: string; + // (undocumented) + mimeType: string; +} + +// @public +export class GenerativeModel { + constructor(vertexAI: VertexAI, modelParams: ModelParams, requestOptions?: RequestOptions); + countTokens(request: CountTokensRequest | string | Array): Promise; + generateContent(request: GenerateContentRequest | string | Array): Promise; + generateContentStream(request: GenerateContentRequest | string | Array): Promise; + // (undocumented) + generationConfig: GenerationConfig; + // (undocumented) + model: string; + // (undocumented) + requestOptions?: RequestOptions; + // (undocumented) + safetySettings: SafetySetting[]; + startChat(startChatParams?: StartChatParams): ChatSession; + // (undocumented) + systemInstruction?: Content; + // (undocumented) + toolConfig?: ToolConfig; + // (undocumented) + tools?: Tool[]; +} + +// @public +export function getGenerativeModel(vertexAI: VertexAI, modelParams: ModelParams, requestOptions?: RequestOptions): GenerativeModel; + +// @public +export function getVertexAI(app?: FirebaseApp, options?: VertexAIOptions): VertexAI; + +// @public (undocumented) +export interface GroundingAttribution { + // (undocumented) + confidenceScore?: number; + // (undocumented) + retrievedContext?: RetrievedContextAttribution; + // (undocumented) + segment: Segment; + // (undocumented) + web?: WebAttribution; +} + +// @public +export interface GroundingMetadata { + // (undocumented) + groundingAttributions: GroundingAttribution[]; + // (undocumented) + retrievalQueries?: string[]; + // (undocumented) + webSearchQueries?: string[]; +} + +// @public (undocumented) +export enum HarmBlockMethod { + // (undocumented) + HARM_BLOCK_METHOD_UNSPECIFIED = "HARM_BLOCK_METHOD_UNSPECIFIED", + // (undocumented) + PROBABILITY = "PROBABILITY", + // (undocumented) + SEVERITY = "SEVERITY" +} + +// @public +export enum HarmBlockThreshold { + // (undocumented) + BLOCK_LOW_AND_ABOVE = "BLOCK_LOW_AND_ABOVE", + // (undocumented) + BLOCK_MEDIUM_AND_ABOVE = "BLOCK_MEDIUM_AND_ABOVE", + // (undocumented) + BLOCK_NONE = "BLOCK_NONE", + // (undocumented) + BLOCK_ONLY_HIGH = "BLOCK_ONLY_HIGH", + // (undocumented) + HARM_BLOCK_THRESHOLD_UNSPECIFIED = "HARM_BLOCK_THRESHOLD_UNSPECIFIED" +} + +// @public +export enum HarmCategory { + // (undocumented) + HARM_CATEGORY_DANGEROUS_CONTENT = "HARM_CATEGORY_DANGEROUS_CONTENT", + // (undocumented) + HARM_CATEGORY_HARASSMENT = "HARM_CATEGORY_HARASSMENT", + // (undocumented) + HARM_CATEGORY_HATE_SPEECH = "HARM_CATEGORY_HATE_SPEECH", + // (undocumented) + HARM_CATEGORY_SEXUALLY_EXPLICIT = "HARM_CATEGORY_SEXUALLY_EXPLICIT", + // (undocumented) + HARM_CATEGORY_UNSPECIFIED = "HARM_CATEGORY_UNSPECIFIED" +} + +// @public +export enum HarmProbability { + // (undocumented) + HARM_PROBABILITY_UNSPECIFIED = "HARM_PROBABILITY_UNSPECIFIED", + // (undocumented) + HIGH = "HIGH", + // (undocumented) + LOW = "LOW", + // (undocumented) + MEDIUM = "MEDIUM", + // (undocumented) + NEGLIGIBLE = "NEGLIGIBLE" +} + +// @public +export enum HarmSeverity { + // (undocumented) + HARM_SEVERITY_HIGH = "HARM_SEVERITY_HIGH", + // (undocumented) + HARM_SEVERITY_LOW = "HARM_SEVERITY_LOW", + // (undocumented) + HARM_SEVERITY_MEDIUM = "HARM_SEVERITY_MEDIUM", + // (undocumented) + HARM_SEVERITY_NEGLIGIBLE = "HARM_SEVERITY_NEGLIGIBLE", + // (undocumented) + HARM_SEVERITY_UNSPECIFIED = "HARM_SEVERITY_UNSPECIFIED" +} + +// @public +export interface InlineDataPart { + // (undocumented) + functionCall?: never; + // (undocumented) + functionResponse?: never; + // (undocumented) + inlineData: GenerativeContentBlob; + // (undocumented) + text?: never; + videoMetadata?: VideoMetadata; +} + +// @public +export interface ModelParams extends BaseParams { + // (undocumented) + model: string; + // (undocumented) + systemInstruction?: string | Part | Content; + // (undocumented) + toolConfig?: ToolConfig; + // (undocumented) + tools?: Tool[]; +} + +// @public +export type Part = TextPart | InlineDataPart | FunctionCallPart | FunctionResponsePart | FileDataPart; + +// @public +export const POSSIBLE_ROLES: readonly ["user", "model", "function", "system"]; + +// @public +export interface PromptFeedback { + // (undocumented) + blockReason: BlockReason; + // (undocumented) + blockReasonMessage?: string; + // (undocumented) + safetyRatings: SafetyRating[]; +} + +// @public +export interface RequestOptions { + baseUrl?: string; + timeout?: number; +} + +// @public (undocumented) +export interface RetrievedContextAttribution { + // (undocumented) + title: string; + // (undocumented) + uri: string; +} + +// @public +export type Role = (typeof POSSIBLE_ROLES)[number]; + +// @public +export interface SafetyRating { + // (undocumented) + blocked: boolean; + // (undocumented) + category: HarmCategory; + // (undocumented) + probability: HarmProbability; + // (undocumented) + probabilityScore: number; + // (undocumented) + severity: HarmSeverity; + // (undocumented) + severityScore: number; +} + +// @public +export interface SafetySetting { + // (undocumented) + category: HarmCategory; + // (undocumented) + method: HarmBlockMethod; + // (undocumented) + threshold: HarmBlockThreshold; +} + +// @public (undocumented) +export interface Segment { + // (undocumented) + endIndex: number; + // (undocumented) + partIndex: number; + // (undocumented) + startIndex: number; +} + +// @public +export interface StartChatParams extends BaseParams { + // (undocumented) + history?: Content[]; + // (undocumented) + systemInstruction?: string | Part | Content; + // (undocumented) + toolConfig?: ToolConfig; + // (undocumented) + tools?: Tool[]; +} + +// @public +export interface TextPart { + // (undocumented) + functionCall?: never; + // (undocumented) + functionResponse?: never; + // (undocumented) + inlineData?: never; + // (undocumented) + text: string; +} + +// @public +export type Tool = FunctionDeclarationsTool; + +// @public +export interface ToolConfig { + // (undocumented) + functionCallingConfig: FunctionCallingConfig; +} + +// @public +export interface UsageMetadata { + // (undocumented) + candidatesTokenCount: number; + // (undocumented) + promptTokenCount: number; + // (undocumented) + totalTokenCount: number; +} + +// @public +export interface VertexAI { + app: FirebaseApp; + // (undocumented) + location: string; +} + +// @public +export interface VertexAIOptions { + // (undocumented) + location?: string; +} + +// @public +export interface VideoMetadata { + endOffset: string; + startOffset: string; +} + +// @public (undocumented) +export interface WebAttribution { + // (undocumented) + title: string; + // (undocumented) + uri: string; +} + + +``` diff --git a/config/functions/package.json b/config/functions/package.json index 083fc2a5e9f..08a79673e85 100644 --- a/config/functions/package.json +++ b/config/functions/package.json @@ -3,7 +3,7 @@ "description": "Cloud Functions for Firebase", "dependencies": { "cors": "2.8.5", - "firebase-admin": "11.10.1", + "firebase-admin": "11.11.1", "firebase-functions": "3.24.1" }, "private": true, diff --git a/config/tsconfig.base.json b/config/tsconfig.base.json index cf88a789aa2..0b585359a36 100644 --- a/config/tsconfig.base.json +++ b/config/tsconfig.base.json @@ -15,6 +15,7 @@ "es2015.core", "es2017.object", "es2017.string", + "ESNext.WeakRef", ], "module": "ES2015", "moduleResolution": "node", diff --git a/docs-devsite/analytics.consentsettings.md b/docs-devsite/analytics.consentsettings.md index 975d51d8bc6..9e01460a31a 100644 --- a/docs-devsite/analytics.consentsettings.md +++ b/docs-devsite/analytics.consentsettings.md @@ -22,12 +22,24 @@ export interface ConsentSettings | Property | Type | Description | | --- | --- | --- | +| [ad\_personalization](./analytics.consentsettings.md#consentsettingsad_personalization) | [ConsentStatusString](./analytics.md#consentstatusstring) | Sets consent for personalized advertising. | | [ad\_storage](./analytics.consentsettings.md#consentsettingsad_storage) | [ConsentStatusString](./analytics.md#consentstatusstring) | Enables storage, such as cookies, related to advertising | +| [ad\_user\_data](./analytics.consentsettings.md#consentsettingsad_user_data) | [ConsentStatusString](./analytics.md#consentstatusstring) | Sets consent for sending user data to Google for advertising purposes. | | [analytics\_storage](./analytics.consentsettings.md#consentsettingsanalytics_storage) | [ConsentStatusString](./analytics.md#consentstatusstring) | Enables storage, such as cookies, related to analytics (for example, visit duration) | | [functionality\_storage](./analytics.consentsettings.md#consentsettingsfunctionality_storage) | [ConsentStatusString](./analytics.md#consentstatusstring) | Enables storage that supports the functionality of the website or app such as language settings | | [personalization\_storage](./analytics.consentsettings.md#consentsettingspersonalization_storage) | [ConsentStatusString](./analytics.md#consentstatusstring) | Enables storage related to personalization such as video recommendations | | [security\_storage](./analytics.consentsettings.md#consentsettingssecurity_storage) | [ConsentStatusString](./analytics.md#consentstatusstring) | Enables storage related to security such as authentication functionality, fraud prevention, and other user protection. | +## ConsentSettings.ad\_personalization + +Sets consent for personalized advertising. + +Signature: + +```typescript +ad_personalization?: ConsentStatusString; +``` + ## ConsentSettings.ad\_storage Enables storage, such as cookies, related to advertising @@ -38,6 +50,16 @@ Enables storage, such as cookies, related to advertising ad_storage?: ConsentStatusString; ``` +## ConsentSettings.ad\_user\_data + +Sets consent for sending user data to Google for advertising purposes. + +Signature: + +```typescript +ad_user_data?: ConsentStatusString; +``` + ## ConsentSettings.analytics\_storage Enables storage, such as cookies, related to analytics (for example, visit duration) diff --git a/docs-devsite/analytics.gtagconfigparams.md b/docs-devsite/analytics.gtagconfigparams.md index f5138b8b65e..c2931e4f637 100644 --- a/docs-devsite/analytics.gtagconfigparams.md +++ b/docs-devsite/analytics.gtagconfigparams.md @@ -29,9 +29,9 @@ export interface GtagConfigParams | [cookie\_flags](./analytics.gtagconfigparams.md#gtagconfigparamscookie_flags) | string | Appends additional flags to the cookie when set. See [Cookies and user identification](https://developers.google.com/analytics/devguides/collection/ga4/cookies-user-id) | | [cookie\_prefix](./analytics.gtagconfigparams.md#gtagconfigparamscookie_prefix) | string | Defaults to _ga. See [Cookies and user identification](https://developers.google.com/analytics/devguides/collection/ga4/cookies-user-id) | | [cookie\_update](./analytics.gtagconfigparams.md#gtagconfigparamscookie_update) | boolean | If set to true, will update cookies on each page load. Defaults to true. See [Cookies and user identification](https://developers.google.com/analytics/devguides/collection/ga4/cookies-user-id) | -| [page\_location](./analytics.gtagconfigparams.md#gtagconfigparamspage_location) | string | The URL of the page. See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/page-view) | -| [page\_title](./analytics.gtagconfigparams.md#gtagconfigparamspage_title) | string | The title of the page. See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/page-view) | -| [send\_page\_view](./analytics.gtagconfigparams.md#gtagconfigparamssend_page_view) | boolean | Whether or not a page view should be sent. If set to true (default), a page view is automatically sent upon initialization of analytics. See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/page-view) | +| [page\_location](./analytics.gtagconfigparams.md#gtagconfigparamspage_location) | string | The URL of the page. See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/views) | +| [page\_title](./analytics.gtagconfigparams.md#gtagconfigparamspage_title) | string | The title of the page. See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/views) | +| [send\_page\_view](./analytics.gtagconfigparams.md#gtagconfigparamssend_page_view) | boolean | Whether or not a page view should be sent. If set to true (default), a page view is automatically sent upon initialization of analytics. See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/views) | ## GtagConfigParams.allow\_ad\_personalization\_signals @@ -105,7 +105,7 @@ If set to true, will update cookies on each page load. Defaults to true. See [Co ## GtagConfigParams.page\_location -The URL of the page. See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/page-view) +The URL of the page. See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/views) Signature: @@ -115,7 +115,7 @@ The URL of the page. See [Page views](https://developers.google.com/analytics/de ## GtagConfigParams.page\_title -The title of the page. See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/page-view) +The title of the page. See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/views) Signature: @@ -125,7 +125,7 @@ The title of the page. See [Page views](https://developers.google.com/analytics/ ## GtagConfigParams.send\_page\_view -Whether or not a page view should be sent. If set to true (default), a page view is automatically sent upon initialization of analytics. See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/page-view) +Whether or not a page view should be sent. If set to true (default), a page view is automatically sent upon initialization of analytics. See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/views) Signature: diff --git a/docs-devsite/analytics.md b/docs-devsite/analytics.md index 5427a2c90b7..fe4fa13a68d 100644 --- a/docs-devsite/analytics.md +++ b/docs-devsite/analytics.md @@ -42,7 +42,7 @@ The Firebase Analytics Web SDK. This SDK does not work in a Node.js environment. | [logEvent(analyticsInstance, eventName, eventParams, options)](./analytics.md#logevent_800159e) | Sends a Google Analytics event with given eventParams. This method automatically associates this logged event with this Firebase web app instance on this device.See [Measure exceptions](https://developers.google.com/analytics/devguides/collection/ga4/exceptions). | | [logEvent(analyticsInstance, eventName, eventParams, options)](./analytics.md#logevent_9c11aa9) | Sends a Google Analytics event with given eventParams. This method automatically associates this logged event with this Firebase web app instance on this device.List of recommended event parameters can be found in [the GA4 reference documentation](https://developers.google.com/gtagjs/reference/ga4-events). | | [logEvent(analyticsInstance, eventName, eventParams, options)](./analytics.md#logevent_1f3f282) | Sends a Google Analytics event with given eventParams. This method automatically associates this logged event with this Firebase web app instance on this device.List of recommended event parameters can be found in [the GA4 reference documentation](https://developers.google.com/gtagjs/reference/ga4-events). | -| [logEvent(analyticsInstance, eventName, eventParams, options)](./analytics.md#logevent_0792e28) | Sends a Google Analytics event with given eventParams. This method automatically associates this logged event with this Firebase web app instance on this device.See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/page-view). | +| [logEvent(analyticsInstance, eventName, eventParams, options)](./analytics.md#logevent_0792e28) | Sends a Google Analytics event with given eventParams. This method automatically associates this logged event with this Firebase web app instance on this device.See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/views). | | [setAnalyticsCollectionEnabled(analyticsInstance, enabled)](./analytics.md#setanalyticscollectionenabled_494179c) | Sets whether Google Analytics collection is enabled for this app on this device. Sets global window['ga-disable-analyticsId'] = true; | | [setCurrentScreen(analyticsInstance, screenName, options)](./analytics.md#setcurrentscreen_a6168fa) | Use gtag config command to set screen_name. | | [setUserId(analyticsInstance, id, options)](./analytics.md#setuserid_86d82f6) | Use gtag config command to set user_id. | @@ -780,7 +780,7 @@ void Sends a Google Analytics event with given `eventParams`. This method automatically associates this logged event with this Firebase web app instance on this device. -See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/page-view). +See [Page views](https://developers.google.com/analytics/devguides/collection/ga4/views). Signature: diff --git a/docs-devsite/app.firebaseserverapp.md b/docs-devsite/app.firebaseserverapp.md new file mode 100644 index 00000000000..66b51c45fb2 --- /dev/null +++ b/docs-devsite/app.firebaseserverapp.md @@ -0,0 +1,59 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FirebaseServerApp interface +A [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface) holds the initialization information for a collection of services running in server environments. + +Do not call this constructor directly. Instead, use [initializeServerApp()](./app.md#initializeserverapp_30ab697) to create an app. + +Signature: + +```typescript +export interface FirebaseServerApp extends FirebaseApp +``` +Extends: [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [name](./app.firebaseserverapp.md#firebaseserverappname) | string | There is no getApp() operation for FirebaseServerApp, so the name is not relevant for applications. However, it may be used internally, and is declared here so that FirebaseServerApp conforms to the FirebaseApp interface. | +| [settings](./app.firebaseserverapp.md#firebaseserverappsettings) | [FirebaseServerAppSettings](./app.firebaseserverappsettings.md#firebaseserverappsettings_interface) | The (read-only) configuration settings for this server app. These are the original parameters given in [initializeServerApp()](./app.md#initializeserverapp_30ab697). | + +## FirebaseServerApp.name + +There is no `getApp()` operation for `FirebaseServerApp`, so the name is not relevant for applications. However, it may be used internally, and is declared here so that `FirebaseServerApp` conforms to the `FirebaseApp` interface. + +Signature: + +```typescript +name: string; +``` + +## FirebaseServerApp.settings + +The (read-only) configuration settings for this server app. These are the original parameters given in [initializeServerApp()](./app.md#initializeserverapp_30ab697). + +Signature: + +```typescript +readonly settings: FirebaseServerAppSettings; +``` + +### Example + + +```javascript +const app = initializeServerApp(settings); +console.log(app.settings.authIdToken === options.authIdToken); // true + +``` + diff --git a/docs-devsite/app.firebaseserverappsettings.md b/docs-devsite/app.firebaseserverappsettings.md new file mode 100644 index 00000000000..59aba9bca78 --- /dev/null +++ b/docs-devsite/app.firebaseserverappsettings.md @@ -0,0 +1,70 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FirebaseServerAppSettings interface +Configuration options given to [initializeServerApp()](./app.md#initializeserverapp_30ab697) + +Signature: + +```typescript +export interface FirebaseServerAppSettings extends FirebaseAppSettings +``` +Extends: [FirebaseAppSettings](./app.firebaseappsettings.md#firebaseappsettings_interface) + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [authIdToken](./app.firebaseserverappsettings.md#firebaseserverappsettingsauthidtoken) | string | An optional Auth ID token used to resume a signed in user session from a client runtime environment.Invoking getAuth with a FirebaseServerApp configured with a validated authIdToken causes an automatic attempt to sign in the user that the authIdToken represents. The token needs to have been recently minted for this operation to succeed.If the token fails local verification, or if the Auth service has failed to validate it when the Auth SDK is initialized, then a warning is logged to the console and the Auth SDK will not sign in a user on initialization.If a user is successfully signed in, then the Auth instance's onAuthStateChanged callback is invoked with the User object as per standard Auth flows. However, User objects created via an authIdToken do not have a refresh token. Attempted refreshToken operations fail. | +| [name](./app.firebaseserverappsettings.md#firebaseserverappsettingsname) | undefined | There is no getApp() operation for FirebaseServerApp, so the name is not relevant for applications. However, it may be used internally, and is declared here so that FirebaseServerApp conforms to the FirebaseApp interface. | +| [releaseOnDeref](./app.firebaseserverappsettings.md#firebaseserverappsettingsreleaseonderef) | object | An optional object. If provided, the Firebase SDK uses a FinalizationRegistry object to monitor the garbage collection status of the provided object. The Firebase SDK releases its reference on the FirebaseServerApp instance when the provided releaseOnDeref object is garbage collected.You can use this field to reduce memory management overhead for your application. If provided, an app running in a SSR pass does not need to perform FirebaseServerApp cleanup, so long as the reference object is deleted (by falling out of SSR scope, for instance.)If an object is not provided then the application must clean up the FirebaseServerApp instance by invoking deleteApp.If the application provides an object in this parameter, but the application is executed in a JavaScript engine that predates the support of FinalizationRegistry (introduced in node v14.6.0, for instance), then an error is thrown at FirebaseServerApp initialization. | + +## FirebaseServerAppSettings.authIdToken + +An optional Auth ID token used to resume a signed in user session from a client runtime environment. + +Invoking `getAuth` with a `FirebaseServerApp` configured with a validated `authIdToken` causes an automatic attempt to sign in the user that the `authIdToken` represents. The token needs to have been recently minted for this operation to succeed. + +If the token fails local verification, or if the Auth service has failed to validate it when the Auth SDK is initialized, then a warning is logged to the console and the Auth SDK will not sign in a user on initialization. + +If a user is successfully signed in, then the Auth instance's `onAuthStateChanged` callback is invoked with the `User` object as per standard Auth flows. However, `User` objects created via an `authIdToken` do not have a refresh token. Attempted `refreshToken` operations fail. + +Signature: + +```typescript +authIdToken?: string; +``` + +## FirebaseServerAppSettings.name + +There is no `getApp()` operation for `FirebaseServerApp`, so the name is not relevant for applications. However, it may be used internally, and is declared here so that `FirebaseServerApp` conforms to the `FirebaseApp` interface. + +Signature: + +```typescript +name?: undefined; +``` + +## FirebaseServerAppSettings.releaseOnDeref + +An optional object. If provided, the Firebase SDK uses a `FinalizationRegistry` object to monitor the garbage collection status of the provided object. The Firebase SDK releases its reference on the `FirebaseServerApp` instance when the provided `releaseOnDeref` object is garbage collected. + +You can use this field to reduce memory management overhead for your application. If provided, an app running in a SSR pass does not need to perform `FirebaseServerApp` cleanup, so long as the reference object is deleted (by falling out of SSR scope, for instance.) + +If an object is not provided then the application must clean up the `FirebaseServerApp` instance by invoking `deleteApp`. + +If the application provides an object in this parameter, but the application is executed in a JavaScript engine that predates the support of `FinalizationRegistry` (introduced in node v14.6.0, for instance), then an error is thrown at `FirebaseServerApp` initialization. + +Signature: + +```typescript +releaseOnDeref?: object; +``` diff --git a/docs-devsite/app.md b/docs-devsite/app.md index de0611cac1a..9c3b322aaaf 100644 --- a/docs-devsite/app.md +++ b/docs-devsite/app.md @@ -34,6 +34,7 @@ This package coordinates the communication between the different Firebase compon | function(options, ...) | | [initializeApp(options, name)](./app.md#initializeapp_cb2f5e1) | Creates and initializes a [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) instance.See [Add Firebase to your app](https://firebase.google.com/docs/web/setup#add_firebase_to_your_app) and [Initialize multiple projects](https://firebase.google.com/docs/web/setup#multiple-projects) for detailed documentation. | | [initializeApp(options, config)](./app.md#initializeapp_079e917) | Creates and initializes a FirebaseApp instance. | +| [initializeServerApp(options, config)](./app.md#initializeserverapp_30ab697) | Creates and initializes a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface) instance.The FirebaseServerApp is similar to FirebaseApp, but is intended for execution in server side rendering environments only. Initialization will fail if invoked from a browser environment.See [Add Firebase to your app](https://firebase.google.com/docs/web/setup#add_firebase_to_your_app) and [Initialize multiple projects](https://firebase.google.com/docs/web/setup#multiple-projects) for detailed documentation. | ## Interfaces @@ -42,6 +43,8 @@ This package coordinates the communication between the different Firebase compon | [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) | A [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) holds the initialization information for a collection of services.Do not call this constructor directly. Instead, use [initializeApp()](./app.md#initializeapp_cb2f5e1) to create an app. | | [FirebaseAppSettings](./app.firebaseappsettings.md#firebaseappsettings_interface) | Configuration options given to [initializeApp()](./app.md#initializeapp_cb2f5e1) | | [FirebaseOptions](./app.firebaseoptions.md#firebaseoptions_interface) | Firebase configuration object. Contains a set of parameters required by services in order to successfully communicate with Firebase server APIs and to associate client data with your Firebase project and Firebase application. Typically this object is populated by the Firebase console at project setup. See also: [Learn about the Firebase config object](https://firebase.google.com/docs/web/setup#config-object). | +| [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface) | A [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface) holds the initialization information for a collection of services running in server environments.Do not call this constructor directly. Instead, use [initializeServerApp()](./app.md#initializeserverapp_30ab697) to create an app. | +| [FirebaseServerAppSettings](./app.firebaseserverappsettings.md#firebaseserverappsettings_interface) | Configuration options given to [initializeServerApp()](./app.md#initializeserverapp_30ab697) | ## Variables @@ -309,6 +312,54 @@ export declare function initializeApp(options: FirebaseOptions, config?: Firebas [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) +### initializeServerApp(options, config) {:#initializeserverapp_30ab697} + +Creates and initializes a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface) instance. + +The `FirebaseServerApp` is similar to `FirebaseApp`, but is intended for execution in server side rendering environments only. Initialization will fail if invoked from a browser environment. + +See [Add Firebase to your app](https://firebase.google.com/docs/web/setup#add_firebase_to_your_app) and [Initialize multiple projects](https://firebase.google.com/docs/web/setup#multiple-projects) for detailed documentation. + +Signature: + +```typescript +export declare function initializeServerApp(options: FirebaseOptions | FirebaseApp, config: FirebaseServerAppSettings): FirebaseServerApp; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | [FirebaseOptions](./app.firebaseoptions.md#firebaseoptions_interface) \| [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) | Firebase.AppOptions to configure the app's services, or a a FirebaseApp instance which contains the AppOptions within. | +| config | [FirebaseServerAppSettings](./app.firebaseserverappsettings.md#firebaseserverappsettings_interface) | FirebaseServerApp configuration. | + +Returns: + +[FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface) + +The initialized `FirebaseServerApp`. + +### Example + + +```javascript + +// Initialize an instance of `FirebaseServerApp`. +// Retrieve your own options values by adding a web app on +// https://console.firebase.google.com +initializeServerApp({ + apiKey: "AIza....", // Auth / General Use + authDomain: "YOUR_APP.firebaseapp.com", // Auth with popup/redirect + databaseURL: "https://YOUR_APP.firebaseio.com", // Realtime Database + storageBucket: "YOUR_APP.appspot.com", // Storage + messagingSenderId: "123456789" // Cloud Messaging + }, + { + authIdToken: "Your Auth ID Token" + }); + +``` + ## SDK\_VERSION The current SDK version. diff --git a/docs-devsite/auth.auth.md b/docs-devsite/auth.auth.md index b089a9b09bd..cbbc7a9ceb0 100644 --- a/docs-devsite/auth.auth.md +++ b/docs-devsite/auth.auth.md @@ -265,6 +265,8 @@ auth.setPersistence(browserSessionPersistence); Signs out the current user. This does not automatically revoke the user's ID token. +This method is not supported by [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). + Signature: ```typescript diff --git a/docs-devsite/auth.googleauthprovider.md b/docs-devsite/auth.googleauthprovider.md index c53c368a62e..edd1f14d0fe 100644 --- a/docs-devsite/auth.googleauthprovider.md +++ b/docs-devsite/auth.googleauthprovider.md @@ -10,7 +10,7 @@ https://github.com/firebase/firebase-js-sdk {% endcomment %} # GoogleAuthProvider class -Provider for generating an an [OAuthCredential](./auth.oauthcredential.md#oauthcredential_class) for [ProviderId](./auth.md#providerid).GOOGLE. +Provider for generating an [OAuthCredential](./auth.oauthcredential.md#oauthcredential_class) for [ProviderId](./auth.md#providerid).GOOGLE. Signature: diff --git a/docs-devsite/auth.md b/docs-devsite/auth.md index a2f17a1962d..43d23dc8931 100644 --- a/docs-devsite/auth.md +++ b/docs-devsite/auth.md @@ -28,7 +28,7 @@ Firebase Authentication | [confirmPasswordReset(auth, oobCode, newPassword)](./auth.md#confirmpasswordreset_749dad8) | Completes the password reset process, given a confirmation code and new password. | | [connectAuthEmulator(auth, url, options)](./auth.md#connectauthemulator_657c7e5) | Changes the [Auth](./auth.auth.md#auth_interface) instance to communicate with the Firebase Auth Emulator, instead of production Firebase Auth services. | | [createUserWithEmailAndPassword(auth, email, password)](./auth.md#createuserwithemailandpassword_21ad33b) | Creates a new user account associated with the specified email address and password. | -| [fetchSignInMethodsForEmail(auth, email)](./auth.md#fetchsigninmethodsforemail_efb3887) | Gets the list of possible sign in methods for the given email address. This method returns an empty list when \[Email Enumeration Protection\](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled, irrespective of the number of authentication methods available for the given email. | +| [fetchSignInMethodsForEmail(auth, email)](./auth.md#fetchsigninmethodsforemail_efb3887) | Gets the list of possible sign in methods for the given email address. This method returns an empty list when [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled, irrespective of the number of authentication methods available for the given email. | | [getMultiFactorResolver(auth, error)](./auth.md#getmultifactorresolver_201ba61) | Provides a [MultiFactorResolver](./auth.multifactorresolver.md#multifactorresolver_interface) suitable for completion of a multi-factor flow. | | [getRedirectResult(auth, resolver)](./auth.md#getredirectresult_c35dc1f) | Returns a [UserCredential](./auth.usercredential.md#usercredential_interface) from the redirect-based sign-in flow. | | [initializeRecaptchaConfig(auth)](./auth.md#initializerecaptchaconfig_2a61ea7) | Loads the reCAPTCHA configuration into the Auth instance. | @@ -36,7 +36,7 @@ Firebase Authentication | [onAuthStateChanged(auth, nextOrObserver, error, completed)](./auth.md#onauthstatechanged_b0d07ab) | Adds an observer for changes to the user's sign-in state. | | [onIdTokenChanged(auth, nextOrObserver, error, completed)](./auth.md#onidtokenchanged_b0d07ab) | Adds an observer for changes to the signed-in user's ID token. | | [revokeAccessToken(auth, token)](./auth.md#revokeaccesstoken_5556ad5) | Revokes the given access token. Currently only supports Apple OAuth access tokens. | -| [sendPasswordResetEmail(auth, email, actionCodeSettings)](./auth.md#sendpasswordresetemail_95b079b) | Sends a password reset email to the given email address. This method does not throw an error when there's no user account with the given email address and \[Email Enumeration Protection\](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled. | +| [sendPasswordResetEmail(auth, email, actionCodeSettings)](./auth.md#sendpasswordresetemail_95b079b) | Sends a password reset email to the given email address. This method does not throw an error when there's no user account with the given email address and [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled. | | [sendSignInLinkToEmail(auth, email, actionCodeSettings)](./auth.md#sendsigninlinktoemail_95b079b) | Sends a sign-in email link to the user with the specified email. | | [setPersistence(auth, persistence)](./auth.md#setpersistence_a3592ac) | Changes the type of persistence on the [Auth](./auth.auth.md#auth_interface) instance for the currently saved Auth session and applies this type of persistence for future sign-in requests, including sign-in with redirect requests. | | [signInAnonymously(auth)](./auth.md#signinanonymously_2a61ea7) | Asynchronously signs in as an anonymous user. | @@ -88,7 +88,7 @@ Firebase Authentication | [EmailAuthProvider](./auth.emailauthprovider.md#emailauthprovider_class) | Provider for generating [EmailAuthCredential](./auth.emailauthcredential.md#emailauthcredential_class). | | [FacebookAuthProvider](./auth.facebookauthprovider.md#facebookauthprovider_class) | Provider for generating an [OAuthCredential](./auth.oauthcredential.md#oauthcredential_class) for [ProviderId](./auth.md#providerid).FACEBOOK. | | [GithubAuthProvider](./auth.githubauthprovider.md#githubauthprovider_class) | Provider for generating an [OAuthCredential](./auth.oauthcredential.md#oauthcredential_class) for [ProviderId](./auth.md#providerid).GITHUB. | -| [GoogleAuthProvider](./auth.googleauthprovider.md#googleauthprovider_class) | Provider for generating an an [OAuthCredential](./auth.oauthcredential.md#oauthcredential_class) for [ProviderId](./auth.md#providerid).GOOGLE. | +| [GoogleAuthProvider](./auth.googleauthprovider.md#googleauthprovider_class) | Provider for generating an [OAuthCredential](./auth.oauthcredential.md#oauthcredential_class) for [ProviderId](./auth.md#providerid).GOOGLE. | | [OAuthCredential](./auth.oauthcredential.md#oauthcredential_class) | Represents the OAuth credentials returned by an [OAuthProvider](./auth.oauthprovider.md#oauthprovider_class). | | [OAuthProvider](./auth.oauthprovider.md#oauthprovider_class) | Provider for generating generic [OAuthCredential](./auth.oauthcredential.md#oauthcredential_class). | | [PhoneAuthCredential](./auth.phoneauthcredential.md#phoneauthcredential_class) | Represents the credentials returned by [PhoneAuthProvider](./auth.phoneauthprovider.md#phoneauthprovider_class). | @@ -136,7 +136,7 @@ Firebase Authentication | [PhoneSingleFactorInfoOptions](./auth.phonesinglefactorinfooptions.md#phonesinglefactorinfooptions_interface) | Options used for single-factor sign-in. | | [PopupRedirectResolver](./auth.popupredirectresolver.md#popupredirectresolver_interface) | A resolver used for handling DOM specific operations like [signInWithPopup()](./auth.md#signinwithpopup_770f816) or [signInWithRedirect()](./auth.md#signinwithredirect_770f816). | | [ReactNativeAsyncStorage](./auth.reactnativeasyncstorage.md#reactnativeasyncstorage_interface) | Interface for a supplied AsyncStorage. | -| [RecaptchaParameters](./auth.recaptchaparameters.md#recaptchaparameters_interface) | Interface representing reCAPTCHA parameters.See the \[reCAPTCHA docs\](https://developers.google.com/recaptcha/docs/display\#render\_param) for the list of accepted parameters. All parameters are accepted except for sitekey: Firebase Auth provisions a reCAPTCHA for each project and will configure the site key upon rendering.For an invisible reCAPTCHA, set the size key to invisible. | +| [RecaptchaParameters](./auth.recaptchaparameters.md#recaptchaparameters_interface) | Interface representing reCAPTCHA parameters.See the [reCAPTCHA docs](https://developers.google.com/recaptcha/docs/display#render_param) for the list of accepted parameters. All parameters are accepted except for sitekey: Firebase Auth provisions a reCAPTCHA for each project and will configure the site key upon rendering.For an invisible reCAPTCHA, set the size key to invisible. | | [TotpMultiFactorAssertion](./auth.totpmultifactorassertion.md#totpmultifactorassertion_interface) | The class for asserting ownership of a TOTP second factor. Provided by [TotpMultiFactorGenerator.assertionForEnrollment()](./auth.totpmultifactorgenerator.md#totpmultifactorgeneratorassertionforenrollment) and [TotpMultiFactorGenerator.assertionForSignIn()](./auth.totpmultifactorgenerator.md#totpmultifactorgeneratorassertionforsignin). | | [TotpMultiFactorInfo](./auth.totpmultifactorinfo.md#totpmultifactorinfo_interface) | The subclass of the [MultiFactorInfo](./auth.multifactorinfo.md#multifactorinfo_interface) interface for TOTP second factors. The factorId of this second factor is [FactorId](./auth.md#factorid).TOTP. | | [User](./auth.user.md#user_interface) | A user account. | @@ -381,6 +381,8 @@ On successful creation of the user account, this user will also be signed in to User account creation can fail if the account already exists or the password is invalid. +This method is not supported on [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). + Note: The email address acts as a unique identifier for the user and enables an email-based password reset. This function will create a new user account and set the initial user password. Signature: @@ -403,7 +405,7 @@ Promise<[UserCredential](./auth.usercredential.md#usercredential_interface).EMAIL\_PASSWORD and [SignInMethod](./auth.md#signinmethod).EMAIL\_LINK. @@ -418,7 +420,7 @@ export declare function fetchSignInMethodsForEmail(auth: Auth, email: string): P | Parameter | Type | Description | | --- | --- | --- | | auth | [Auth](./auth.auth.md#auth_interface) | The [Auth](./auth.auth.md#auth_interface) instance. | -| email | string | The user's email address.Deprecated. Migrating off of this method is recommended as a security best-practice. Learn more in the Identity Platform documentation for \[Email Enumeration Protection\](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection). | +| email | string | The user's email address.Deprecated. Migrating off of this method is recommended as a security best-practice. Learn more in the Identity Platform documentation for [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection). | Returns: @@ -451,7 +453,7 @@ Returns a [UserCredential](./auth.usercredential.md#usercredential_interface) fr If sign-in succeeded, returns the signed in user. If sign-in was unsuccessful, fails with an error. If no redirect operation was called, returns `null`. -This method does not work in a Node.js environment. +This method does not work in a Node.js environment or with [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). Signature: @@ -628,7 +630,7 @@ Promise<void> ### sendPasswordResetEmail(auth, email, actionCodeSettings) {:#sendpasswordresetemail_95b079b} -Sends a password reset email to the given email address. This method does not throw an error when there's no user account with the given email address and \[Email Enumeration Protection\](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled. +Sends a password reset email to the given email address. This method does not throw an error when there's no user account with the given email address and [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled. To complete the password reset, call [confirmPasswordReset()](./auth.md#confirmpasswordreset_749dad8) with the code supplied in the email sent to the user, along with the new password specified by the user. @@ -728,7 +730,7 @@ Changes the type of persistence on the [Auth](./auth.auth.md#auth_interface) ins This makes it easy for a user signing in to specify whether their session should be remembered or not. It also makes it easier to never persist the `Auth` state for applications that are shared by other users or have sensitive data. -This method does not work in a Node.js environment. +This method does not work in a Node.js environment or with [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). Signature: @@ -763,6 +765,8 @@ Asynchronously signs in as an anonymous user. If there is already an anonymous user signed in, that user will be returned; otherwise, a new anonymous user identity will be created and returned. +This method is not supported by [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). + Signature: ```typescript @@ -785,6 +789,8 @@ Asynchronously signs in with the given credentials. An [AuthProvider](./auth.authprovider.md#authprovider_interface) can be used to generate the credential. +This method is not supported by [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). + Signature: ```typescript @@ -810,6 +816,8 @@ Custom tokens are used to integrate Firebase Auth with existing auth systems, an Fails with an error if the token is invalid, expired, or not accepted by the Firebase Auth service. +This method is not supported by [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). + Signature: ```typescript @@ -831,7 +839,9 @@ Promise<[UserCredential](./auth.usercredential.md#usercredential_interface). Note: The user's password is NOT the password used to access the user's email account. The email address serves as a unique identifier for the user, and the password is used to access the user's account in your Firebase project. See also: [createUserWithEmailAndPassword()](./auth.md#createuserwithemailandpassword_21ad33b). @@ -861,6 +871,8 @@ If no link is passed, the link is inferred from the current URL. Fails with an error if the email address is invalid or OTP in email link expires. +This method is not supported by [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). + Note: Confirm the link is a sign-in email link before calling this method firebase.auth.Auth.isSignInWithEmailLink. Signature: @@ -913,7 +925,7 @@ This method sends a code via SMS to the given phone number, and returns a [Confi For abuse prevention, this method also requires a [ApplicationVerifier](./auth.applicationverifier.md#applicationverifier_interface). This SDK includes a reCAPTCHA-based implementation, [RecaptchaVerifier](./auth.recaptchaverifier.md#recaptchaverifier_class). This function can work on other platforms that do not support the [RecaptchaVerifier](./auth.recaptchaverifier.md#recaptchaverifier_class) (like React Native), but you need to use a third-party [ApplicationVerifier](./auth.applicationverifier.md#applicationverifier_interface) implementation. -This method does not work in a Node.js environment. +This method does not work in a Node.js environment or with [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). Signature: @@ -951,7 +963,7 @@ Authenticates a Firebase client using a popup-based OAuth authentication flow. If succeeds, returns the signed in user along with the provider's credential. If sign in was unsuccessful, returns an error object containing additional information about the error. -This method does not work in a Node.js environment. +This method does not work in a Node.js environment or with [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). Signature: @@ -993,7 +1005,7 @@ Authenticates a Firebase client using a full-page redirect flow. To handle the results and errors for this operation, refer to [getRedirectResult()](./auth.md#getredirectresult_c35dc1f). Follow the [best practices](https://firebase.google.com/docs/auth/web/redirect-best-practices) when using [signInWithRedirect()](./auth.md#signinwithredirect_770f816). -This method does not work in a Node.js environment. +This method does not work in a Node.js environment or with [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). Signature: @@ -1045,6 +1057,8 @@ const operationType = result.operationType; Signs out the current user. +This method is not supported by [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). + Signature: ```typescript @@ -1071,6 +1085,8 @@ This will trigger [onAuthStateChanged()](./auth.md#onauthstatechanged_b0d07ab) a The operation fails with an error if the user to be updated belongs to a different Firebase project. +This method is not supported by [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). + Signature: ```typescript @@ -1347,7 +1363,7 @@ Links the [OAuthProvider](./auth.oauthprovider.md#oauthprovider_class) to the us To handle the results and errors for this operation, refer to [getRedirectResult()](./auth.md#getredirectresult_c35dc1f). Follow the [best practices](https://firebase.google.com/docs/auth/web/redirect-best-practices) when using [linkWithRedirect()](./auth.md#linkwithredirect_41c0b31). -This method does not work in a Node.js environment. +This method does not work in a Node.js environment or with [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). Signature: @@ -1411,6 +1427,8 @@ Re-authenticates a user using a fresh credential. Use before operations such as [updatePassword()](./auth.md#updatepassword_6df673e) that require tokens from recent sign-in attempts. This method can be used to recover from a `CREDENTIAL_TOO_OLD_LOGIN_AGAIN` error or a `TOKEN_EXPIRED` error. +This method is not supported on any [User](./auth.user.md#user_interface) signed in by [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). + Signature: ```typescript @@ -1434,7 +1452,7 @@ Re-authenticates a user using a fresh phone credential. Use before operations such as [updatePassword()](./auth.md#updatepassword_6df673e) that require tokens from recent sign-in attempts. -This method does not work in a Node.js environment. +This method does not work in a Node.js environment or on any [User](./auth.user.md#user_interface) signed in by [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). Signature: @@ -1460,7 +1478,7 @@ Reauthenticates the current user with the specified [OAuthProvider](./auth.oauth If the reauthentication is successful, the returned result will contain the user and the provider's credential. -This method does not work in a Node.js environment. +This method does not work in a Node.js environment or on any [User](./auth.user.md#user_interface) signed in by [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). Signature: @@ -1498,7 +1516,7 @@ Reauthenticates the current user with the specified [OAuthProvider](./auth.oauth To handle the results and errors for this operation, refer to [getRedirectResult()](./auth.md#getredirectresult_c35dc1f). Follow the [best practices](https://firebase.google.com/docs/auth/web/redirect-best-practices) when using [reauthenticateWithRedirect()](./auth.md#reauthenticatewithredirect_41c0b31). -This method does not work in a Node.js environment. +This method does not work in a Node.js environment or with [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). Signature: @@ -1630,6 +1648,8 @@ Updates the user's email address. An email will be sent to the original email address (if it was set) that allows to revoke the email address change, in order to protect them from account hijacking. +This method is not supported on any [User](./auth.user.md#user_interface) signed in by [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). + Important: this is a security sensitive operation that requires the user to have recently signed in. If this requirement isn't met, ask the user to authenticate again and then call [reauthenticateWithCredential()](./auth.md#reauthenticatewithcredential_60f8043). Signature: @@ -1643,7 +1663,7 @@ export declare function updateEmail(user: User, newEmail: string): Promise | Parameter | Type | Description | | --- | --- | --- | | user | [User](./auth.user.md#user_interface) | The user. | -| newEmail | string | The new email address.Throws "auth/operation-not-allowed" error when \[Email Enumeration Protection\](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled. Deprecated - Use [verifyBeforeUpdateEmail()](./auth.md#verifybeforeupdateemail_09d6f11) instead. | +| newEmail | string | The new email address.Throws "auth/operation-not-allowed" error when [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled. Deprecated - Use [verifyBeforeUpdateEmail()](./auth.md#verifybeforeupdateemail_09d6f11) instead. | Returns: @@ -1676,7 +1696,7 @@ Promise<void> Updates the user's phone number. -This method does not work in a Node.js environment. +This method does not work in a Node.js environment or on any [User](./auth.user.md#user_interface) signed in by [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). Signature: diff --git a/docs-devsite/auth.recaptchaparameters.md b/docs-devsite/auth.recaptchaparameters.md index 5d70f1826eb..e817961ac9e 100644 --- a/docs-devsite/auth.recaptchaparameters.md +++ b/docs-devsite/auth.recaptchaparameters.md @@ -12,7 +12,7 @@ https://github.com/firebase/firebase-js-sdk # RecaptchaParameters interface Interface representing reCAPTCHA parameters. -See the \[reCAPTCHA docs\](https://developers.google.com/recaptcha/docs/display\#render\_param) for the list of accepted parameters. All parameters are accepted except for `sitekey`: Firebase Auth provisions a reCAPTCHA for each project and will configure the site key upon rendering. +See the [reCAPTCHA docs](https://developers.google.com/recaptcha/docs/display#render_param) for the list of accepted parameters. All parameters are accepted except for `sitekey`: Firebase Auth provisions a reCAPTCHA for each project and will configure the site key upon rendering. For an invisible reCAPTCHA, set the `size` key to `invisible`. diff --git a/docs-devsite/auth.user.md b/docs-devsite/auth.user.md index a774c914f34..f28c7eeb3bc 100644 --- a/docs-devsite/auth.user.md +++ b/docs-devsite/auth.user.md @@ -121,6 +121,8 @@ Deletes and signs out the user. Important: this is a security-sensitive operation that requires the user to have recently signed in. If this requirement isn't met, ask the user to authenticate again and then call one of the reauthentication methods like [reauthenticateWithCredential()](./auth.md#reauthenticatewithcredential_60f8043). +This method is not supported on any [User](./auth.user.md#user_interface) signed in by [Auth](./auth.auth.md#auth_interface) instances created with a [FirebaseServerApp](./app.firebaseserverapp.md#firebaseserverapp_interface). + Signature: ```typescript diff --git a/docs-devsite/firestore_.firestoredataconverter.md b/docs-devsite/firestore_.firestoredataconverter.md index 412b49a03fb..eb49df60753 100644 --- a/docs-devsite/firestore_.firestoredataconverter.md +++ b/docs-devsite/firestore_.firestoredataconverter.md @@ -14,6 +14,8 @@ Converter used by `withConverter()` to transform user objects of type `AppModelT Using the converter allows you to specify generic type arguments when storing and retrieving objects from Firestore. +In this context, an "AppModel" is a class that is used in an application to package together related information and functionality. Such a class could, for example, have properties with complex, nested data types, properties used for memoization, properties of types not supported by Firestore (such as `symbol` and `bigint`), and helper functions that perform compound operations. Such classes are not suitable and/or possible to store into a Firestore database. Instead, instances of such classes need to be converted to "plain old JavaScript objects" (POJOs) with exclusively primitive properties, potentially nested inside other POJOs or arrays of POJOs. In this context, this type is referred to as the "DbModel" and would be an object suitable for persisting into Firestore. For convenience, applications can implement `FirestoreDataConverter` and register the converter with Firestore objects, such as `DocumentReference` or `Query`, to automatically convert `AppModel` to `DbModel` when storing into Firestore, and convert `DbModel` to `AppModel` when retrieving from Firestore. + Signature: ```typescript @@ -24,7 +26,7 @@ export declare interface FirestoreDataConverterAppModelType. You can access your data by calling: snapshot.data(options).Generally, the data returned from snapshot.data() can be cast to DbModelType; however, this is not guaranteed as writes to the database may have occurred without a type converter enforcing this specific layout. | +| [fromFirestore(snapshot, options)](./firestore_.firestoredataconverter.md#firestoredataconverterfromfirestore) | Called by the Firestore SDK to convert Firestore data into an object of type AppModelType. You can access your data by calling: snapshot.data(options).Generally, the data returned from snapshot.data() can be cast to DbModelType; however, this is not guaranteed because Firestore does not enforce a schema on the database. For example, writes from a previous version of the application or writes from another client that did not use a type converter could have written data with different properties and/or property types. The implementation will need to choose whether to gracefully recover from non-conforming data or throw an error.To override this method, see . | | [toFirestore(modelObject)](./firestore_.firestoredataconverter.md#firestoredataconvertertofirestore) | Called by the Firestore SDK to convert a custom model object of type AppModelType into a plain JavaScript object (suitable for writing directly to the Firestore database) of type DbModelType. To use set() with merge and mergeFields, toFirestore() must be defined with PartialWithFieldValue<AppModelType>.The WithFieldValue<T> type extends T to also allow FieldValues such as [deleteField()](./firestore_.md#deletefield) to be used as property values. | | [toFirestore(modelObject, options)](./firestore_.firestoredataconverter.md#firestoredataconvertertofirestore) | Called by the Firestore SDK to convert a custom model object of type AppModelType into a plain JavaScript object (suitable for writing directly to the Firestore database) of type DbModelType. Used with [setDoc()](./firestore_.md#setdoc_ee215ad), and with merge:true or mergeFields.The PartialWithFieldValue<T> type extends Partial<T> to allow FieldValues such as [arrayUnion()](./firestore_.md#arrayunion_7d853aa) to be used as property values. It also supports nested Partial by allowing nested fields to be omitted. | @@ -32,7 +34,9 @@ export declare interface FirestoreDataConverter. You can access your data by calling: `snapshot.data(options)`. -Generally, the data returned from `snapshot.data()` can be cast to `DbModelType`; however, this is not guaranteed as writes to the database may have occurred without a type converter enforcing this specific layout. +Generally, the data returned from `snapshot.data()` can be cast to `DbModelType`; however, this is not guaranteed because Firestore does not enforce a schema on the database. For example, writes from a previous version of the application or writes from another client that did not use a type converter could have written data with different properties and/or property types. The implementation will need to choose whether to gracefully recover from non-conforming data or throw an error. + +To override this method, see . Signature: diff --git a/docs-devsite/firestore_.md b/docs-devsite/firestore_.md index 8f329d05287..74a0c356523 100644 --- a/docs-devsite/firestore_.md +++ b/docs-devsite/firestore_.md @@ -165,7 +165,7 @@ https://github.com/firebase/firebase-js-sdk | [DocumentChange](./firestore_.documentchange.md#documentchange_interface) | A DocumentChange represents a change to the documents matching a query. It contains the document affected and the type of change that occurred. | | [DocumentData](./firestore_.documentdata.md#documentdata_interface) | Document data (for use with [setDoc()](./firestore_lite.md#setdoc_ee215ad)) consists of fields mapped to values. | | [ExperimentalLongPollingOptions](./firestore_.experimentallongpollingoptions.md#experimentallongpollingoptions_interface) | Options that configure the SDK’s underlying network transport (WebChannel) when long-polling is used.Note: This interface is "experimental" and is subject to change.See FirestoreSettings.experimentalAutoDetectLongPolling, FirestoreSettings.experimentalForceLongPolling, and FirestoreSettings.experimentalLongPollingOptions. | -| [FirestoreDataConverter](./firestore_.firestoredataconverter.md#firestoredataconverter_interface) | Converter used by withConverter() to transform user objects of type AppModelType into Firestore data of type DbModelType.Using the converter allows you to specify generic type arguments when storing and retrieving objects from Firestore. | +| [FirestoreDataConverter](./firestore_.firestoredataconverter.md#firestoredataconverter_interface) | Converter used by withConverter() to transform user objects of type AppModelType into Firestore data of type DbModelType.Using the converter allows you to specify generic type arguments when storing and retrieving objects from Firestore.In this context, an "AppModel" is a class that is used in an application to package together related information and functionality. Such a class could, for example, have properties with complex, nested data types, properties used for memoization, properties of types not supported by Firestore (such as symbol and bigint), and helper functions that perform compound operations. Such classes are not suitable and/or possible to store into a Firestore database. Instead, instances of such classes need to be converted to "plain old JavaScript objects" (POJOs) with exclusively primitive properties, potentially nested inside other POJOs or arrays of POJOs. In this context, this type is referred to as the "DbModel" and would be an object suitable for persisting into Firestore. For convenience, applications can implement FirestoreDataConverter and register the converter with Firestore objects, such as DocumentReference or Query, to automatically convert AppModel to DbModel when storing into Firestore, and convert DbModel to AppModel when retrieving from Firestore. | | [FirestoreSettings](./firestore_.firestoresettings.md#firestoresettings_interface) | Specifies custom configurations for your Cloud Firestore instance. You must set these before invoking any other methods. | | [Index](./firestore_.index.md#index_interface) | (BETA) The SDK definition of a Firestore index. | | [IndexConfiguration](./firestore_.indexconfiguration.md#indexconfiguration_interface) | (BETA) A list of Firestore indexes to speed up local query execution.See [JSON Format](https://firebase.google.com/docs/reference/firestore/indexes/#json_format) for a description of the format of the index definition. | @@ -204,6 +204,7 @@ https://github.com/firebase/firebase-js-sdk | [DocumentChangeType](./firestore_.md#documentchangetype) | The type of a DocumentChange may be 'added', 'removed', or 'modified'. | | [FirestoreErrorCode](./firestore_.md#firestoreerrorcode) | The set of Firestore status codes. The codes are the same at the ones exposed by gRPC here: https://github.com/grpc/grpc/blob/master/doc/statuscodes.mdPossible values: - 'cancelled': The operation was cancelled (typically by the caller). - 'unknown': Unknown error or an error from a different error domain. - 'invalid-argument': Client specified an invalid argument. Note that this differs from 'failed-precondition'. 'invalid-argument' indicates arguments that are problematic regardless of the state of the system (e.g. an invalid field name). - 'deadline-exceeded': Deadline expired before operation could complete. For operations that change the state of the system, this error may be returned even if the operation has completed successfully. For example, a successful response from a server could have been delayed long enough for the deadline to expire. - 'not-found': Some requested document was not found. - 'already-exists': Some document that we attempted to create already exists. - 'permission-denied': The caller does not have permission to execute the specified operation. - 'resource-exhausted': Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space. - 'failed-precondition': Operation was rejected because the system is not in a state required for the operation's execution. - 'aborted': The operation was aborted, typically due to a concurrency issue like transaction aborts, etc. - 'out-of-range': Operation was attempted past the valid range. - 'unimplemented': Operation is not implemented or not supported/enabled. - 'internal': Internal errors. Means some invariants expected by underlying system has been broken. If you see one of these errors, something is very broken. - 'unavailable': The service is currently unavailable. This is most likely a transient condition and may be corrected by retrying with a backoff. - 'data-loss': Unrecoverable data loss or corruption. - 'unauthenticated': The request does not have valid authentication credentials for the operation. | | [FirestoreLocalCache](./firestore_.md#firestorelocalcache) | Union type from all supported SDK cache layer. | +| [ListenSource](./firestore_.md#listensource) | Describe the source a query listens to.Set to default to listen to both cache and server changes. Set to cache to listen to changes in cache only. | | [MemoryGarbageCollector](./firestore_.md#memorygarbagecollector) | Union type from all support gabage collectors for memory local cache. | | [NestedUpdateFields](./firestore_.md#nestedupdatefields) | For each field (e.g. 'bar'), find all nested keys (e.g. {'bar.baz': T1, 'bar.qux': T2}). Intersect them together to make a single map containing all possible keys that are all marked as optional | | [OrderByDirection](./firestore_.md#orderbydirection) | The direction of a [orderBy()](./firestore_.md#orderby_006d61f) clause is specified as 'desc' or 'asc' (descending or ascending). | @@ -2551,6 +2552,18 @@ Union type from all supported SDK cache layer. export declare type FirestoreLocalCache = MemoryLocalCache | PersistentLocalCache; ``` +## ListenSource + +Describe the source a query listens to. + +Set to `default` to listen to both cache and server changes. Set to `cache` to listen to changes in cache only. + +Signature: + +```typescript +export declare type ListenSource = 'default' | 'cache'; +``` + ## MemoryGarbageCollector Union type from all support gabage collectors for memory local cache. diff --git a/docs-devsite/firestore_.snapshotlistenoptions.md b/docs-devsite/firestore_.snapshotlistenoptions.md index 7551b0a2f23..33d769f4fd9 100644 --- a/docs-devsite/firestore_.snapshotlistenoptions.md +++ b/docs-devsite/firestore_.snapshotlistenoptions.md @@ -23,6 +23,7 @@ export declare interface SnapshotListenOptions | Property | Type | Description | | --- | --- | --- | | [includeMetadataChanges](./firestore_.snapshotlistenoptions.md#snapshotlistenoptionsincludemetadatachanges) | boolean | Include a change even if only the metadata of the query or of a document changed. Default is false. | +| [source](./firestore_.snapshotlistenoptions.md#snapshotlistenoptionssource) | [ListenSource](./firestore_.md#listensource) | Set the source the query listens to. Default to "default", which listens to both cache and server. | ## SnapshotListenOptions.includeMetadataChanges @@ -33,3 +34,13 @@ Include a change even if only the metadata of the query or of a document changed ```typescript readonly includeMetadataChanges?: boolean; ``` + +## SnapshotListenOptions.source + +Set the source the query listens to. Default to "default", which listens to both cache and server. + +Signature: + +```typescript +readonly source?: ListenSource; +``` diff --git a/docs-devsite/firestore_lite.firestoredataconverter.md b/docs-devsite/firestore_lite.firestoredataconverter.md index 7b70f943688..9295c7055f7 100644 --- a/docs-devsite/firestore_lite.firestoredataconverter.md +++ b/docs-devsite/firestore_lite.firestoredataconverter.md @@ -14,6 +14,8 @@ Converter used by `withConverter()` to transform user objects of type `AppModelT Using the converter allows you to specify generic type arguments when storing and retrieving objects from Firestore. +In this context, an "AppModel" is a class that is used in an application to package together related information and functionality. Such a class could, for example, have properties with complex, nested data types, properties used for memoization, properties of types not supported by Firestore (such as `symbol` and `bigint`), and helper functions that perform compound operations. Such classes are not suitable and/or possible to store into a Firestore database. Instead, instances of such classes need to be converted to "plain old JavaScript objects" (POJOs) with exclusively primitive properties, potentially nested inside other POJOs or arrays of POJOs. In this context, this type is referred to as the "DbModel" and would be an object suitable for persisting into Firestore. For convenience, applications can implement `FirestoreDataConverter` and register the converter with Firestore objects, such as `DocumentReference` or `Query`, to automatically convert `AppModel` to `DbModel` when storing into Firestore, and convert `DbModel` to `AppModel` when retrieving from Firestore. + Signature: ```typescript @@ -24,7 +26,7 @@ export declare interface FirestoreDataConverterAppModelType. You can access your data by calling: snapshot.data().Generally, the data returned from snapshot.data() can be cast to DbModelType; however, this is not guaranteed as writes to the database may have occurred without a type converter enforcing this specific layout. | +| [fromFirestore(snapshot)](./firestore_lite.firestoredataconverter.md#firestoredataconverterfromfirestore) | Called by the Firestore SDK to convert Firestore data into an object of type AppModelType. You can access your data by calling: snapshot.data().Generally, the data returned from snapshot.data() can be cast to DbModelType; however, this is not guaranteed because Firestore does not enforce a schema on the database. For example, writes from a previous version of the application or writes from another client that did not use a type converter could have written data with different properties and/or property types. The implementation will need to choose whether to gracefully recover from non-conforming data or throw an error. | | [toFirestore(modelObject)](./firestore_lite.firestoredataconverter.md#firestoredataconvertertofirestore) | Called by the Firestore SDK to convert a custom model object of type AppModelType into a plain Javascript object (suitable for writing directly to the Firestore database) of type DbModelType. Used with [setDoc()](./firestore_lite.md#setdoc_ee215ad), and .The WithFieldValue<T> type extends T to also allow FieldValues such as [deleteField()](./firestore_.md#deletefield) to be used as property values. | | [toFirestore(modelObject, options)](./firestore_lite.firestoredataconverter.md#firestoredataconvertertofirestore) | Called by the Firestore SDK to convert a custom model object of type AppModelType into a plain Javascript object (suitable for writing directly to the Firestore database) of type DbModelType. Used with [setDoc()](./firestore_lite.md#setdoc_ee215ad), and with merge:true or mergeFields.The PartialWithFieldValue<T> type extends Partial<T> to allow FieldValues such as [arrayUnion()](./firestore_.md#arrayunion_7d853aa) to be used as property values. It also supports nested Partial by allowing nested fields to be omitted. | @@ -32,7 +34,7 @@ export declare interface FirestoreDataConverter. You can access your data by calling: `snapshot.data()`. -Generally, the data returned from `snapshot.data()` can be cast to `DbModelType`; however, this is not guaranteed as writes to the database may have occurred without a type converter enforcing this specific layout. +Generally, the data returned from `snapshot.data()` can be cast to `DbModelType`; however, this is not guaranteed because Firestore does not enforce a schema on the database. For example, writes from a previous version of the application or writes from another client that did not use a type converter could have written data with different properties and/or property types. The implementation will need to choose whether to gracefully recover from non-conforming data or throw an error. Signature: diff --git a/docs-devsite/firestore_lite.md b/docs-devsite/firestore_lite.md index 6e02adce2e1..d5b989f434c 100644 --- a/docs-devsite/firestore_lite.md +++ b/docs-devsite/firestore_lite.md @@ -125,7 +125,7 @@ https://github.com/firebase/firebase-js-sdk | --- | --- | | [AggregateSpec](./firestore_lite.aggregatespec.md#aggregatespec_interface) | Specifies a set of aggregations and their aliases. | | [DocumentData](./firestore_lite.documentdata.md#documentdata_interface) | Document data (for use with [setDoc()](./firestore_lite.md#setdoc_ee215ad)) consists of fields mapped to values. | -| [FirestoreDataConverter](./firestore_lite.firestoredataconverter.md#firestoredataconverter_interface) | Converter used by withConverter() to transform user objects of type AppModelType into Firestore data of type DbModelType.Using the converter allows you to specify generic type arguments when storing and retrieving objects from Firestore. | +| [FirestoreDataConverter](./firestore_lite.firestoredataconverter.md#firestoredataconverter_interface) | Converter used by withConverter() to transform user objects of type AppModelType into Firestore data of type DbModelType.Using the converter allows you to specify generic type arguments when storing and retrieving objects from Firestore.In this context, an "AppModel" is a class that is used in an application to package together related information and functionality. Such a class could, for example, have properties with complex, nested data types, properties used for memoization, properties of types not supported by Firestore (such as symbol and bigint), and helper functions that perform compound operations. Such classes are not suitable and/or possible to store into a Firestore database. Instead, instances of such classes need to be converted to "plain old JavaScript objects" (POJOs) with exclusively primitive properties, potentially nested inside other POJOs or arrays of POJOs. In this context, this type is referred to as the "DbModel" and would be an object suitable for persisting into Firestore. For convenience, applications can implement FirestoreDataConverter and register the converter with Firestore objects, such as DocumentReference or Query, to automatically convert AppModel to DbModel when storing into Firestore, and convert DbModel to AppModel when retrieving from Firestore. | | [Settings](./firestore_lite.settings.md#settings_interface) | Specifies custom configurations for your Cloud Firestore instance. You must set these before invoking any other methods. | | [TransactionOptions](./firestore_lite.transactionoptions.md#transactionoptions_interface) | Options to customize transaction behavior. | diff --git a/docs-devsite/index.md b/docs-devsite/index.md index 6a32ccdbaa6..2c22b58d80c 100644 --- a/docs-devsite/index.md +++ b/docs-devsite/index.md @@ -27,4 +27,5 @@ https://github.com/firebase/firebase-js-sdk | [@firebase/performance](./performance.md#performance_package) | The Firebase Performance Monitoring Web SDK. This SDK does not work in a Node.js environment. | | [@firebase/remote-config](./remote-config.md#remote-config_package) | The Firebase Remote Config Web SDK. This SDK does not work in a Node.js environment. | | [@firebase/storage](./storage.md#storage_package) | Cloud Storage for Firebase | +| [@firebase/vertexai-preview](./vertexai-preview.md#vertexai-preview_package) | The Vertex AI For Firebase Web SDK. | diff --git a/docs-devsite/vertexai-preview.baseparams.md b/docs-devsite/vertexai-preview.baseparams.md new file mode 100644 index 00000000000..6756c919ccc --- /dev/null +++ b/docs-devsite/vertexai-preview.baseparams.md @@ -0,0 +1,42 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# BaseParams interface +Base parameters for a number of methods. + +Signature: + +```typescript +export interface BaseParams +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [generationConfig](./vertexai-preview.baseparams.md#baseparamsgenerationconfig) | [GenerationConfig](./vertexai-preview.generationconfig.md#generationconfig_interface) | | +| [safetySettings](./vertexai-preview.baseparams.md#baseparamssafetysettings) | [SafetySetting](./vertexai-preview.safetysetting.md#safetysetting_interface)\[\] | | + +## BaseParams.generationConfig + +Signature: + +```typescript +generationConfig?: GenerationConfig; +``` + +## BaseParams.safetySettings + +Signature: + +```typescript +safetySettings?: SafetySetting[]; +``` diff --git a/docs-devsite/vertexai-preview.chatsession.md b/docs-devsite/vertexai-preview.chatsession.md new file mode 100644 index 00000000000..3d78bab3745 --- /dev/null +++ b/docs-devsite/vertexai-preview.chatsession.md @@ -0,0 +1,138 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# ChatSession class +ChatSession class that enables sending chat messages and stores history of sent and received messages so far. + +Signature: + +```typescript +export declare class ChatSession +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(apiSettings, model, params, requestOptions)](./vertexai-preview.chatsession.md#chatsessionconstructor) | | Constructs a new instance of the ChatSession class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [model](./vertexai-preview.chatsession.md#chatsessionmodel) | | string | | +| [params](./vertexai-preview.chatsession.md#chatsessionparams) | | [StartChatParams](./vertexai-preview.startchatparams.md#startchatparams_interface) \| undefined | | +| [requestOptions](./vertexai-preview.chatsession.md#chatsessionrequestoptions) | | [RequestOptions](./vertexai-preview.requestoptions.md#requestoptions_interface) \| undefined | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [getHistory()](./vertexai-preview.chatsession.md#chatsessiongethistory) | | Gets the chat history so far. Blocked prompts are not added to history. Blocked candidates are not added to history, nor are the prompts that generated them. | +| [sendMessage(request)](./vertexai-preview.chatsession.md#chatsessionsendmessage) | | Sends a chat message and receives a non-streaming [GenerateContentResult](./vertexai-preview.generatecontentresult.md#generatecontentresult_interface) | +| [sendMessageStream(request)](./vertexai-preview.chatsession.md#chatsessionsendmessagestream) | | Sends a chat message and receives the response as a [GenerateContentStreamResult](./vertexai-preview.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. | + +## ChatSession.(constructor) + +Constructs a new instance of the `ChatSession` class + +Signature: + +```typescript +constructor(apiSettings: ApiSettings, model: string, params?: StartChatParams | undefined, requestOptions?: RequestOptions | undefined); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| apiSettings | ApiSettings | | +| model | string | | +| params | [StartChatParams](./vertexai-preview.startchatparams.md#startchatparams_interface) \| undefined | | +| requestOptions | [RequestOptions](./vertexai-preview.requestoptions.md#requestoptions_interface) \| undefined | | + +## ChatSession.model + +Signature: + +```typescript +model: string; +``` + +## ChatSession.params + +Signature: + +```typescript +params?: StartChatParams | undefined; +``` + +## ChatSession.requestOptions + +Signature: + +```typescript +requestOptions?: RequestOptions | undefined; +``` + +## ChatSession.getHistory() + +Gets the chat history so far. Blocked prompts are not added to history. Blocked candidates are not added to history, nor are the prompts that generated them. + +Signature: + +```typescript +getHistory(): Promise; +``` +Returns: + +Promise<[Content](./vertexai-preview.content.md#content_interface)\[\]> + +## ChatSession.sendMessage() + +Sends a chat message and receives a non-streaming [GenerateContentResult](./vertexai-preview.generatecontentresult.md#generatecontentresult_interface) + +Signature: + +```typescript +sendMessage(request: string | Array): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| request | string \| Array<string \| [Part](./vertexai-preview.md#part)> | | + +Returns: + +Promise<[GenerateContentResult](./vertexai-preview.generatecontentresult.md#generatecontentresult_interface)> + +## ChatSession.sendMessageStream() + +Sends a chat message and receives the response as a [GenerateContentStreamResult](./vertexai-preview.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. + +Signature: + +```typescript +sendMessageStream(request: string | Array): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| request | string \| Array<string \| [Part](./vertexai-preview.md#part)> | | + +Returns: + +Promise<[GenerateContentStreamResult](./vertexai-preview.generatecontentstreamresult.md#generatecontentstreamresult_interface)> + diff --git a/docs-devsite/vertexai-preview.citation.md b/docs-devsite/vertexai-preview.citation.md new file mode 100644 index 00000000000..10a615ee247 --- /dev/null +++ b/docs-devsite/vertexai-preview.citation.md @@ -0,0 +1,78 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Citation interface +A single citation. + +Signature: + +```typescript +export interface Citation +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [endIndex](./vertexai-preview.citation.md#citationendindex) | number | | +| [license](./vertexai-preview.citation.md#citationlicense) | string | | +| [publicationDate](./vertexai-preview.citation.md#citationpublicationdate) | Date | | +| [startIndex](./vertexai-preview.citation.md#citationstartindex) | number | | +| [title](./vertexai-preview.citation.md#citationtitle) | string | | +| [uri](./vertexai-preview.citation.md#citationuri) | string | | + +## Citation.endIndex + +Signature: + +```typescript +endIndex?: number; +``` + +## Citation.license + +Signature: + +```typescript +license?: string; +``` + +## Citation.publicationDate + +Signature: + +```typescript +publicationDate?: Date; +``` + +## Citation.startIndex + +Signature: + +```typescript +startIndex?: number; +``` + +## Citation.title + +Signature: + +```typescript +title?: string; +``` + +## Citation.uri + +Signature: + +```typescript +uri?: string; +``` diff --git a/docs-devsite/vertexai-preview.citationmetadata.md b/docs-devsite/vertexai-preview.citationmetadata.md new file mode 100644 index 00000000000..fa740ca1af7 --- /dev/null +++ b/docs-devsite/vertexai-preview.citationmetadata.md @@ -0,0 +1,33 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# CitationMetadata interface +Citation metadata that may be found on a [GenerateContentCandidate](./vertexai-preview.generatecontentcandidate.md#generatecontentcandidate_interface). + +Signature: + +```typescript +export interface CitationMetadata +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [citations](./vertexai-preview.citationmetadata.md#citationmetadatacitations) | [Citation](./vertexai-preview.citation.md#citation_interface)\[\] | | + +## CitationMetadata.citations + +Signature: + +```typescript +citations: Citation[]; +``` diff --git a/docs-devsite/vertexai-preview.content.md b/docs-devsite/vertexai-preview.content.md new file mode 100644 index 00000000000..26198a3951f --- /dev/null +++ b/docs-devsite/vertexai-preview.content.md @@ -0,0 +1,42 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Content interface +Content type for both prompts and response candidates. + +Signature: + +```typescript +export interface Content +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [parts](./vertexai-preview.content.md#contentparts) | [Part](./vertexai-preview.md#part)\[\] | | +| [role](./vertexai-preview.content.md#contentrole) | [Role](./vertexai-preview.md#role) | | + +## Content.parts + +Signature: + +```typescript +parts: Part[]; +``` + +## Content.role + +Signature: + +```typescript +role: Role; +``` diff --git a/docs-devsite/vertexai-preview.counttokensrequest.md b/docs-devsite/vertexai-preview.counttokensrequest.md new file mode 100644 index 00000000000..07e5f0d85f3 --- /dev/null +++ b/docs-devsite/vertexai-preview.counttokensrequest.md @@ -0,0 +1,33 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# CountTokensRequest interface +Params for calling [GenerativeModel.countTokens()](./vertexai-preview.generativemodel.md#generativemodelcounttokens) + +Signature: + +```typescript +export interface CountTokensRequest +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [contents](./vertexai-preview.counttokensrequest.md#counttokensrequestcontents) | [Content](./vertexai-preview.content.md#content_interface)\[\] | | + +## CountTokensRequest.contents + +Signature: + +```typescript +contents: Content[]; +``` diff --git a/docs-devsite/vertexai-preview.counttokensresponse.md b/docs-devsite/vertexai-preview.counttokensresponse.md new file mode 100644 index 00000000000..d097d5aacff --- /dev/null +++ b/docs-devsite/vertexai-preview.counttokensresponse.md @@ -0,0 +1,46 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# CountTokensResponse interface +Response from calling [GenerativeModel.countTokens()](./vertexai-preview.generativemodel.md#generativemodelcounttokens). + +Signature: + +```typescript +export interface CountTokensResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [totalBillableCharacters](./vertexai-preview.counttokensresponse.md#counttokensresponsetotalbillablecharacters) | number | The total number of billable characters counted across all instances from the request. | +| [totalTokens](./vertexai-preview.counttokensresponse.md#counttokensresponsetotaltokens) | number | The total number of tokens counted across all instances from the request. | + +## CountTokensResponse.totalBillableCharacters + +The total number of billable characters counted across all instances from the request. + +Signature: + +```typescript +totalBillableCharacters?: number; +``` + +## CountTokensResponse.totalTokens + +The total number of tokens counted across all instances from the request. + +Signature: + +```typescript +totalTokens: number; +``` diff --git a/docs-devsite/vertexai-preview.date_2.md b/docs-devsite/vertexai-preview.date_2.md new file mode 100644 index 00000000000..5af031447c4 --- /dev/null +++ b/docs-devsite/vertexai-preview.date_2.md @@ -0,0 +1,51 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Date_2 interface +Protobuf google.type.Date + +Signature: + +```typescript +export interface Date +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [day](./vertexai-preview.date_2.md#date_2day) | number | | +| [month](./vertexai-preview.date_2.md#date_2month) | number | | +| [year](./vertexai-preview.date_2.md#date_2year) | number | | + +## Date\_2.day + +Signature: + +```typescript +day: number; +``` + +## Date\_2.month + +Signature: + +```typescript +month: number; +``` + +## Date\_2.year + +Signature: + +```typescript +year: number; +``` diff --git a/docs-devsite/vertexai-preview.enhancedgeneratecontentresponse.md b/docs-devsite/vertexai-preview.enhancedgeneratecontentresponse.md new file mode 100644 index 00000000000..132c5ed0be2 --- /dev/null +++ b/docs-devsite/vertexai-preview.enhancedgeneratecontentresponse.md @@ -0,0 +1,45 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# EnhancedGenerateContentResponse interface +Response object wrapped with helper methods. + +Signature: + +```typescript +export interface EnhancedGenerateContentResponse extends GenerateContentResponse +``` +Extends: [GenerateContentResponse](./vertexai-preview.generatecontentresponse.md#generatecontentresponse_interface) + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [functionCalls](./vertexai-preview.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponsefunctioncalls) | () => [FunctionCall](./vertexai-preview.functioncall.md#functioncall_interface)\[\] \| undefined | | +| [text](./vertexai-preview.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponsetext) | () => string | Returns the text string from the response, if available. Throws if the prompt or candidate was blocked. | + +## EnhancedGenerateContentResponse.functionCalls + +Signature: + +```typescript +functionCalls: () => FunctionCall[] | undefined; +``` + +## EnhancedGenerateContentResponse.text + +Returns the text string from the response, if available. Throws if the prompt or candidate was blocked. + +Signature: + +```typescript +text: () => string; +``` diff --git a/docs-devsite/vertexai-preview.filedata.md b/docs-devsite/vertexai-preview.filedata.md new file mode 100644 index 00000000000..577b4b1910d --- /dev/null +++ b/docs-devsite/vertexai-preview.filedata.md @@ -0,0 +1,42 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FileData interface +Data pointing to a file uploaded on Google Cloud Storage. + +Signature: + +```typescript +export interface FileData +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [fileUri](./vertexai-preview.filedata.md#filedatafileuri) | string | | +| [mimeType](./vertexai-preview.filedata.md#filedatamimetype) | string | | + +## FileData.fileUri + +Signature: + +```typescript +fileUri: string; +``` + +## FileData.mimeType + +Signature: + +```typescript +mimeType: string; +``` diff --git a/docs-devsite/vertexai-preview.filedatapart.md b/docs-devsite/vertexai-preview.filedatapart.md new file mode 100644 index 00000000000..e03c056f588 --- /dev/null +++ b/docs-devsite/vertexai-preview.filedatapart.md @@ -0,0 +1,69 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FileDataPart interface +Content part interface if the part represents [FileData](./vertexai-preview.filedata.md#filedata_interface) + +Signature: + +```typescript +export interface FileDataPart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [fileData](./vertexai-preview.filedatapart.md#filedatapartfiledata) | [FileData](./vertexai-preview.filedata.md#filedata_interface) | | +| [functionCall](./vertexai-preview.filedatapart.md#filedatapartfunctioncall) | never | | +| [functionResponse](./vertexai-preview.filedatapart.md#filedatapartfunctionresponse) | never | | +| [inlineData](./vertexai-preview.filedatapart.md#filedatapartinlinedata) | never | | +| [text](./vertexai-preview.filedatapart.md#filedataparttext) | never | | + +## FileDataPart.fileData + +Signature: + +```typescript +fileData: FileData; +``` + +## FileDataPart.functionCall + +Signature: + +```typescript +functionCall?: never; +``` + +## FileDataPart.functionResponse + +Signature: + +```typescript +functionResponse?: never; +``` + +## FileDataPart.inlineData + +Signature: + +```typescript +inlineData?: never; +``` + +## FileDataPart.text + +Signature: + +```typescript +text?: never; +``` diff --git a/docs-devsite/vertexai-preview.functioncall.md b/docs-devsite/vertexai-preview.functioncall.md new file mode 100644 index 00000000000..60e0ea50dc4 --- /dev/null +++ b/docs-devsite/vertexai-preview.functioncall.md @@ -0,0 +1,42 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FunctionCall interface +A predicted [FunctionCall](./vertexai-preview.functioncall.md#functioncall_interface) returned from the model that contains a string representing the [FunctionDeclaration.name](./vertexai-preview.functiondeclaration.md#functiondeclarationname) and a structured JSON object containing the parameters and their values. + +Signature: + +```typescript +export interface FunctionCall +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [args](./vertexai-preview.functioncall.md#functioncallargs) | object | | +| [name](./vertexai-preview.functioncall.md#functioncallname) | string | | + +## FunctionCall.args + +Signature: + +```typescript +args: object; +``` + +## FunctionCall.name + +Signature: + +```typescript +name: string; +``` diff --git a/docs-devsite/vertexai-preview.functioncallingconfig.md b/docs-devsite/vertexai-preview.functioncallingconfig.md new file mode 100644 index 00000000000..1965fb76e95 --- /dev/null +++ b/docs-devsite/vertexai-preview.functioncallingconfig.md @@ -0,0 +1,41 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FunctionCallingConfig interface + +Signature: + +```typescript +export interface FunctionCallingConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [allowedFunctionNames](./vertexai-preview.functioncallingconfig.md#functioncallingconfigallowedfunctionnames) | string\[\] | | +| [mode](./vertexai-preview.functioncallingconfig.md#functioncallingconfigmode) | [FunctionCallingMode](./vertexai-preview.md#functioncallingmode) | | + +## FunctionCallingConfig.allowedFunctionNames + +Signature: + +```typescript +allowedFunctionNames?: string[]; +``` + +## FunctionCallingConfig.mode + +Signature: + +```typescript +mode?: FunctionCallingMode; +``` diff --git a/docs-devsite/vertexai-preview.functioncallpart.md b/docs-devsite/vertexai-preview.functioncallpart.md new file mode 100644 index 00000000000..5da204692f9 --- /dev/null +++ b/docs-devsite/vertexai-preview.functioncallpart.md @@ -0,0 +1,60 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FunctionCallPart interface +Content part interface if the part represents a [FunctionCall](./vertexai-preview.functioncall.md#functioncall_interface). + +Signature: + +```typescript +export interface FunctionCallPart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [functionCall](./vertexai-preview.functioncallpart.md#functioncallpartfunctioncall) | [FunctionCall](./vertexai-preview.functioncall.md#functioncall_interface) | | +| [functionResponse](./vertexai-preview.functioncallpart.md#functioncallpartfunctionresponse) | never | | +| [inlineData](./vertexai-preview.functioncallpart.md#functioncallpartinlinedata) | never | | +| [text](./vertexai-preview.functioncallpart.md#functioncallparttext) | never | | + +## FunctionCallPart.functionCall + +Signature: + +```typescript +functionCall: FunctionCall; +``` + +## FunctionCallPart.functionResponse + +Signature: + +```typescript +functionResponse?: never; +``` + +## FunctionCallPart.inlineData + +Signature: + +```typescript +inlineData?: never; +``` + +## FunctionCallPart.text + +Signature: + +```typescript +text?: never; +``` diff --git a/docs-devsite/vertexai-preview.functiondeclaration.md b/docs-devsite/vertexai-preview.functiondeclaration.md new file mode 100644 index 00000000000..e725b9557e1 --- /dev/null +++ b/docs-devsite/vertexai-preview.functiondeclaration.md @@ -0,0 +1,57 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FunctionDeclaration interface +Structured representation of a function declaration as defined by the [OpenAPI 3.0 specification](https://spec.openapis.org/oas/v3.0.3). Included in this declaration are the function name and parameters. This `FunctionDeclaration` is a representation of a block of code that can be used as a Tool by the model and executed by the client. + +Signature: + +```typescript +export declare interface FunctionDeclaration +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [description](./vertexai-preview.functiondeclaration.md#functiondeclarationdescription) | string | Optional. Description and purpose of the function. Model uses it to decide how and whether to call the function. | +| [name](./vertexai-preview.functiondeclaration.md#functiondeclarationname) | string | The name of the function to call. Must start with a letter or an underscore. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a max length of 64. | +| [parameters](./vertexai-preview.functiondeclaration.md#functiondeclarationparameters) | [FunctionDeclarationSchema](./vertexai-preview.functiondeclarationschema.md#functiondeclarationschema_interface) | Optional. Describes the parameters to this function in JSON Schema Object format. Reflects the Open API 3.03 Parameter Object. Parameter names are case sensitive. For a function with no parameters, this can be left unset. | + +## FunctionDeclaration.description + +Optional. Description and purpose of the function. Model uses it to decide how and whether to call the function. + +Signature: + +```typescript +description?: string; +``` + +## FunctionDeclaration.name + +The name of the function to call. Must start with a letter or an underscore. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a max length of 64. + +Signature: + +```typescript +name: string; +``` + +## FunctionDeclaration.parameters + +Optional. Describes the parameters to this function in JSON Schema Object format. Reflects the Open API 3.03 Parameter Object. Parameter names are case sensitive. For a function with no parameters, this can be left unset. + +Signature: + +```typescript +parameters?: FunctionDeclarationSchema; +``` diff --git a/docs-devsite/vertexai-preview.functiondeclarationschema.md b/docs-devsite/vertexai-preview.functiondeclarationschema.md new file mode 100644 index 00000000000..7d0e5809d41 --- /dev/null +++ b/docs-devsite/vertexai-preview.functiondeclarationschema.md @@ -0,0 +1,70 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FunctionDeclarationSchema interface +Schema for parameters passed to [FunctionDeclaration.parameters](./vertexai-preview.functiondeclaration.md#functiondeclarationparameters). + +Signature: + +```typescript +export interface FunctionDeclarationSchema +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [description](./vertexai-preview.functiondeclarationschema.md#functiondeclarationschemadescription) | string | Optional. Description of the parameter. | +| [properties](./vertexai-preview.functiondeclarationschema.md#functiondeclarationschemaproperties) | { \[k: string\]: [FunctionDeclarationSchemaProperty](./vertexai-preview.functiondeclarationschemaproperty.md#functiondeclarationschemaproperty_interface); } | The format of the parameter. | +| [required](./vertexai-preview.functiondeclarationschema.md#functiondeclarationschemarequired) | string\[\] | Optional. Array of required parameters. | +| [type](./vertexai-preview.functiondeclarationschema.md#functiondeclarationschematype) | [FunctionDeclarationSchemaType](./vertexai-preview.md#functiondeclarationschematype) | The type of the parameter. | + +## FunctionDeclarationSchema.description + +Optional. Description of the parameter. + +Signature: + +```typescript +description?: string; +``` + +## FunctionDeclarationSchema.properties + +The format of the parameter. + +Signature: + +```typescript +properties: { + [k: string]: FunctionDeclarationSchemaProperty; + }; +``` + +## FunctionDeclarationSchema.required + +Optional. Array of required parameters. + +Signature: + +```typescript +required?: string[]; +``` + +## FunctionDeclarationSchema.type + +The type of the parameter. + +Signature: + +```typescript +type: FunctionDeclarationSchemaType; +``` diff --git a/docs-devsite/vertexai-preview.functiondeclarationschemaproperty.md b/docs-devsite/vertexai-preview.functiondeclarationschemaproperty.md new file mode 100644 index 00000000000..ac2e1262dd0 --- /dev/null +++ b/docs-devsite/vertexai-preview.functiondeclarationschemaproperty.md @@ -0,0 +1,125 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FunctionDeclarationSchemaProperty interface +Schema is used to define the format of input/output data. Represents a select subset of an OpenAPI 3.0 schema object. More fields may be added in the future as needed. + +Signature: + +```typescript +export interface FunctionDeclarationSchemaProperty +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [description](./vertexai-preview.functiondeclarationschemaproperty.md#functiondeclarationschemapropertydescription) | string | Optional. The description of the property. | +| [enum](./vertexai-preview.functiondeclarationschemaproperty.md#functiondeclarationschemapropertyenum) | string\[\] | Optional. The enum of the property. | +| [example](./vertexai-preview.functiondeclarationschemaproperty.md#functiondeclarationschemapropertyexample) | unknown | Optional. The example of the property. | +| [format](./vertexai-preview.functiondeclarationschemaproperty.md#functiondeclarationschemapropertyformat) | string | Optional. The format of the property. | +| [items](./vertexai-preview.functiondeclarationschemaproperty.md#functiondeclarationschemapropertyitems) | [FunctionDeclarationSchema](./vertexai-preview.functiondeclarationschema.md#functiondeclarationschema_interface) | Optional. The items of the property. [FunctionDeclarationSchema](./vertexai-preview.functiondeclarationschema.md#functiondeclarationschema_interface) | +| [nullable](./vertexai-preview.functiondeclarationschemaproperty.md#functiondeclarationschemapropertynullable) | boolean | Optional. Whether the property is nullable. | +| [properties](./vertexai-preview.functiondeclarationschemaproperty.md#functiondeclarationschemapropertyproperties) | { \[k: string\]: [FunctionDeclarationSchema](./vertexai-preview.functiondeclarationschema.md#functiondeclarationschema_interface); } | Optional. Map of [FunctionDeclarationSchema](./vertexai-preview.functiondeclarationschema.md#functiondeclarationschema_interface). | +| [required](./vertexai-preview.functiondeclarationschemaproperty.md#functiondeclarationschemapropertyrequired) | string\[\] | Optional. Array of required property. | +| [type](./vertexai-preview.functiondeclarationschemaproperty.md#functiondeclarationschemapropertytype) | [FunctionDeclarationSchemaType](./vertexai-preview.md#functiondeclarationschematype) | Optional. The type of the property. [FunctionDeclarationSchemaType](./vertexai-preview.md#functiondeclarationschematype). | + +## FunctionDeclarationSchemaProperty.description + +Optional. The description of the property. + +Signature: + +```typescript +description?: string; +``` + +## FunctionDeclarationSchemaProperty.enum + +Optional. The enum of the property. + +Signature: + +```typescript +enum?: string[]; +``` + +## FunctionDeclarationSchemaProperty.example + +Optional. The example of the property. + +Signature: + +```typescript +example?: unknown; +``` + +## FunctionDeclarationSchemaProperty.format + +Optional. The format of the property. + +Signature: + +```typescript +format?: string; +``` + +## FunctionDeclarationSchemaProperty.items + +Optional. The items of the property. [FunctionDeclarationSchema](./vertexai-preview.functiondeclarationschema.md#functiondeclarationschema_interface) + +Signature: + +```typescript +items?: FunctionDeclarationSchema; +``` + +## FunctionDeclarationSchemaProperty.nullable + +Optional. Whether the property is nullable. + +Signature: + +```typescript +nullable?: boolean; +``` + +## FunctionDeclarationSchemaProperty.properties + +Optional. Map of [FunctionDeclarationSchema](./vertexai-preview.functiondeclarationschema.md#functiondeclarationschema_interface). + +Signature: + +```typescript +properties?: { + [k: string]: FunctionDeclarationSchema; + }; +``` + +## FunctionDeclarationSchemaProperty.required + +Optional. Array of required property. + +Signature: + +```typescript +required?: string[]; +``` + +## FunctionDeclarationSchemaProperty.type + +Optional. The type of the property. [FunctionDeclarationSchemaType](./vertexai-preview.md#functiondeclarationschematype). + +Signature: + +```typescript +type?: FunctionDeclarationSchemaType; +``` diff --git a/docs-devsite/vertexai-preview.functiondeclarationstool.md b/docs-devsite/vertexai-preview.functiondeclarationstool.md new file mode 100644 index 00000000000..d1af4351a23 --- /dev/null +++ b/docs-devsite/vertexai-preview.functiondeclarationstool.md @@ -0,0 +1,35 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FunctionDeclarationsTool interface +A `FunctionDeclarationsTool` is a piece of code that enables the system to interact with external systems to perform an action, or set of actions, outside of knowledge and scope of the model. + +Signature: + +```typescript +export declare interface FunctionDeclarationsTool +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [functionDeclarations](./vertexai-preview.functiondeclarationstool.md#functiondeclarationstoolfunctiondeclarations) | [FunctionDeclaration](./vertexai-preview.functiondeclaration.md#functiondeclaration_interface)\[\] | Optional. One or more function declarations to be passed to the model along with the current user query. Model may decide to call a subset of these functions by populating [FunctionCall](./vertexai-preview.functioncall.md#functioncall_interface) in the response. User should provide a [FunctionResponse](./vertexai-preview.functionresponse.md#functionresponse_interface) for each function call in the next turn. Based on the function responses, the model will generate the final response back to the user. Maximum 64 function declarations can be provided. | + +## FunctionDeclarationsTool.functionDeclarations + +Optional. One or more function declarations to be passed to the model along with the current user query. Model may decide to call a subset of these functions by populating [FunctionCall](./vertexai-preview.functioncall.md#functioncall_interface) in the response. User should provide a [FunctionResponse](./vertexai-preview.functionresponse.md#functionresponse_interface) for each function call in the next turn. Based on the function responses, the model will generate the final response back to the user. Maximum 64 function declarations can be provided. + +Signature: + +```typescript +functionDeclarations?: FunctionDeclaration[]; +``` diff --git a/docs-devsite/vertexai-preview.functionresponse.md b/docs-devsite/vertexai-preview.functionresponse.md new file mode 100644 index 00000000000..d89ace08df1 --- /dev/null +++ b/docs-devsite/vertexai-preview.functionresponse.md @@ -0,0 +1,42 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FunctionResponse interface +The result output from a [FunctionCall](./vertexai-preview.functioncall.md#functioncall_interface) that contains a string representing the [FunctionDeclaration.name](./vertexai-preview.functiondeclaration.md#functiondeclarationname) and a structured JSON object containing any output from the function is used as context to the model. This should contain the result of a [FunctionCall](./vertexai-preview.functioncall.md#functioncall_interface) made based on model prediction. + +Signature: + +```typescript +export interface FunctionResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [name](./vertexai-preview.functionresponse.md#functionresponsename) | string | | +| [response](./vertexai-preview.functionresponse.md#functionresponseresponse) | object | | + +## FunctionResponse.name + +Signature: + +```typescript +name: string; +``` + +## FunctionResponse.response + +Signature: + +```typescript +response: object; +``` diff --git a/docs-devsite/vertexai-preview.functionresponsepart.md b/docs-devsite/vertexai-preview.functionresponsepart.md new file mode 100644 index 00000000000..4e246d625f6 --- /dev/null +++ b/docs-devsite/vertexai-preview.functionresponsepart.md @@ -0,0 +1,60 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# FunctionResponsePart interface +Content part interface if the part represents [FunctionResponse](./vertexai-preview.functionresponse.md#functionresponse_interface). + +Signature: + +```typescript +export interface FunctionResponsePart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [functionCall](./vertexai-preview.functionresponsepart.md#functionresponsepartfunctioncall) | never | | +| [functionResponse](./vertexai-preview.functionresponsepart.md#functionresponsepartfunctionresponse) | [FunctionResponse](./vertexai-preview.functionresponse.md#functionresponse_interface) | | +| [inlineData](./vertexai-preview.functionresponsepart.md#functionresponsepartinlinedata) | never | | +| [text](./vertexai-preview.functionresponsepart.md#functionresponseparttext) | never | | + +## FunctionResponsePart.functionCall + +Signature: + +```typescript +functionCall?: never; +``` + +## FunctionResponsePart.functionResponse + +Signature: + +```typescript +functionResponse: FunctionResponse; +``` + +## FunctionResponsePart.inlineData + +Signature: + +```typescript +inlineData?: never; +``` + +## FunctionResponsePart.text + +Signature: + +```typescript +text?: never; +``` diff --git a/docs-devsite/vertexai-preview.generatecontentcandidate.md b/docs-devsite/vertexai-preview.generatecontentcandidate.md new file mode 100644 index 00000000000..9f36fab1e87 --- /dev/null +++ b/docs-devsite/vertexai-preview.generatecontentcandidate.md @@ -0,0 +1,87 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# GenerateContentCandidate interface +A candidate returned as part of a [GenerateContentResponse](./vertexai-preview.generatecontentresponse.md#generatecontentresponse_interface). + +Signature: + +```typescript +export interface GenerateContentCandidate +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [citationMetadata](./vertexai-preview.generatecontentcandidate.md#generatecontentcandidatecitationmetadata) | [CitationMetadata](./vertexai-preview.citationmetadata.md#citationmetadata_interface) | | +| [content](./vertexai-preview.generatecontentcandidate.md#generatecontentcandidatecontent) | [Content](./vertexai-preview.content.md#content_interface) | | +| [finishMessage](./vertexai-preview.generatecontentcandidate.md#generatecontentcandidatefinishmessage) | string | | +| [finishReason](./vertexai-preview.generatecontentcandidate.md#generatecontentcandidatefinishreason) | [FinishReason](./vertexai-preview.md#finishreason) | | +| [groundingMetadata](./vertexai-preview.generatecontentcandidate.md#generatecontentcandidategroundingmetadata) | [GroundingMetadata](./vertexai-preview.groundingmetadata.md#groundingmetadata_interface) | | +| [index](./vertexai-preview.generatecontentcandidate.md#generatecontentcandidateindex) | number | | +| [safetyRatings](./vertexai-preview.generatecontentcandidate.md#generatecontentcandidatesafetyratings) | [SafetyRating](./vertexai-preview.safetyrating.md#safetyrating_interface)\[\] | | + +## GenerateContentCandidate.citationMetadata + +Signature: + +```typescript +citationMetadata?: CitationMetadata; +``` + +## GenerateContentCandidate.content + +Signature: + +```typescript +content: Content; +``` + +## GenerateContentCandidate.finishMessage + +Signature: + +```typescript +finishMessage?: string; +``` + +## GenerateContentCandidate.finishReason + +Signature: + +```typescript +finishReason?: FinishReason; +``` + +## GenerateContentCandidate.groundingMetadata + +Signature: + +```typescript +groundingMetadata?: GroundingMetadata; +``` + +## GenerateContentCandidate.index + +Signature: + +```typescript +index: number; +``` + +## GenerateContentCandidate.safetyRatings + +Signature: + +```typescript +safetyRatings?: SafetyRating[]; +``` diff --git a/docs-devsite/vertexai-preview.generatecontentrequest.md b/docs-devsite/vertexai-preview.generatecontentrequest.md new file mode 100644 index 00000000000..68ce52340e8 --- /dev/null +++ b/docs-devsite/vertexai-preview.generatecontentrequest.md @@ -0,0 +1,61 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# GenerateContentRequest interface +Request sent through [GenerativeModel.generateContent()](./vertexai-preview.generativemodel.md#generativemodelgeneratecontent) + +Signature: + +```typescript +export interface GenerateContentRequest extends BaseParams +``` +Extends: [BaseParams](./vertexai-preview.baseparams.md#baseparams_interface) + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [contents](./vertexai-preview.generatecontentrequest.md#generatecontentrequestcontents) | [Content](./vertexai-preview.content.md#content_interface)\[\] | | +| [systemInstruction](./vertexai-preview.generatecontentrequest.md#generatecontentrequestsysteminstruction) | string \| [Part](./vertexai-preview.md#part) \| [Content](./vertexai-preview.content.md#content_interface) | | +| [toolConfig](./vertexai-preview.generatecontentrequest.md#generatecontentrequesttoolconfig) | [ToolConfig](./vertexai-preview.toolconfig.md#toolconfig_interface) | | +| [tools](./vertexai-preview.generatecontentrequest.md#generatecontentrequesttools) | [Tool](./vertexai-preview.md#tool)\[\] | | + +## GenerateContentRequest.contents + +Signature: + +```typescript +contents: Content[]; +``` + +## GenerateContentRequest.systemInstruction + +Signature: + +```typescript +systemInstruction?: string | Part | Content; +``` + +## GenerateContentRequest.toolConfig + +Signature: + +```typescript +toolConfig?: ToolConfig; +``` + +## GenerateContentRequest.tools + +Signature: + +```typescript +tools?: Tool[]; +``` diff --git a/docs-devsite/vertexai-preview.generatecontentresponse.md b/docs-devsite/vertexai-preview.generatecontentresponse.md new file mode 100644 index 00000000000..cb0fb0e3209 --- /dev/null +++ b/docs-devsite/vertexai-preview.generatecontentresponse.md @@ -0,0 +1,51 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# GenerateContentResponse interface +Individual response from [GenerativeModel.generateContent()](./vertexai-preview.generativemodel.md#generativemodelgeneratecontent) and [GenerativeModel.generateContentStream()](./vertexai-preview.generativemodel.md#generativemodelgeneratecontentstream). `generateContentStream()` will return one in each chunk until the stream is done. + +Signature: + +```typescript +export interface GenerateContentResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [candidates](./vertexai-preview.generatecontentresponse.md#generatecontentresponsecandidates) | [GenerateContentCandidate](./vertexai-preview.generatecontentcandidate.md#generatecontentcandidate_interface)\[\] | | +| [promptFeedback](./vertexai-preview.generatecontentresponse.md#generatecontentresponsepromptfeedback) | [PromptFeedback](./vertexai-preview.promptfeedback.md#promptfeedback_interface) | | +| [usageMetadata](./vertexai-preview.generatecontentresponse.md#generatecontentresponseusagemetadata) | [UsageMetadata](./vertexai-preview.usagemetadata.md#usagemetadata_interface) | | + +## GenerateContentResponse.candidates + +Signature: + +```typescript +candidates?: GenerateContentCandidate[]; +``` + +## GenerateContentResponse.promptFeedback + +Signature: + +```typescript +promptFeedback?: PromptFeedback; +``` + +## GenerateContentResponse.usageMetadata + +Signature: + +```typescript +usageMetadata?: UsageMetadata; +``` diff --git a/docs-devsite/vertexai-preview.generatecontentresult.md b/docs-devsite/vertexai-preview.generatecontentresult.md new file mode 100644 index 00000000000..87249a5bc55 --- /dev/null +++ b/docs-devsite/vertexai-preview.generatecontentresult.md @@ -0,0 +1,33 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# GenerateContentResult interface +Result object returned from [GenerativeModel.generateContent()](./vertexai-preview.generativemodel.md#generativemodelgeneratecontent) call. + +Signature: + +```typescript +export interface GenerateContentResult +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [response](./vertexai-preview.generatecontentresult.md#generatecontentresultresponse) | [EnhancedGenerateContentResponse](./vertexai-preview.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponse_interface) | | + +## GenerateContentResult.response + +Signature: + +```typescript +response: EnhancedGenerateContentResponse; +``` diff --git a/docs-devsite/vertexai-preview.generatecontentstreamresult.md b/docs-devsite/vertexai-preview.generatecontentstreamresult.md new file mode 100644 index 00000000000..6fd46600079 --- /dev/null +++ b/docs-devsite/vertexai-preview.generatecontentstreamresult.md @@ -0,0 +1,42 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# GenerateContentStreamResult interface +Result object returned from [GenerativeModel.generateContentStream()](./vertexai-preview.generativemodel.md#generativemodelgeneratecontentstream) call. Iterate over `stream` to get chunks as they come in and/or use the `response` promise to get the aggregated response when the stream is done. + +Signature: + +```typescript +export interface GenerateContentStreamResult +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [response](./vertexai-preview.generatecontentstreamresult.md#generatecontentstreamresultresponse) | Promise<[EnhancedGenerateContentResponse](./vertexai-preview.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponse_interface)> | | +| [stream](./vertexai-preview.generatecontentstreamresult.md#generatecontentstreamresultstream) | AsyncGenerator<[EnhancedGenerateContentResponse](./vertexai-preview.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponse_interface)> | | + +## GenerateContentStreamResult.response + +Signature: + +```typescript +response: Promise; +``` + +## GenerateContentStreamResult.stream + +Signature: + +```typescript +stream: AsyncGenerator; +``` diff --git a/docs-devsite/vertexai-preview.generationconfig.md b/docs-devsite/vertexai-preview.generationconfig.md new file mode 100644 index 00000000000..3b00214d88b --- /dev/null +++ b/docs-devsite/vertexai-preview.generationconfig.md @@ -0,0 +1,107 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# GenerationConfig interface +Config options for content-related requests + +Signature: + +```typescript +export interface GenerationConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [candidateCount](./vertexai-preview.generationconfig.md#generationconfigcandidatecount) | number | | +| [frequencyPenalty](./vertexai-preview.generationconfig.md#generationconfigfrequencypenalty) | number | | +| [maxOutputTokens](./vertexai-preview.generationconfig.md#generationconfigmaxoutputtokens) | number | | +| [presencePenalty](./vertexai-preview.generationconfig.md#generationconfigpresencepenalty) | number | | +| [responseMimeType](./vertexai-preview.generationconfig.md#generationconfigresponsemimetype) | string | Output response mimetype of the generated candidate text. Supported mimetype: text/plain: (default) Text output. application/json: JSON response in the candidates. The model needs to be prompted to output the appropriate response type, otherwise the behavior is undefined. This is a preview feature. | +| [stopSequences](./vertexai-preview.generationconfig.md#generationconfigstopsequences) | string\[\] | | +| [temperature](./vertexai-preview.generationconfig.md#generationconfigtemperature) | number | | +| [topK](./vertexai-preview.generationconfig.md#generationconfigtopk) | number | | +| [topP](./vertexai-preview.generationconfig.md#generationconfigtopp) | number | | + +## GenerationConfig.candidateCount + +Signature: + +```typescript +candidateCount?: number; +``` + +## GenerationConfig.frequencyPenalty + +Signature: + +```typescript +frequencyPenalty?: number; +``` + +## GenerationConfig.maxOutputTokens + +Signature: + +```typescript +maxOutputTokens?: number; +``` + +## GenerationConfig.presencePenalty + +Signature: + +```typescript +presencePenalty?: number; +``` + +## GenerationConfig.responseMimeType + +Output response mimetype of the generated candidate text. Supported mimetype: `text/plain`: (default) Text output. `application/json`: JSON response in the candidates. The model needs to be prompted to output the appropriate response type, otherwise the behavior is undefined. This is a preview feature. + +Signature: + +```typescript +responseMimeType?: string; +``` + +## GenerationConfig.stopSequences + +Signature: + +```typescript +stopSequences?: string[]; +``` + +## GenerationConfig.temperature + +Signature: + +```typescript +temperature?: number; +``` + +## GenerationConfig.topK + +Signature: + +```typescript +topK?: number; +``` + +## GenerationConfig.topP + +Signature: + +```typescript +topP?: number; +``` diff --git a/docs-devsite/vertexai-preview.generativecontentblob.md b/docs-devsite/vertexai-preview.generativecontentblob.md new file mode 100644 index 00000000000..b5dcb272027 --- /dev/null +++ b/docs-devsite/vertexai-preview.generativecontentblob.md @@ -0,0 +1,44 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# GenerativeContentBlob interface +Interface for sending an image. + +Signature: + +```typescript +export interface GenerativeContentBlob +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [data](./vertexai-preview.generativecontentblob.md#generativecontentblobdata) | string | Image as a base64 string. | +| [mimeType](./vertexai-preview.generativecontentblob.md#generativecontentblobmimetype) | string | | + +## GenerativeContentBlob.data + +Image as a base64 string. + +Signature: + +```typescript +data: string; +``` + +## GenerativeContentBlob.mimeType + +Signature: + +```typescript +mimeType: string; +``` diff --git a/docs-devsite/vertexai-preview.generativemodel.md b/docs-devsite/vertexai-preview.generativemodel.md new file mode 100644 index 00000000000..a50fac631cc --- /dev/null +++ b/docs-devsite/vertexai-preview.generativemodel.md @@ -0,0 +1,201 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# GenerativeModel class +Class for generative model APIs. + +Signature: + +```typescript +export declare class GenerativeModel +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(vertexAI, modelParams, requestOptions)](./vertexai-preview.generativemodel.md#generativemodelconstructor) | | Constructs a new instance of the GenerativeModel class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [generationConfig](./vertexai-preview.generativemodel.md#generativemodelgenerationconfig) | | [GenerationConfig](./vertexai-preview.generationconfig.md#generationconfig_interface) | | +| [model](./vertexai-preview.generativemodel.md#generativemodelmodel) | | string | | +| [requestOptions](./vertexai-preview.generativemodel.md#generativemodelrequestoptions) | | [RequestOptions](./vertexai-preview.requestoptions.md#requestoptions_interface) | | +| [safetySettings](./vertexai-preview.generativemodel.md#generativemodelsafetysettings) | | [SafetySetting](./vertexai-preview.safetysetting.md#safetysetting_interface)\[\] | | +| [systemInstruction](./vertexai-preview.generativemodel.md#generativemodelsysteminstruction) | | [Content](./vertexai-preview.content.md#content_interface) | | +| [toolConfig](./vertexai-preview.generativemodel.md#generativemodeltoolconfig) | | [ToolConfig](./vertexai-preview.toolconfig.md#toolconfig_interface) | | +| [tools](./vertexai-preview.generativemodel.md#generativemodeltools) | | [Tool](./vertexai-preview.md#tool)\[\] | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [countTokens(request)](./vertexai-preview.generativemodel.md#generativemodelcounttokens) | | Counts the tokens in the provided request. | +| [generateContent(request)](./vertexai-preview.generativemodel.md#generativemodelgeneratecontent) | | Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./vertexai-preview.generatecontentresponse.md#generatecontentresponse_interface). | +| [generateContentStream(request)](./vertexai-preview.generativemodel.md#generativemodelgeneratecontentstream) | | Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. | +| [startChat(startChatParams)](./vertexai-preview.generativemodel.md#generativemodelstartchat) | | Gets a new [ChatSession](./vertexai-preview.chatsession.md#chatsession_class) instance which can be used for multi-turn chats. | + +## GenerativeModel.(constructor) + +Constructs a new instance of the `GenerativeModel` class + +Signature: + +```typescript +constructor(vertexAI: VertexAI, modelParams: ModelParams, requestOptions?: RequestOptions); +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vertexAI | [VertexAI](./vertexai-preview.vertexai.md#vertexai_interface) | | +| modelParams | [ModelParams](./vertexai-preview.modelparams.md#modelparams_interface) | | +| requestOptions | [RequestOptions](./vertexai-preview.requestoptions.md#requestoptions_interface) | | + +## GenerativeModel.generationConfig + +Signature: + +```typescript +generationConfig: GenerationConfig; +``` + +## GenerativeModel.model + +Signature: + +```typescript +model: string; +``` + +## GenerativeModel.requestOptions + +Signature: + +```typescript +requestOptions?: RequestOptions; +``` + +## GenerativeModel.safetySettings + +Signature: + +```typescript +safetySettings: SafetySetting[]; +``` + +## GenerativeModel.systemInstruction + +Signature: + +```typescript +systemInstruction?: Content; +``` + +## GenerativeModel.toolConfig + +Signature: + +```typescript +toolConfig?: ToolConfig; +``` + +## GenerativeModel.tools + +Signature: + +```typescript +tools?: Tool[]; +``` + +## GenerativeModel.countTokens() + +Counts the tokens in the provided request. + +Signature: + +```typescript +countTokens(request: CountTokensRequest | string | Array): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| request | [CountTokensRequest](./vertexai-preview.counttokensrequest.md#counttokensrequest_interface) \| string \| Array<string \| [Part](./vertexai-preview.md#part)> | | + +Returns: + +Promise<[CountTokensResponse](./vertexai-preview.counttokensresponse.md#counttokensresponse_interface)> + +## GenerativeModel.generateContent() + +Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./vertexai-preview.generatecontentresponse.md#generatecontentresponse_interface). + +Signature: + +```typescript +generateContent(request: GenerateContentRequest | string | Array): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| request | [GenerateContentRequest](./vertexai-preview.generatecontentrequest.md#generatecontentrequest_interface) \| string \| Array<string \| [Part](./vertexai-preview.md#part)> | | + +Returns: + +Promise<[GenerateContentResult](./vertexai-preview.generatecontentresult.md#generatecontentresult_interface)> + +## GenerativeModel.generateContentStream() + +Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. + +Signature: + +```typescript +generateContentStream(request: GenerateContentRequest | string | Array): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| request | [GenerateContentRequest](./vertexai-preview.generatecontentrequest.md#generatecontentrequest_interface) \| string \| Array<string \| [Part](./vertexai-preview.md#part)> | | + +Returns: + +Promise<[GenerateContentStreamResult](./vertexai-preview.generatecontentstreamresult.md#generatecontentstreamresult_interface)> + +## GenerativeModel.startChat() + +Gets a new [ChatSession](./vertexai-preview.chatsession.md#chatsession_class) instance which can be used for multi-turn chats. + +Signature: + +```typescript +startChat(startChatParams?: StartChatParams): ChatSession; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| startChatParams | [StartChatParams](./vertexai-preview.startchatparams.md#startchatparams_interface) | | + +Returns: + +[ChatSession](./vertexai-preview.chatsession.md#chatsession_class) + diff --git a/docs-devsite/vertexai-preview.groundingattribution.md b/docs-devsite/vertexai-preview.groundingattribution.md new file mode 100644 index 00000000000..2c7d2f09e0b --- /dev/null +++ b/docs-devsite/vertexai-preview.groundingattribution.md @@ -0,0 +1,59 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# GroundingAttribution interface + +Signature: + +```typescript +export interface GroundingAttribution +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [confidenceScore](./vertexai-preview.groundingattribution.md#groundingattributionconfidencescore) | number | | +| [retrievedContext](./vertexai-preview.groundingattribution.md#groundingattributionretrievedcontext) | [RetrievedContextAttribution](./vertexai-preview.retrievedcontextattribution.md#retrievedcontextattribution_interface) | | +| [segment](./vertexai-preview.groundingattribution.md#groundingattributionsegment) | [Segment](./vertexai-preview.segment.md#segment_interface) | | +| [web](./vertexai-preview.groundingattribution.md#groundingattributionweb) | [WebAttribution](./vertexai-preview.webattribution.md#webattribution_interface) | | + +## GroundingAttribution.confidenceScore + +Signature: + +```typescript +confidenceScore?: number; +``` + +## GroundingAttribution.retrievedContext + +Signature: + +```typescript +retrievedContext?: RetrievedContextAttribution; +``` + +## GroundingAttribution.segment + +Signature: + +```typescript +segment: Segment; +``` + +## GroundingAttribution.web + +Signature: + +```typescript +web?: WebAttribution; +``` diff --git a/docs-devsite/vertexai-preview.groundingmetadata.md b/docs-devsite/vertexai-preview.groundingmetadata.md new file mode 100644 index 00000000000..5f40a00457d --- /dev/null +++ b/docs-devsite/vertexai-preview.groundingmetadata.md @@ -0,0 +1,51 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# GroundingMetadata interface +Metadata returned to client when grounding is enabled. + +Signature: + +```typescript +export interface GroundingMetadata +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [groundingAttributions](./vertexai-preview.groundingmetadata.md#groundingmetadatagroundingattributions) | [GroundingAttribution](./vertexai-preview.groundingattribution.md#groundingattribution_interface)\[\] | | +| [retrievalQueries](./vertexai-preview.groundingmetadata.md#groundingmetadataretrievalqueries) | string\[\] | | +| [webSearchQueries](./vertexai-preview.groundingmetadata.md#groundingmetadatawebsearchqueries) | string\[\] | | + +## GroundingMetadata.groundingAttributions + +Signature: + +```typescript +groundingAttributions: GroundingAttribution[]; +``` + +## GroundingMetadata.retrievalQueries + +Signature: + +```typescript +retrievalQueries?: string[]; +``` + +## GroundingMetadata.webSearchQueries + +Signature: + +```typescript +webSearchQueries?: string[]; +``` diff --git a/docs-devsite/vertexai-preview.inlinedatapart.md b/docs-devsite/vertexai-preview.inlinedatapart.md new file mode 100644 index 00000000000..ae05f80ddb7 --- /dev/null +++ b/docs-devsite/vertexai-preview.inlinedatapart.md @@ -0,0 +1,71 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# InlineDataPart interface +Content part interface if the part represents an image. + +Signature: + +```typescript +export interface InlineDataPart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [functionCall](./vertexai-preview.inlinedatapart.md#inlinedatapartfunctioncall) | never | | +| [functionResponse](./vertexai-preview.inlinedatapart.md#inlinedatapartfunctionresponse) | never | | +| [inlineData](./vertexai-preview.inlinedatapart.md#inlinedatapartinlinedata) | [GenerativeContentBlob](./vertexai-preview.generativecontentblob.md#generativecontentblob_interface) | | +| [text](./vertexai-preview.inlinedatapart.md#inlinedataparttext) | never | | +| [videoMetadata](./vertexai-preview.inlinedatapart.md#inlinedatapartvideometadata) | [VideoMetadata](./vertexai-preview.videometadata.md#videometadata_interface) | Applicable if inlineData is a video. | + +## InlineDataPart.functionCall + +Signature: + +```typescript +functionCall?: never; +``` + +## InlineDataPart.functionResponse + +Signature: + +```typescript +functionResponse?: never; +``` + +## InlineDataPart.inlineData + +Signature: + +```typescript +inlineData: GenerativeContentBlob; +``` + +## InlineDataPart.text + +Signature: + +```typescript +text?: never; +``` + +## InlineDataPart.videoMetadata + +Applicable if `inlineData` is a video. + +Signature: + +```typescript +videoMetadata?: VideoMetadata; +``` diff --git a/docs-devsite/vertexai-preview.md b/docs-devsite/vertexai-preview.md new file mode 100644 index 00000000000..1aba07d3719 --- /dev/null +++ b/docs-devsite/vertexai-preview.md @@ -0,0 +1,369 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# vertexai-preview package +The Vertex AI For Firebase Web SDK. + +## Functions + +| Function | Description | +| --- | --- | +| function(app, ...) | +| [getVertexAI(app, options)](./vertexai-preview.md#getvertexai_04094cf) | Returns a [VertexAI](./vertexai-preview.vertexai.md#vertexai_interface) instance for the given app. | +| function(vertexAI, ...) | +| [getGenerativeModel(vertexAI, modelParams, requestOptions)](./vertexai-preview.md#getgenerativemodel_e3037c9) | Returns a [GenerativeModel](./vertexai-preview.generativemodel.md#generativemodel_class) class with methods for inference and other functionality. | + +## Classes + +| Class | Description | +| --- | --- | +| [ChatSession](./vertexai-preview.chatsession.md#chatsession_class) | ChatSession class that enables sending chat messages and stores history of sent and received messages so far. | +| [GenerativeModel](./vertexai-preview.generativemodel.md#generativemodel_class) | Class for generative model APIs. | + +## Enumerations + +| Enumeration | Description | +| --- | --- | +| [BlockReason](./vertexai-preview.md#blockreason) | Reason that a prompt was blocked. | +| [FinishReason](./vertexai-preview.md#finishreason) | Reason that a candidate finished. | +| [FunctionCallingMode](./vertexai-preview.md#functioncallingmode) | | +| [FunctionDeclarationSchemaType](./vertexai-preview.md#functiondeclarationschematype) | Contains the list of OpenAPI data types as defined by https://swagger.io/docs/specification/data-models/data-types/ | +| [HarmBlockMethod](./vertexai-preview.md#harmblockmethod) | | +| [HarmBlockThreshold](./vertexai-preview.md#harmblockthreshold) | Threshold above which a prompt or candidate will be blocked. | +| [HarmCategory](./vertexai-preview.md#harmcategory) | Harm categories that would cause prompts or candidates to be blocked. | +| [HarmProbability](./vertexai-preview.md#harmprobability) | Probability that a prompt or candidate matches a harm category. | +| [HarmSeverity](./vertexai-preview.md#harmseverity) | Harm severity levels. | + +## Interfaces + +| Interface | Description | +| --- | --- | +| [BaseParams](./vertexai-preview.baseparams.md#baseparams_interface) | Base parameters for a number of methods. | +| [Citation](./vertexai-preview.citation.md#citation_interface) | A single citation. | +| [CitationMetadata](./vertexai-preview.citationmetadata.md#citationmetadata_interface) | Citation metadata that may be found on a [GenerateContentCandidate](./vertexai-preview.generatecontentcandidate.md#generatecontentcandidate_interface). | +| [Content](./vertexai-preview.content.md#content_interface) | Content type for both prompts and response candidates. | +| [CountTokensRequest](./vertexai-preview.counttokensrequest.md#counttokensrequest_interface) | Params for calling [GenerativeModel.countTokens()](./vertexai-preview.generativemodel.md#generativemodelcounttokens) | +| [CountTokensResponse](./vertexai-preview.counttokensresponse.md#counttokensresponse_interface) | Response from calling [GenerativeModel.countTokens()](./vertexai-preview.generativemodel.md#generativemodelcounttokens). | +| [Date\_2](./vertexai-preview.date_2.md#date_2_interface) | Protobuf google.type.Date | +| [EnhancedGenerateContentResponse](./vertexai-preview.enhancedgeneratecontentresponse.md#enhancedgeneratecontentresponse_interface) | Response object wrapped with helper methods. | +| [FileData](./vertexai-preview.filedata.md#filedata_interface) | Data pointing to a file uploaded on Google Cloud Storage. | +| [FileDataPart](./vertexai-preview.filedatapart.md#filedatapart_interface) | Content part interface if the part represents [FileData](./vertexai-preview.filedata.md#filedata_interface) | +| [FunctionCall](./vertexai-preview.functioncall.md#functioncall_interface) | A predicted [FunctionCall](./vertexai-preview.functioncall.md#functioncall_interface) returned from the model that contains a string representing the [FunctionDeclaration.name](./vertexai-preview.functiondeclaration.md#functiondeclarationname) and a structured JSON object containing the parameters and their values. | +| [FunctionCallingConfig](./vertexai-preview.functioncallingconfig.md#functioncallingconfig_interface) | | +| [FunctionCallPart](./vertexai-preview.functioncallpart.md#functioncallpart_interface) | Content part interface if the part represents a [FunctionCall](./vertexai-preview.functioncall.md#functioncall_interface). | +| [FunctionDeclaration](./vertexai-preview.functiondeclaration.md#functiondeclaration_interface) | Structured representation of a function declaration as defined by the [OpenAPI 3.0 specification](https://spec.openapis.org/oas/v3.0.3). Included in this declaration are the function name and parameters. This FunctionDeclaration is a representation of a block of code that can be used as a Tool by the model and executed by the client. | +| [FunctionDeclarationSchema](./vertexai-preview.functiondeclarationschema.md#functiondeclarationschema_interface) | Schema for parameters passed to [FunctionDeclaration.parameters](./vertexai-preview.functiondeclaration.md#functiondeclarationparameters). | +| [FunctionDeclarationSchemaProperty](./vertexai-preview.functiondeclarationschemaproperty.md#functiondeclarationschemaproperty_interface) | Schema is used to define the format of input/output data. Represents a select subset of an OpenAPI 3.0 schema object. More fields may be added in the future as needed. | +| [FunctionDeclarationsTool](./vertexai-preview.functiondeclarationstool.md#functiondeclarationstool_interface) | A FunctionDeclarationsTool is a piece of code that enables the system to interact with external systems to perform an action, or set of actions, outside of knowledge and scope of the model. | +| [FunctionResponse](./vertexai-preview.functionresponse.md#functionresponse_interface) | The result output from a [FunctionCall](./vertexai-preview.functioncall.md#functioncall_interface) that contains a string representing the [FunctionDeclaration.name](./vertexai-preview.functiondeclaration.md#functiondeclarationname) and a structured JSON object containing any output from the function is used as context to the model. This should contain the result of a [FunctionCall](./vertexai-preview.functioncall.md#functioncall_interface) made based on model prediction. | +| [FunctionResponsePart](./vertexai-preview.functionresponsepart.md#functionresponsepart_interface) | Content part interface if the part represents [FunctionResponse](./vertexai-preview.functionresponse.md#functionresponse_interface). | +| [GenerateContentCandidate](./vertexai-preview.generatecontentcandidate.md#generatecontentcandidate_interface) | A candidate returned as part of a [GenerateContentResponse](./vertexai-preview.generatecontentresponse.md#generatecontentresponse_interface). | +| [GenerateContentRequest](./vertexai-preview.generatecontentrequest.md#generatecontentrequest_interface) | Request sent through [GenerativeModel.generateContent()](./vertexai-preview.generativemodel.md#generativemodelgeneratecontent) | +| [GenerateContentResponse](./vertexai-preview.generatecontentresponse.md#generatecontentresponse_interface) | Individual response from [GenerativeModel.generateContent()](./vertexai-preview.generativemodel.md#generativemodelgeneratecontent) and [GenerativeModel.generateContentStream()](./vertexai-preview.generativemodel.md#generativemodelgeneratecontentstream). generateContentStream() will return one in each chunk until the stream is done. | +| [GenerateContentResult](./vertexai-preview.generatecontentresult.md#generatecontentresult_interface) | Result object returned from [GenerativeModel.generateContent()](./vertexai-preview.generativemodel.md#generativemodelgeneratecontent) call. | +| [GenerateContentStreamResult](./vertexai-preview.generatecontentstreamresult.md#generatecontentstreamresult_interface) | Result object returned from [GenerativeModel.generateContentStream()](./vertexai-preview.generativemodel.md#generativemodelgeneratecontentstream) call. Iterate over stream to get chunks as they come in and/or use the response promise to get the aggregated response when the stream is done. | +| [GenerationConfig](./vertexai-preview.generationconfig.md#generationconfig_interface) | Config options for content-related requests | +| [GenerativeContentBlob](./vertexai-preview.generativecontentblob.md#generativecontentblob_interface) | Interface for sending an image. | +| [GroundingAttribution](./vertexai-preview.groundingattribution.md#groundingattribution_interface) | | +| [GroundingMetadata](./vertexai-preview.groundingmetadata.md#groundingmetadata_interface) | Metadata returned to client when grounding is enabled. | +| [InlineDataPart](./vertexai-preview.inlinedatapart.md#inlinedatapart_interface) | Content part interface if the part represents an image. | +| [ModelParams](./vertexai-preview.modelparams.md#modelparams_interface) | Params passed to [getGenerativeModel()](./vertexai-preview.md#getgenerativemodel_e3037c9). | +| [PromptFeedback](./vertexai-preview.promptfeedback.md#promptfeedback_interface) | If the prompt was blocked, this will be populated with blockReason and the relevant safetyRatings. | +| [RequestOptions](./vertexai-preview.requestoptions.md#requestoptions_interface) | Params passed to [getGenerativeModel()](./vertexai-preview.md#getgenerativemodel_e3037c9). | +| [RetrievedContextAttribution](./vertexai-preview.retrievedcontextattribution.md#retrievedcontextattribution_interface) | | +| [SafetyRating](./vertexai-preview.safetyrating.md#safetyrating_interface) | A safety rating associated with a [GenerateContentCandidate](./vertexai-preview.generatecontentcandidate.md#generatecontentcandidate_interface) | +| [SafetySetting](./vertexai-preview.safetysetting.md#safetysetting_interface) | Safety setting that can be sent as part of request parameters. | +| [Segment](./vertexai-preview.segment.md#segment_interface) | | +| [StartChatParams](./vertexai-preview.startchatparams.md#startchatparams_interface) | Params for [GenerativeModel.startChat()](./vertexai-preview.generativemodel.md#generativemodelstartchat). | +| [TextPart](./vertexai-preview.textpart.md#textpart_interface) | Content part interface if the part represents a text string. | +| [ToolConfig](./vertexai-preview.toolconfig.md#toolconfig_interface) | Tool config. This config is shared for all tools provided in the request. | +| [UsageMetadata](./vertexai-preview.usagemetadata.md#usagemetadata_interface) | Usage metadata about a [GenerateContentResponse](./vertexai-preview.generatecontentresponse.md#generatecontentresponse_interface). | +| [VertexAI](./vertexai-preview.vertexai.md#vertexai_interface) | An instance of the Vertex AI for Firebase SDK. | +| [VertexAIOptions](./vertexai-preview.vertexaioptions.md#vertexaioptions_interface) | Options when initializing the Vertex AI for Firebase SDK. | +| [VideoMetadata](./vertexai-preview.videometadata.md#videometadata_interface) | Describes the input video content. | +| [WebAttribution](./vertexai-preview.webattribution.md#webattribution_interface) | | + +## Variables + +| Variable | Description | +| --- | --- | +| [POSSIBLE\_ROLES](./vertexai-preview.md#possible_roles) | Possible roles. | + +## Type Aliases + +| Type Alias | Description | +| --- | --- | +| [Part](./vertexai-preview.md#part) | Content part - includes text, image/video, or function call/response part types. | +| [Role](./vertexai-preview.md#role) | Role is the producer of the content. | +| [Tool](./vertexai-preview.md#tool) | Defines a tool that model can call to access external knowledge. | + +## function(app, ...) + +### getVertexAI(app, options) {:#getvertexai_04094cf} + +Returns a [VertexAI](./vertexai-preview.vertexai.md#vertexai_interface) instance for the given app. + +Signature: + +```typescript +export declare function getVertexAI(app?: FirebaseApp, options?: VertexAIOptions): VertexAI; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| app | [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) | The [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) to use. | +| options | [VertexAIOptions](./vertexai-preview.vertexaioptions.md#vertexaioptions_interface) | | + +Returns: + +[VertexAI](./vertexai-preview.vertexai.md#vertexai_interface) + +## function(vertexAI, ...) + +### getGenerativeModel(vertexAI, modelParams, requestOptions) {:#getgenerativemodel_e3037c9} + +Returns a [GenerativeModel](./vertexai-preview.generativemodel.md#generativemodel_class) class with methods for inference and other functionality. + +Signature: + +```typescript +export declare function getGenerativeModel(vertexAI: VertexAI, modelParams: ModelParams, requestOptions?: RequestOptions): GenerativeModel; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| vertexAI | [VertexAI](./vertexai-preview.vertexai.md#vertexai_interface) | | +| modelParams | [ModelParams](./vertexai-preview.modelparams.md#modelparams_interface) | | +| requestOptions | [RequestOptions](./vertexai-preview.requestoptions.md#requestoptions_interface) | | + +Returns: + +[GenerativeModel](./vertexai-preview.generativemodel.md#generativemodel_class) + +## POSSIBLE\_ROLES + +Possible roles. + +Signature: + +```typescript +POSSIBLE_ROLES: readonly ["user", "model", "function", "system"] +``` + +## Part + +Content part - includes text, image/video, or function call/response part types. + +Signature: + +```typescript +export declare type Part = TextPart | InlineDataPart | FunctionCallPart | FunctionResponsePart | FileDataPart; +``` + +## Role + +Role is the producer of the content. + +Signature: + +```typescript +export declare type Role = (typeof POSSIBLE_ROLES)[number]; +``` + +## Tool + +Defines a tool that model can call to access external knowledge. + +Signature: + +```typescript +export declare type Tool = FunctionDeclarationsTool; +``` + +## BlockReason + +Reason that a prompt was blocked. + +Signature: + +```typescript +export declare enum BlockReason +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| BLOCKED\_REASON\_UNSPECIFIED | "BLOCKED_REASON_UNSPECIFIED" | | +| OTHER | "OTHER" | | +| SAFETY | "SAFETY" | | + +## FinishReason + +Reason that a candidate finished. + +Signature: + +```typescript +export declare enum FinishReason +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| FINISH\_REASON\_UNSPECIFIED | "FINISH_REASON_UNSPECIFIED" | | +| MAX\_TOKENS | "MAX_TOKENS" | | +| OTHER | "OTHER" | | +| RECITATION | "RECITATION" | | +| SAFETY | "SAFETY" | | +| STOP | "STOP" | | + +## FunctionCallingMode + + +Signature: + +```typescript +export declare enum FunctionCallingMode +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| ANY | "ANY" | | +| AUTO | "AUTO" | | +| MODE\_UNSPECIFIED | "MODE_UNSPECIFIED" | | +| NONE | "NONE" | | + +## FunctionDeclarationSchemaType + +Contains the list of OpenAPI data types as defined by https://swagger.io/docs/specification/data-models/data-types/ + +Signature: + +```typescript +export declare enum FunctionDeclarationSchemaType +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| ARRAY | "ARRAY" | Array type. | +| BOOLEAN | "BOOLEAN" | Boolean type. | +| INTEGER | "INTEGER" | Integer type. | +| NUMBER | "NUMBER" | Number type. | +| OBJECT | "OBJECT" | Object type. | +| STRING | "STRING" | String type. | + +## HarmBlockMethod + + +Signature: + +```typescript +export declare enum HarmBlockMethod +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| HARM\_BLOCK\_METHOD\_UNSPECIFIED | "HARM_BLOCK_METHOD_UNSPECIFIED" | | +| PROBABILITY | "PROBABILITY" | | +| SEVERITY | "SEVERITY" | | + +## HarmBlockThreshold + +Threshold above which a prompt or candidate will be blocked. + +Signature: + +```typescript +export declare enum HarmBlockThreshold +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| BLOCK\_LOW\_AND\_ABOVE | "BLOCK_LOW_AND_ABOVE" | | +| BLOCK\_MEDIUM\_AND\_ABOVE | "BLOCK_MEDIUM_AND_ABOVE" | | +| BLOCK\_NONE | "BLOCK_NONE" | | +| BLOCK\_ONLY\_HIGH | "BLOCK_ONLY_HIGH" | | +| HARM\_BLOCK\_THRESHOLD\_UNSPECIFIED | "HARM_BLOCK_THRESHOLD_UNSPECIFIED" | | + +## HarmCategory + +Harm categories that would cause prompts or candidates to be blocked. + +Signature: + +```typescript +export declare enum HarmCategory +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| HARM\_CATEGORY\_DANGEROUS\_CONTENT | "HARM_CATEGORY_DANGEROUS_CONTENT" | | +| HARM\_CATEGORY\_HARASSMENT | "HARM_CATEGORY_HARASSMENT" | | +| HARM\_CATEGORY\_HATE\_SPEECH | "HARM_CATEGORY_HATE_SPEECH" | | +| HARM\_CATEGORY\_SEXUALLY\_EXPLICIT | "HARM_CATEGORY_SEXUALLY_EXPLICIT" | | +| HARM\_CATEGORY\_UNSPECIFIED | "HARM_CATEGORY_UNSPECIFIED" | | + +## HarmProbability + +Probability that a prompt or candidate matches a harm category. + +Signature: + +```typescript +export declare enum HarmProbability +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| HARM\_PROBABILITY\_UNSPECIFIED | "HARM_PROBABILITY_UNSPECIFIED" | | +| HIGH | "HIGH" | | +| LOW | "LOW" | | +| MEDIUM | "MEDIUM" | | +| NEGLIGIBLE | "NEGLIGIBLE" | | + +## HarmSeverity + +Harm severity levels. + +Signature: + +```typescript +export declare enum HarmSeverity +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| HARM\_SEVERITY\_HIGH | "HARM_SEVERITY_HIGH" | | +| HARM\_SEVERITY\_LOW | "HARM_SEVERITY_LOW" | | +| HARM\_SEVERITY\_MEDIUM | "HARM_SEVERITY_MEDIUM" | | +| HARM\_SEVERITY\_NEGLIGIBLE | "HARM_SEVERITY_NEGLIGIBLE" | | +| HARM\_SEVERITY\_UNSPECIFIED | "HARM_SEVERITY_UNSPECIFIED" | | + diff --git a/docs-devsite/vertexai-preview.modelparams.md b/docs-devsite/vertexai-preview.modelparams.md new file mode 100644 index 00000000000..34d68f86714 --- /dev/null +++ b/docs-devsite/vertexai-preview.modelparams.md @@ -0,0 +1,61 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# ModelParams interface +Params passed to [getGenerativeModel()](./vertexai-preview.md#getgenerativemodel_e3037c9). + +Signature: + +```typescript +export interface ModelParams extends BaseParams +``` +Extends: [BaseParams](./vertexai-preview.baseparams.md#baseparams_interface) + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [model](./vertexai-preview.modelparams.md#modelparamsmodel) | string | | +| [systemInstruction](./vertexai-preview.modelparams.md#modelparamssysteminstruction) | string \| [Part](./vertexai-preview.md#part) \| [Content](./vertexai-preview.content.md#content_interface) | | +| [toolConfig](./vertexai-preview.modelparams.md#modelparamstoolconfig) | [ToolConfig](./vertexai-preview.toolconfig.md#toolconfig_interface) | | +| [tools](./vertexai-preview.modelparams.md#modelparamstools) | [Tool](./vertexai-preview.md#tool)\[\] | | + +## ModelParams.model + +Signature: + +```typescript +model: string; +``` + +## ModelParams.systemInstruction + +Signature: + +```typescript +systemInstruction?: string | Part | Content; +``` + +## ModelParams.toolConfig + +Signature: + +```typescript +toolConfig?: ToolConfig; +``` + +## ModelParams.tools + +Signature: + +```typescript +tools?: Tool[]; +``` diff --git a/docs-devsite/vertexai-preview.promptfeedback.md b/docs-devsite/vertexai-preview.promptfeedback.md new file mode 100644 index 00000000000..cb27f10c8c3 --- /dev/null +++ b/docs-devsite/vertexai-preview.promptfeedback.md @@ -0,0 +1,51 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# PromptFeedback interface +If the prompt was blocked, this will be populated with `blockReason` and the relevant `safetyRatings`. + +Signature: + +```typescript +export interface PromptFeedback +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [blockReason](./vertexai-preview.promptfeedback.md#promptfeedbackblockreason) | [BlockReason](./vertexai-preview.md#blockreason) | | +| [blockReasonMessage](./vertexai-preview.promptfeedback.md#promptfeedbackblockreasonmessage) | string | | +| [safetyRatings](./vertexai-preview.promptfeedback.md#promptfeedbacksafetyratings) | [SafetyRating](./vertexai-preview.safetyrating.md#safetyrating_interface)\[\] | | + +## PromptFeedback.blockReason + +Signature: + +```typescript +blockReason: BlockReason; +``` + +## PromptFeedback.blockReasonMessage + +Signature: + +```typescript +blockReasonMessage?: string; +``` + +## PromptFeedback.safetyRatings + +Signature: + +```typescript +safetyRatings: SafetyRating[]; +``` diff --git a/docs-devsite/vertexai-preview.requestoptions.md b/docs-devsite/vertexai-preview.requestoptions.md new file mode 100644 index 00000000000..550ec44ce96 --- /dev/null +++ b/docs-devsite/vertexai-preview.requestoptions.md @@ -0,0 +1,46 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# RequestOptions interface +Params passed to [getGenerativeModel()](./vertexai-preview.md#getgenerativemodel_e3037c9). + +Signature: + +```typescript +export interface RequestOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [baseUrl](./vertexai-preview.requestoptions.md#requestoptionsbaseurl) | string | Base url for endpoint. Defaults to https://firebaseml.googleapis.com | +| [timeout](./vertexai-preview.requestoptions.md#requestoptionstimeout) | number | Request timeout in milliseconds. | + +## RequestOptions.baseUrl + +Base url for endpoint. Defaults to https://firebaseml.googleapis.com + +Signature: + +```typescript +baseUrl?: string; +``` + +## RequestOptions.timeout + +Request timeout in milliseconds. + +Signature: + +```typescript +timeout?: number; +``` diff --git a/docs-devsite/vertexai-preview.retrievedcontextattribution.md b/docs-devsite/vertexai-preview.retrievedcontextattribution.md new file mode 100644 index 00000000000..0a121cdc004 --- /dev/null +++ b/docs-devsite/vertexai-preview.retrievedcontextattribution.md @@ -0,0 +1,41 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# RetrievedContextAttribution interface + +Signature: + +```typescript +export interface RetrievedContextAttribution +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [title](./vertexai-preview.retrievedcontextattribution.md#retrievedcontextattributiontitle) | string | | +| [uri](./vertexai-preview.retrievedcontextattribution.md#retrievedcontextattributionuri) | string | | + +## RetrievedContextAttribution.title + +Signature: + +```typescript +title: string; +``` + +## RetrievedContextAttribution.uri + +Signature: + +```typescript +uri: string; +``` diff --git a/docs-devsite/vertexai-preview.safetyrating.md b/docs-devsite/vertexai-preview.safetyrating.md new file mode 100644 index 00000000000..65b1bc8fb42 --- /dev/null +++ b/docs-devsite/vertexai-preview.safetyrating.md @@ -0,0 +1,78 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# SafetyRating interface +A safety rating associated with a [GenerateContentCandidate](./vertexai-preview.generatecontentcandidate.md#generatecontentcandidate_interface) + +Signature: + +```typescript +export interface SafetyRating +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [blocked](./vertexai-preview.safetyrating.md#safetyratingblocked) | boolean | | +| [category](./vertexai-preview.safetyrating.md#safetyratingcategory) | [HarmCategory](./vertexai-preview.md#harmcategory) | | +| [probability](./vertexai-preview.safetyrating.md#safetyratingprobability) | [HarmProbability](./vertexai-preview.md#harmprobability) | | +| [probabilityScore](./vertexai-preview.safetyrating.md#safetyratingprobabilityscore) | number | | +| [severity](./vertexai-preview.safetyrating.md#safetyratingseverity) | [HarmSeverity](./vertexai-preview.md#harmseverity) | | +| [severityScore](./vertexai-preview.safetyrating.md#safetyratingseverityscore) | number | | + +## SafetyRating.blocked + +Signature: + +```typescript +blocked: boolean; +``` + +## SafetyRating.category + +Signature: + +```typescript +category: HarmCategory; +``` + +## SafetyRating.probability + +Signature: + +```typescript +probability: HarmProbability; +``` + +## SafetyRating.probabilityScore + +Signature: + +```typescript +probabilityScore: number; +``` + +## SafetyRating.severity + +Signature: + +```typescript +severity: HarmSeverity; +``` + +## SafetyRating.severityScore + +Signature: + +```typescript +severityScore: number; +``` diff --git a/docs-devsite/vertexai-preview.safetysetting.md b/docs-devsite/vertexai-preview.safetysetting.md new file mode 100644 index 00000000000..78678315805 --- /dev/null +++ b/docs-devsite/vertexai-preview.safetysetting.md @@ -0,0 +1,51 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# SafetySetting interface +Safety setting that can be sent as part of request parameters. + +Signature: + +```typescript +export interface SafetySetting +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [category](./vertexai-preview.safetysetting.md#safetysettingcategory) | [HarmCategory](./vertexai-preview.md#harmcategory) | | +| [method](./vertexai-preview.safetysetting.md#safetysettingmethod) | [HarmBlockMethod](./vertexai-preview.md#harmblockmethod) | | +| [threshold](./vertexai-preview.safetysetting.md#safetysettingthreshold) | [HarmBlockThreshold](./vertexai-preview.md#harmblockthreshold) | | + +## SafetySetting.category + +Signature: + +```typescript +category: HarmCategory; +``` + +## SafetySetting.method + +Signature: + +```typescript +method: HarmBlockMethod; +``` + +## SafetySetting.threshold + +Signature: + +```typescript +threshold: HarmBlockThreshold; +``` diff --git a/docs-devsite/vertexai-preview.segment.md b/docs-devsite/vertexai-preview.segment.md new file mode 100644 index 00000000000..c64bc3ffcda --- /dev/null +++ b/docs-devsite/vertexai-preview.segment.md @@ -0,0 +1,50 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# Segment interface + +Signature: + +```typescript +export interface Segment +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [endIndex](./vertexai-preview.segment.md#segmentendindex) | number | | +| [partIndex](./vertexai-preview.segment.md#segmentpartindex) | number | | +| [startIndex](./vertexai-preview.segment.md#segmentstartindex) | number | | + +## Segment.endIndex + +Signature: + +```typescript +endIndex: number; +``` + +## Segment.partIndex + +Signature: + +```typescript +partIndex: number; +``` + +## Segment.startIndex + +Signature: + +```typescript +startIndex: number; +``` diff --git a/docs-devsite/vertexai-preview.startchatparams.md b/docs-devsite/vertexai-preview.startchatparams.md new file mode 100644 index 00000000000..f422f7a1ff0 --- /dev/null +++ b/docs-devsite/vertexai-preview.startchatparams.md @@ -0,0 +1,61 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# StartChatParams interface +Params for [GenerativeModel.startChat()](./vertexai-preview.generativemodel.md#generativemodelstartchat). + +Signature: + +```typescript +export interface StartChatParams extends BaseParams +``` +Extends: [BaseParams](./vertexai-preview.baseparams.md#baseparams_interface) + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [history](./vertexai-preview.startchatparams.md#startchatparamshistory) | [Content](./vertexai-preview.content.md#content_interface)\[\] | | +| [systemInstruction](./vertexai-preview.startchatparams.md#startchatparamssysteminstruction) | string \| [Part](./vertexai-preview.md#part) \| [Content](./vertexai-preview.content.md#content_interface) | | +| [toolConfig](./vertexai-preview.startchatparams.md#startchatparamstoolconfig) | [ToolConfig](./vertexai-preview.toolconfig.md#toolconfig_interface) | | +| [tools](./vertexai-preview.startchatparams.md#startchatparamstools) | [Tool](./vertexai-preview.md#tool)\[\] | | + +## StartChatParams.history + +Signature: + +```typescript +history?: Content[]; +``` + +## StartChatParams.systemInstruction + +Signature: + +```typescript +systemInstruction?: string | Part | Content; +``` + +## StartChatParams.toolConfig + +Signature: + +```typescript +toolConfig?: ToolConfig; +``` + +## StartChatParams.tools + +Signature: + +```typescript +tools?: Tool[]; +``` diff --git a/docs-devsite/vertexai-preview.textpart.md b/docs-devsite/vertexai-preview.textpart.md new file mode 100644 index 00000000000..206168180b2 --- /dev/null +++ b/docs-devsite/vertexai-preview.textpart.md @@ -0,0 +1,60 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# TextPart interface +Content part interface if the part represents a text string. + +Signature: + +```typescript +export interface TextPart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [functionCall](./vertexai-preview.textpart.md#textpartfunctioncall) | never | | +| [functionResponse](./vertexai-preview.textpart.md#textpartfunctionresponse) | never | | +| [inlineData](./vertexai-preview.textpart.md#textpartinlinedata) | never | | +| [text](./vertexai-preview.textpart.md#textparttext) | string | | + +## TextPart.functionCall + +Signature: + +```typescript +functionCall?: never; +``` + +## TextPart.functionResponse + +Signature: + +```typescript +functionResponse?: never; +``` + +## TextPart.inlineData + +Signature: + +```typescript +inlineData?: never; +``` + +## TextPart.text + +Signature: + +```typescript +text: string; +``` diff --git a/docs-devsite/vertexai-preview.toolconfig.md b/docs-devsite/vertexai-preview.toolconfig.md new file mode 100644 index 00000000000..4278eef509b --- /dev/null +++ b/docs-devsite/vertexai-preview.toolconfig.md @@ -0,0 +1,33 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# ToolConfig interface +Tool config. This config is shared for all tools provided in the request. + +Signature: + +```typescript +export interface ToolConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [functionCallingConfig](./vertexai-preview.toolconfig.md#toolconfigfunctioncallingconfig) | [FunctionCallingConfig](./vertexai-preview.functioncallingconfig.md#functioncallingconfig_interface) | | + +## ToolConfig.functionCallingConfig + +Signature: + +```typescript +functionCallingConfig: FunctionCallingConfig; +``` diff --git a/docs-devsite/vertexai-preview.usagemetadata.md b/docs-devsite/vertexai-preview.usagemetadata.md new file mode 100644 index 00000000000..2829c9dbd5d --- /dev/null +++ b/docs-devsite/vertexai-preview.usagemetadata.md @@ -0,0 +1,51 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# UsageMetadata interface +Usage metadata about a [GenerateContentResponse](./vertexai-preview.generatecontentresponse.md#generatecontentresponse_interface). + +Signature: + +```typescript +export interface UsageMetadata +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [candidatesTokenCount](./vertexai-preview.usagemetadata.md#usagemetadatacandidatestokencount) | number | | +| [promptTokenCount](./vertexai-preview.usagemetadata.md#usagemetadataprompttokencount) | number | | +| [totalTokenCount](./vertexai-preview.usagemetadata.md#usagemetadatatotaltokencount) | number | | + +## UsageMetadata.candidatesTokenCount + +Signature: + +```typescript +candidatesTokenCount: number; +``` + +## UsageMetadata.promptTokenCount + +Signature: + +```typescript +promptTokenCount: number; +``` + +## UsageMetadata.totalTokenCount + +Signature: + +```typescript +totalTokenCount: number; +``` diff --git a/docs-devsite/vertexai-preview.vertexai.md b/docs-devsite/vertexai-preview.vertexai.md new file mode 100644 index 00000000000..35991f2be12 --- /dev/null +++ b/docs-devsite/vertexai-preview.vertexai.md @@ -0,0 +1,44 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# VertexAI interface +An instance of the Vertex AI for Firebase SDK. + +Signature: + +```typescript +export interface VertexAI +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [app](./vertexai-preview.vertexai.md#vertexaiapp) | [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) | The [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) this [VertexAI](./vertexai-preview.vertexai.md#vertexai_interface) instance is associated with. | +| [location](./vertexai-preview.vertexai.md#vertexailocation) | string | | + +## VertexAI.app + +The [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface) this [VertexAI](./vertexai-preview.vertexai.md#vertexai_interface) instance is associated with. + +Signature: + +```typescript +app: FirebaseApp; +``` + +## VertexAI.location + +Signature: + +```typescript +location: string; +``` diff --git a/docs-devsite/vertexai-preview.vertexaioptions.md b/docs-devsite/vertexai-preview.vertexaioptions.md new file mode 100644 index 00000000000..320132c22f9 --- /dev/null +++ b/docs-devsite/vertexai-preview.vertexaioptions.md @@ -0,0 +1,33 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# VertexAIOptions interface +Options when initializing the Vertex AI for Firebase SDK. + +Signature: + +```typescript +export interface VertexAIOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [location](./vertexai-preview.vertexaioptions.md#vertexaioptionslocation) | string | | + +## VertexAIOptions.location + +Signature: + +```typescript +location?: string; +``` diff --git a/docs-devsite/vertexai-preview.videometadata.md b/docs-devsite/vertexai-preview.videometadata.md new file mode 100644 index 00000000000..04d8883bae9 --- /dev/null +++ b/docs-devsite/vertexai-preview.videometadata.md @@ -0,0 +1,46 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# VideoMetadata interface +Describes the input video content. + +Signature: + +```typescript +export interface VideoMetadata +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [endOffset](./vertexai-preview.videometadata.md#videometadataendoffset) | string | The end offset of the video in protobuf [Duration](https://cloud.google.com/ruby/docs/reference/google-cloud-workflows-v1/latest/Google-Protobuf-Duration#json-mapping) format. | +| [startOffset](./vertexai-preview.videometadata.md#videometadatastartoffset) | string | The start offset of the video in protobuf [Duration](https://cloud.google.com/ruby/docs/reference/google-cloud-workflows-v1/latest/Google-Protobuf-Duration#json-mapping) format. | + +## VideoMetadata.endOffset + +The end offset of the video in protobuf [Duration](https://cloud.google.com/ruby/docs/reference/google-cloud-workflows-v1/latest/Google-Protobuf-Duration#json-mapping) format. + +Signature: + +```typescript +endOffset: string; +``` + +## VideoMetadata.startOffset + +The start offset of the video in protobuf [Duration](https://cloud.google.com/ruby/docs/reference/google-cloud-workflows-v1/latest/Google-Protobuf-Duration#json-mapping) format. + +Signature: + +```typescript +startOffset: string; +``` diff --git a/docs-devsite/vertexai-preview.webattribution.md b/docs-devsite/vertexai-preview.webattribution.md new file mode 100644 index 00000000000..5db6f94b82e --- /dev/null +++ b/docs-devsite/vertexai-preview.webattribution.md @@ -0,0 +1,41 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# WebAttribution interface + +Signature: + +```typescript +export interface WebAttribution +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [title](./vertexai-preview.webattribution.md#webattributiontitle) | string | | +| [uri](./vertexai-preview.webattribution.md#webattributionuri) | string | | + +## WebAttribution.title + +Signature: + +```typescript +title: string; +``` + +## WebAttribution.uri + +Signature: + +```typescript +uri: string; +``` diff --git a/e2e/package.json b/e2e/package.json index eac3b6c6faf..c4dee3448ce 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -21,12 +21,12 @@ "firebase": "9.23.0" }, "devDependencies": { - "@babel/core": "7.22.11", + "@babel/core": "7.24.3", "@babel/preset-env": "7.22.10", - "@types/chai": "4.3.5", + "@types/chai": "4.3.14", "@types/mocha": "9.1.1", "babel-loader": "8.3.0", - "chai": "4.3.7", + "chai": "4.4.1", "karma": "6.4.2", "karma-chrome-launcher": "3.2.0", "karma-mocha": "2.0.1", diff --git a/e2e/yarn.lock b/e2e/yarn.lock index 92b3439c7fa..c457b3cff79 100644 --- a/e2e/yarn.lock +++ b/e2e/yarn.lock @@ -2,13 +2,13 @@ # yarn lockfile v1 -"@ampproject/remapping@^2.1.0": - version "2.2.0" - resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" - integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== +"@ampproject/remapping@^2.2.0": + version "2.3.0" + resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== dependencies: - "@jridgewell/gen-mapping" "^0.1.0" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" "@babel/code-frame@^7.14.5": version "7.14.5" @@ -17,55 +17,52 @@ dependencies: "@babel/highlight" "^7.14.5" -"@babel/code-frame@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== +"@babel/code-frame@^7.23.5": + version "7.23.5" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== dependencies: - "@babel/highlight" "^7.16.7" + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" -"@babel/code-frame@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== +"@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2": + version "7.24.2" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" + integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== dependencies: - "@babel/highlight" "^7.18.6" + "@babel/highlight" "^7.24.2" + picocolors "^1.0.0" "@babel/compat-data@^7.13.11", "@babel/compat-data@^7.14.5", "@babel/compat-data@^7.14.7": version "7.14.7" resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz#7b047d7a3a89a67d2258dc61f604f098f1bc7e08" integrity sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw== -"@babel/compat-data@^7.17.10": - version "7.17.10" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz#711dc726a492dfc8be8220028b1b92482362baab" - integrity sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw== - -"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.19.4", "@babel/compat-data@^7.20.5": - version "7.20.14" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.14.tgz#4106fc8b755f3e3ee0a0a7c27dde5de1d2b2baf8" - integrity sha512-0YpKHD6ImkWMEINCyDAD0HLLUH/lPCefG8ld9it8DJB2wnApraKuhgYTvTY1z7UFIfBTGy5LwncZ+5HWWGbhFw== - -"@babel/core@7.17.10": - version "7.17.10" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.17.10.tgz#74ef0fbf56b7dfc3f198fc2d927f4f03e12f4b05" - integrity sha512-liKoppandF3ZcBnIYFjfSDHZLKdLHGJRkoWtG8zQyGJBQfIYobpnVGI5+pLBNtS6psFLDzyq8+h5HiVljW9PNA== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.10" - "@babel/helper-compilation-targets" "^7.17.10" - "@babel/helper-module-transforms" "^7.17.7" - "@babel/helpers" "^7.17.9" - "@babel/parser" "^7.17.10" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.10" - "@babel/types" "^7.17.10" - convert-source-map "^1.7.0" +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9", "@babel/compat-data@^7.23.5": + version "7.23.5" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" + integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== + +"@babel/core@7.24.3": + version "7.24.3" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz#568864247ea10fbd4eff04dda1e05f9e2ea985c3" + integrity sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.24.2" + "@babel/generator" "^7.24.1" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.24.1" + "@babel/parser" "^7.24.1" + "@babel/template" "^7.24.0" + "@babel/traverse" "^7.24.1" + "@babel/types" "^7.24.0" + convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.2.1" - semver "^6.3.0" + json5 "^2.2.3" + semver "^6.3.1" "@babel/core@^7.11.1", "@babel/core@^7.7.5": version "7.14.6" @@ -97,22 +94,14 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/generator@^7.17.10": - version "7.17.10" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.17.10.tgz#c281fa35b0c349bbe9d02916f4ae08fc85ed7189" - integrity sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg== +"@babel/generator@^7.24.1": + version "7.24.1" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz#e67e06f68568a4ebf194d1c6014235344f0476d0" + integrity sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A== dependencies: - "@babel/types" "^7.17.10" - "@jridgewell/gen-mapping" "^0.1.0" - jsesc "^2.5.1" - -"@babel/generator@^7.20.7": - version "7.20.14" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.20.14.tgz#9fa772c9f86a46c6ac9b321039400712b96f64ce" - integrity sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg== - dependencies: - "@babel/types" "^7.20.7" - "@jridgewell/gen-mapping" "^0.3.2" + "@babel/types" "^7.24.0" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" "@babel/helper-annotate-as-pure@^7.14.5": @@ -129,6 +118,13 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-annotate-as-pure@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" + integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz#b939b43f8c37765443a19ae74ad8b15978e0a191" @@ -137,13 +133,12 @@ "@babel/helper-explode-assignable-expression" "^7.14.5" "@babel/types" "^7.14.5" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" - integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.22.15": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz#5426b109cf3ad47b91120f8328d8ab1be8b0b956" + integrity sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw== dependencies: - "@babel/helper-explode-assignable-expression" "^7.18.6" - "@babel/types" "^7.18.9" + "@babel/types" "^7.22.15" "@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.14.5": version "7.14.5" @@ -155,26 +150,16 @@ browserslist "^4.16.6" semver "^6.3.0" -"@babel/helper-compilation-targets@^7.17.10": - version "7.17.10" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.10.tgz#09c63106d47af93cf31803db6bc49fef354e2ebe" - integrity sha512-gh3RxjWbauw/dFiU/7whjd0qN9K6nPJMqe6+Er7rOavFh0CQUSwhAE3IcTho2rywPJFxej6TUUHDkWcYI6gGqQ== +"@babel/helper-compilation-targets@^7.22.10", "@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6": + version "7.23.6" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" + integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== dependencies: - "@babel/compat-data" "^7.17.10" - "@babel/helper-validator-option" "^7.16.7" - browserslist "^4.20.2" - semver "^6.3.0" - -"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.19.3", "@babel/helper-compilation-targets@^7.20.7": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz#a6cd33e93629f5eb473b021aac05df62c4cd09bb" - integrity sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ== - dependencies: - "@babel/compat-data" "^7.20.5" - "@babel/helper-validator-option" "^7.18.6" - browserslist "^4.21.3" + "@babel/compat-data" "^7.23.5" + "@babel/helper-validator-option" "^7.23.5" + browserslist "^4.22.2" lru-cache "^5.1.1" - semver "^6.3.0" + semver "^6.3.1" "@babel/helper-create-class-features-plugin@^7.14.5": version "7.14.6" @@ -188,19 +173,20 @@ "@babel/helper-replace-supers" "^7.14.5" "@babel/helper-split-export-declaration" "^7.14.5" -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.5", "@babel/helper-create-class-features-plugin@^7.20.7": - version "7.20.12" - resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.12.tgz#4349b928e79be05ed2d1643b20b99bb87c503819" - integrity sha512-9OunRkbT0JQcednL0UFvbfXpAsUXiGjUk0a7sN8fUXX7Mue79cUSMjHGDRRi/Vz9vYlpIhLV5fMD5dKoMhhsNQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-member-expression-to-functions" "^7.20.7" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-replace-supers" "^7.20.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" - "@babel/helper-split-export-declaration" "^7.18.6" +"@babel/helper-create-class-features-plugin@^7.22.15": + version "7.24.0" + resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.0.tgz#fc7554141bdbfa2d17f7b4b80153b9b090e5d158" + integrity sha512-QAH+vfvts51BCsNZ2PhY6HAggnlS6omLLFTsIpeqZk/MmJ6cW7tgz5yRv0fMJThcr6FmbMrENh1RgrWPTYA76g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-member-expression-to-functions" "^7.23.0" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.20" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + semver "^6.3.1" "@babel/helper-create-regexp-features-plugin@^7.14.5": version "7.14.5" @@ -210,7 +196,7 @@ "@babel/helper-annotate-as-pure" "^7.14.5" regexpu-core "^4.7.1" -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.20.5": +"@babel/helper-create-regexp-features-plugin@^7.18.6": version "7.20.5" resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.20.5.tgz#5ea79b59962a09ec2acf20a963a01ab4d076ccca" integrity sha512-m68B1lkg3XDGX5yCvGO0kPx3v9WIYLnzjKfPcQiwntEQa5ZeRkPmo2X/ISJc8qxWGfwUr+kvZAeEzAwLec2r2w== @@ -218,6 +204,15 @@ "@babel/helper-annotate-as-pure" "^7.18.6" regexpu-core "^5.2.1" +"@babel/helper-create-regexp-features-plugin@^7.22.15", "@babel/helper-create-regexp-features-plugin@^7.22.5": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz#5ee90093914ea09639b01c711db0d6775e558be1" + integrity sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + regexpu-core "^5.3.1" + semver "^6.3.1" + "@babel/helper-define-polyfill-provider@^0.2.2": version "0.2.3" resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz#0525edec5094653a282688d34d846e4c75e9c0b6" @@ -232,29 +227,43 @@ resolve "^1.14.2" semver "^6.1.2" -"@babel/helper-define-polyfill-provider@^0.3.3": - version "0.3.3" - resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" - integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== +"@babel/helper-define-polyfill-provider@^0.4.4": + version "0.4.4" + resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz#64df615451cb30e94b59a9696022cffac9a10088" + integrity sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA== dependencies: - "@babel/helper-compilation-targets" "^7.17.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" debug "^4.1.1" lodash.debounce "^4.0.8" resolve "^1.14.2" - semver "^6.1.2" -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== +"@babel/helper-define-polyfill-provider@^0.5.0": + version "0.5.0" + resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz#465805b7361f461e86c680f1de21eaf88c25901b" + integrity sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q== dependencies: - "@babel/types" "^7.16.7" + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" -"@babel/helper-environment-visitor@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" - integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== +"@babel/helper-define-polyfill-provider@^0.6.1": + version "0.6.1" + resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz#fadc63f0c2ff3c8d02ed905dcea747c5b0fb74fd" + integrity sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA== + dependencies: + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== "@babel/helper-explode-assignable-expression@^7.14.5": version "7.14.5" @@ -263,13 +272,6 @@ dependencies: "@babel/types" "^7.14.5" -"@babel/helper-explode-assignable-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" - integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== - dependencies: - "@babel/types" "^7.18.6" - "@babel/helper-function-name@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz#89e2c474972f15d8e233b52ee8c480e2cfcd50c4" @@ -279,21 +281,13 @@ "@babel/template" "^7.14.5" "@babel/types" "^7.14.5" -"@babel/helper-function-name@^7.17.9": - version "7.17.9" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz#136fcd54bc1da82fcb47565cf16fd8e444b1ff12" - integrity sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg== - dependencies: - "@babel/template" "^7.16.7" - "@babel/types" "^7.17.0" - -"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": - version "7.19.0" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" - integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== +"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== dependencies: - "@babel/template" "^7.18.10" - "@babel/types" "^7.19.0" + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" "@babel/helper-get-function-arity@^7.14.5": version "7.14.5" @@ -309,19 +303,12 @@ dependencies: "@babel/types" "^7.14.5" -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== - dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.22.5" "@babel/helper-member-expression-to-functions@^7.14.5": version "7.14.7" @@ -330,12 +317,12 @@ dependencies: "@babel/types" "^7.14.5" -"@babel/helper-member-expression-to-functions@^7.20.7": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.20.7.tgz#a6f26e919582275a93c3aa6594756d71b0bb7f05" - integrity sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw== +"@babel/helper-member-expression-to-functions@^7.22.15", "@babel/helper-member-expression-to-functions@^7.23.0": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" + integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== dependencies: - "@babel/types" "^7.20.7" + "@babel/types" "^7.23.0" "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.14.5": version "7.14.5" @@ -344,19 +331,12 @@ dependencies: "@babel/types" "^7.14.5" -"@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-module-imports@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== +"@babel/helper-module-imports@^7.22.15": + version "7.22.15" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.22.15" "@babel/helper-module-transforms@^7.14.5": version "7.14.5" @@ -372,33 +352,16 @@ "@babel/traverse" "^7.14.5" "@babel/types" "^7.14.5" -"@babel/helper-module-transforms@^7.17.7": - version "7.17.7" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz#3943c7f777139e7954a5355c815263741a9c1cbd" - integrity sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw== - dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-simple-access" "^7.17.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" - -"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11": - version "7.20.11" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz#df4c7af713c557938c50ea3ad0117a7944b2f1b0" - integrity sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-simple-access" "^7.20.2" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.19.1" - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.10" - "@babel/types" "^7.20.7" +"@babel/helper-module-transforms@^7.23.3": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" + integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== + 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" "@babel/helper-optimise-call-expression@^7.14.5": version "7.14.5" @@ -407,28 +370,28 @@ dependencies: "@babel/types" "^7.14.5" -"@babel/helper-optimise-call-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" - integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== +"@babel/helper-optimise-call-expression@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" + integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.22.5" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.14.5" resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== -"@babel/helper-plugin-utils@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" - integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== - -"@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2": +"@babel/helper-plugin-utils@^7.18.6": version "7.20.2" resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== +"@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.0": + version "7.24.0" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a" + integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w== + "@babel/helper-remap-async-to-generator@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz#51439c913612958f54a987a4ffc9ee587a2045d6" @@ -438,15 +401,14 @@ "@babel/helper-wrap-function" "^7.14.5" "@babel/types" "^7.14.5" -"@babel/helper-remap-async-to-generator@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" - integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== +"@babel/helper-remap-async-to-generator@^7.22.20": + version "7.22.20" + resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0" + integrity sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw== dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-wrap-function" "^7.18.9" - "@babel/types" "^7.18.9" + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-wrap-function" "^7.22.20" "@babel/helper-replace-supers@^7.14.5": version "7.14.5" @@ -458,17 +420,14 @@ "@babel/traverse" "^7.14.5" "@babel/types" "^7.14.5" -"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.20.7": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz#243ecd2724d2071532b2c8ad2f0f9f083bcae331" - integrity sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A== +"@babel/helper-replace-supers@^7.22.20": + version "7.22.20" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793" + integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw== dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-member-expression-to-functions" "^7.20.7" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.7" - "@babel/types" "^7.20.7" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" "@babel/helper-simple-access@^7.14.5": version "7.14.5" @@ -477,19 +436,12 @@ dependencies: "@babel/types" "^7.14.5" -"@babel/helper-simple-access@^7.17.7": - version "7.17.7" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz#aaa473de92b7987c6dfa7ce9a7d9674724823367" - integrity sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA== - dependencies: - "@babel/types" "^7.17.0" - -"@babel/helper-simple-access@^7.20.2": - version "7.20.2" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" - integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== dependencies: - "@babel/types" "^7.20.2" + "@babel/types" "^7.22.5" "@babel/helper-skip-transparent-expression-wrappers@^7.14.5": version "7.14.5" @@ -498,12 +450,12 @@ dependencies: "@babel/types" "^7.14.5" -"@babel/helper-skip-transparent-expression-wrappers@^7.20.0": - version "7.20.0" - resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" - integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg== +"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" + integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== dependencies: - "@babel/types" "^7.20.0" + "@babel/types" "^7.22.5" "@babel/helper-split-export-declaration@^7.14.5": version "7.14.5" @@ -512,54 +464,47 @@ dependencies: "@babel/types" "^7.14.5" -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-split-export-declaration@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" - integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.22.5" "@babel/helper-string-parser@^7.19.4": version "7.19.4" resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== + "@babel/helper-validator-identifier@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8" integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg== -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - -"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": +"@babel/helper-validator-identifier@^7.19.1": version "7.19.1" resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + "@babel/helper-validator-option@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== -"@babel/helper-validator-option@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" - integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== - -"@babel/helper-validator-option@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" - integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== +"@babel/helper-validator-option@^7.22.5", "@babel/helper-validator-option@^7.23.5": + version "7.23.5" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" + integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== "@babel/helper-wrap-function@^7.14.5": version "7.14.5" @@ -571,15 +516,14 @@ "@babel/traverse" "^7.14.5" "@babel/types" "^7.14.5" -"@babel/helper-wrap-function@^7.18.9": - version "7.20.5" - resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz#75e2d84d499a0ab3b31c33bcfe59d6b8a45f62e3" - integrity sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q== +"@babel/helper-wrap-function@^7.22.20": + version "7.22.20" + resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz#15352b0b9bfb10fc9c76f79f6342c00e3411a569" + integrity sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw== dependencies: - "@babel/helper-function-name" "^7.19.0" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.5" - "@babel/types" "^7.20.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/template" "^7.22.15" + "@babel/types" "^7.22.19" "@babel/helpers@^7.14.6": version "7.14.6" @@ -590,14 +534,14 @@ "@babel/traverse" "^7.14.5" "@babel/types" "^7.14.5" -"@babel/helpers@^7.17.9": - version "7.17.9" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz#b2af120821bfbe44f9907b1826e168e819375a1a" - integrity sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q== +"@babel/helpers@^7.24.1": + version "7.24.1" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz#183e44714b9eba36c3038e442516587b1e0a1a94" + integrity sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg== dependencies: - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.9" - "@babel/types" "^7.17.0" + "@babel/template" "^7.24.0" + "@babel/traverse" "^7.24.1" + "@babel/types" "^7.24.0" "@babel/highlight@^7.14.5": version "7.14.5" @@ -608,45 +552,46 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/highlight@^7.16.7": - version "7.17.9" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz#61b2ee7f32ea0454612def4fccdae0de232b73e3" - integrity sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg== +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== +"@babel/highlight@^7.24.2": + version "7.24.2" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz#3f539503efc83d3c59080a10e6634306e0370d26" + integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA== dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" js-tokens "^4.0.0" + picocolors "^1.0.0" -"@babel/parser@^7.14.5", "@babel/parser@^7.14.6", "@babel/parser@^7.14.7": +"@babel/parser@^7.14.5", "@babel/parser@^7.14.6": version "7.14.7" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz#6099720c8839ca865a2637e6c85852ead0bdb595" integrity sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA== -"@babel/parser@^7.16.7", "@babel/parser@^7.17.10": - version "7.17.10" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz#873b16db82a8909e0fbd7f115772f4b739f6ce78" - integrity sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ== +"@babel/parser@^7.24.0": + version "7.24.0" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac" + integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg== -"@babel/parser@^7.20.13", "@babel/parser@^7.20.7": - version "7.20.13" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.20.13.tgz#ddf1eb5a813588d2fb1692b70c6fce75b945c088" - integrity sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw== +"@babel/parser@^7.24.1": + version "7.24.1" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz#1e416d3627393fab1cb5b0f2f1796a100ae9133a" + integrity sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg== -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" - integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz#5cd1c87ba9380d0afb78469292c954fee5d2411a" + integrity sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.14.5": version "7.14.5" @@ -657,14 +602,14 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" "@babel/plugin-proposal-optional-chaining" "^7.14.5" -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz#d9c85589258539a22a901033853101a6198d4ef1" - integrity sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz#f6652bb16b94f8f9c20c50941e16e9756898dc5d" + integrity sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" - "@babel/plugin-proposal-optional-chaining" "^7.20.7" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-transform-optional-chaining" "^7.23.3" "@babel/plugin-proposal-async-generator-functions@^7.14.7": version "7.14.7" @@ -675,16 +620,6 @@ "@babel/helper-remap-async-to-generator" "^7.14.5" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-async-generator-functions@^7.19.1": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz#bfb7276d2d573cb67ba379984a2334e262ba5326" - integrity sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-remap-async-to-generator" "^7.18.9" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-proposal-class-properties@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz#40d1ee140c5b1e31a350f4f5eed945096559b42e" @@ -693,14 +628,6 @@ "@babel/helper-create-class-features-plugin" "^7.14.5" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-proposal-class-properties@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" - integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-proposal-class-static-block@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.14.5.tgz#158e9e10d449c3849ef3ecde94a03d9f1841b681" @@ -710,15 +637,6 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-proposal-class-static-block@^7.18.6": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.20.7.tgz#92592e9029b13b15be0f7ce6a7aedc2879ca45a7" - integrity sha512-AveGOoi9DAjUYYuUAG//Ig69GlazLnoyzMw68VCDux+c1tsnnH/OkYcpz/5xzMkEFC6UxjR5Gw1c+iY2wOGVeQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.20.7" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - "@babel/plugin-proposal-dynamic-import@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz#0c6617df461c0c1f8fff3b47cd59772360101d2c" @@ -727,14 +645,6 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-proposal-dynamic-import@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" - integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-proposal-export-namespace-from@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz#dbad244310ce6ccd083072167d8cea83a52faf76" @@ -743,14 +653,6 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-export-namespace-from@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" - integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-proposal-json-strings@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz#38de60db362e83a3d8c944ac858ddf9f0c2239eb" @@ -759,14 +661,6 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" - integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-proposal-logical-assignment-operators@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz#6e6229c2a99b02ab2915f82571e0cc646a40c738" @@ -775,14 +669,6 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-logical-assignment-operators@^7.18.9": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz#dfbcaa8f7b4d37b51e8bfb46d94a5aea2bb89d83" - integrity sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-proposal-nullish-coalescing-operator@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz#ee38589ce00e2cc59b299ec3ea406fcd3a0fdaf6" @@ -791,14 +677,6 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" - integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-proposal-numeric-separator@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz#83631bf33d9a51df184c2102a069ac0c58c05f18" @@ -807,14 +685,6 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-numeric-separator@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" - integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-proposal-object-rest-spread@^7.14.7": version "7.14.7" resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz#5920a2b3df7f7901df0205974c0641b13fd9d363" @@ -826,17 +696,6 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-transform-parameters" "^7.14.5" -"@babel/plugin-proposal-object-rest-spread@^7.19.4": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" - integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== - dependencies: - "@babel/compat-data" "^7.20.5" - "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.20.7" - "@babel/plugin-proposal-optional-catch-binding@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz#939dd6eddeff3a67fdf7b3f044b5347262598c3c" @@ -845,14 +704,6 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-catch-binding@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" - integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-proposal-optional-chaining@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz#fa83651e60a360e3f13797eef00b8d519695b603" @@ -862,15 +713,6 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.18.9", "@babel/plugin-proposal-optional-chaining@^7.20.7": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.20.7.tgz#49f2b372519ab31728cc14115bb0998b15bfda55" - integrity sha512-T+A7b1kfjtRM51ssoOfS1+wbyCVqorfyZhT99TvxxLMirPShD8CzKMRepMlCBGM5RpHMbn8s+5MMHnPstJH6mQ== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-proposal-private-methods@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz#37446495996b2945f30f5be5b60d5e2aa4f5792d" @@ -879,13 +721,10 @@ "@babel/helper-create-class-features-plugin" "^7.14.5" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-proposal-private-methods@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" - integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== "@babel/plugin-proposal-private-property-in-object@^7.14.5": version "7.14.5" @@ -897,16 +736,6 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-proposal-private-property-in-object@^7.18.6": - version "7.20.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.20.5.tgz#309c7668f2263f1c711aa399b5a9a6291eef6135" - integrity sha512-Vq7b9dUA12ByzB4EjQTPo25sFhY+08pQDBSZRtUAkj7lb7jahaHR5igera16QZ+3my1nYR4dKsNdYj5IjPHilQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-create-class-features-plugin" "^7.20.5" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-proposal-unicode-property-regex@^7.14.5", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz#0f95ee0e757a5d647f378daa0eca7e93faa8bbe8" @@ -915,14 +744,6 @@ "@babel/helper-create-regexp-features-plugin" "^7.14.5" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-proposal-unicode-property-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" - integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" @@ -958,12 +779,26 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-import-assertions@^7.18.6": - version "7.20.0" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz#bb50e0d4bea0957235390641209394e87bdb9cc4" - integrity sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ== +"@babel/plugin-syntax-import-assertions@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz#9c05a7f592982aff1a2768260ad84bcd3f0c77fc" + integrity sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-import-attributes@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz#992aee922cf04512461d7dae3ff6951b90a2dc06" + integrity sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-import-meta@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== dependencies: - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" @@ -1028,6 +863,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-transform-arrow-functions@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz#f7187d9588a768dd080bf4c9ffe117ea62f7862a" @@ -1035,12 +878,22 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-arrow-functions@^7.18.6": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz#bea332b0e8b2dab3dafe55a163d8227531ab0551" - integrity sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ== +"@babel/plugin-transform-arrow-functions@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz#94c6dcfd731af90f27a79509f9ab7fb2120fc38b" + integrity sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-async-generator-functions@^7.22.10": + version "7.23.9" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz#9adaeb66fc9634a586c5df139c6240d41ed801ce" + integrity sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-remap-async-to-generator" "^7.22.20" + "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-transform-async-to-generator@^7.14.5": version "7.14.5" @@ -1051,14 +904,14 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/helper-remap-async-to-generator" "^7.14.5" -"@babel/plugin-transform-async-to-generator@^7.18.6": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz#dfee18623c8cb31deb796aa3ca84dda9cea94354" - integrity sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q== +"@babel/plugin-transform-async-to-generator@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz#d1f513c7a8a506d43f47df2bf25f9254b0b051fa" + integrity sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw== dependencies: - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-remap-async-to-generator" "^7.18.9" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-remap-async-to-generator" "^7.22.20" "@babel/plugin-transform-block-scoped-functions@^7.14.5": version "7.14.5" @@ -1067,12 +920,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-block-scoped-functions@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" - integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== +"@babel/plugin-transform-block-scoped-functions@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz#fe1177d715fb569663095e04f3598525d98e8c77" + integrity sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-block-scoping@^7.14.5": version "7.14.5" @@ -1081,12 +934,29 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-block-scoping@^7.19.4": - version "7.20.14" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.14.tgz#2f5025f01713ba739daf737997308e0d29d1dd75" - integrity sha512-sMPepQtsOs5fM1bwNvuJJHvaCfOEQfmc01FGw0ELlTpTJj5Ql/zuNRRldYhAPys4ghXdBIQJbRVYi44/7QflQQ== +"@babel/plugin-transform-block-scoping@^7.22.10": + version "7.23.4" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz#b2d38589531c6c80fbe25e6b58e763622d2d3cf5" + integrity sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-class-properties@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz#35c377db11ca92a785a718b6aa4e3ed1eb65dc48" + integrity sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-class-static-block@^7.22.5": + version "7.23.4" + resolved "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz#2a202c8787a8964dd11dfcedf994d36bfc844ab5" + integrity sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-create-class-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-transform-classes@^7.14.5": version "7.14.5" @@ -1101,19 +971,18 @@ "@babel/helper-split-export-declaration" "^7.14.5" globals "^11.1.0" -"@babel/plugin-transform-classes@^7.19.0": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.7.tgz#f438216f094f6bb31dc266ebfab8ff05aecad073" - integrity sha512-LWYbsiXTPKl+oBlXUGlwNlJZetXD5Am+CyBdqhPsDVjM9Jc8jwBJFrKhHf900Kfk2eZG1y9MAG3UNajol7A4VQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-replace-supers" "^7.20.7" - "@babel/helper-split-export-declaration" "^7.18.6" +"@babel/plugin-transform-classes@^7.22.6": + version "7.23.8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz#d08ae096c240347badd68cdf1b6d1624a6435d92" + integrity sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.20" + "@babel/helper-split-export-declaration" "^7.22.6" globals "^11.1.0" "@babel/plugin-transform-computed-properties@^7.14.5": @@ -1123,13 +992,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-computed-properties@^7.18.9": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz#704cc2fd155d1c996551db8276d55b9d46e4d0aa" - integrity sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ== +"@babel/plugin-transform-computed-properties@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz#652e69561fcc9d2b50ba4f7ac7f60dcf65e86474" + integrity sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/template" "^7.20.7" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/template" "^7.22.15" "@babel/plugin-transform-destructuring@^7.14.7": version "7.14.7" @@ -1138,12 +1007,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-destructuring@^7.19.4": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz#8bda578f71620c7de7c93af590154ba331415454" - integrity sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA== +"@babel/plugin-transform-destructuring@^7.22.10": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz#8c9ee68228b12ae3dff986e56ed1ba4f3c446311" + integrity sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-dotall-regex@^7.14.5", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.14.5" @@ -1153,13 +1022,13 @@ "@babel/helper-create-regexp-features-plugin" "^7.14.5" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-dotall-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" - integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== +"@babel/plugin-transform-dotall-regex@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz#3f7af6054882ede89c378d0cf889b854a993da50" + integrity sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-duplicate-keys@^7.14.5": version "7.14.5" @@ -1168,12 +1037,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-duplicate-keys@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" - integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== +"@babel/plugin-transform-duplicate-keys@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz#664706ca0a5dfe8d066537f99032fc1dc8b720ce" + integrity sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-dynamic-import@^7.22.5": + version "7.23.4" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz#c7629e7254011ac3630d47d7f34ddd40ca535143" + integrity sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-transform-exponentiation-operator@^7.14.5": version "7.14.5" @@ -1183,13 +1060,21 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.14.5" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-exponentiation-operator@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" - integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== +"@babel/plugin-transform-exponentiation-operator@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz#ea0d978f6b9232ba4722f3dbecdd18f450babd18" + integrity sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-export-namespace-from@^7.22.5": + version "7.23.4" + resolved "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz#084c7b25e9a5c8271e987a08cf85807b80283191" + integrity sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-transform-for-of@^7.14.5": version "7.14.5" @@ -1198,12 +1083,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-for-of@^7.18.8": - version "7.18.8" - resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" - integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== +"@babel/plugin-transform-for-of@^7.22.5": + version "7.23.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz#81c37e24171b37b370ba6aaffa7ac86bcb46f94e" + integrity sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/plugin-transform-function-name@^7.14.5": version "7.14.5" @@ -1213,14 +1099,22 @@ "@babel/helper-function-name" "^7.14.5" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-function-name@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" - integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== +"@babel/plugin-transform-function-name@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz#8f424fcd862bf84cb9a1a6b42bc2f47ed630f8dc" + integrity sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw== dependencies: - "@babel/helper-compilation-targets" "^7.18.9" - "@babel/helper-function-name" "^7.18.9" - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-json-strings@^7.22.5": + version "7.23.4" + resolved "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz#a871d9b6bd171976efad2e43e694c961ffa3714d" + integrity sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-transform-literals@^7.14.5": version "7.14.5" @@ -1229,12 +1123,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-literals@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" - integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== +"@babel/plugin-transform-literals@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz#8214665f00506ead73de157eba233e7381f3beb4" + integrity sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-logical-assignment-operators@^7.22.5": + version "7.23.4" + resolved "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz#e599f82c51d55fac725f62ce55d3a0886279ecb5" + integrity sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-transform-member-expression-literals@^7.14.5": version "7.14.5" @@ -1243,12 +1145,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-member-expression-literals@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" - integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== +"@babel/plugin-transform-member-expression-literals@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz#e37b3f0502289f477ac0e776b05a833d853cabcc" + integrity sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-modules-amd@^7.14.5": version "7.14.5" @@ -1259,13 +1161,13 @@ "@babel/helper-plugin-utils" "^7.14.5" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-amd@^7.18.6": - version "7.20.11" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz#3daccca8e4cc309f03c3a0c4b41dc4b26f55214a" - integrity sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g== +"@babel/plugin-transform-modules-amd@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz#e19b55436a1416829df0a1afc495deedfae17f7d" + integrity sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw== dependencies: - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-modules-commonjs@^7.14.5": version "7.14.5" @@ -1277,14 +1179,14 @@ "@babel/helper-simple-access" "^7.14.5" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.18.6": - version "7.20.11" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.20.11.tgz#8cb23010869bf7669fd4b3098598b6b2be6dc607" - integrity sha512-S8e1f7WQ7cimJQ51JkAaDrEtohVEitXjgCGAS2N8S31Y42E+kWwfSz83LYz57QdBm7q9diARVqanIaH2oVgQnw== +"@babel/plugin-transform-modules-commonjs@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz#661ae831b9577e52be57dd8356b734f9700b53b4" + integrity sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA== dependencies: - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" "@babel/plugin-transform-modules-systemjs@^7.14.5": version "7.14.5" @@ -1297,15 +1199,15 @@ "@babel/helper-validator-identifier" "^7.14.5" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.19.0": - version "7.20.11" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz#467ec6bba6b6a50634eea61c9c232654d8a4696e" - integrity sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw== +"@babel/plugin-transform-modules-systemjs@^7.22.5": + version "7.23.9" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz#105d3ed46e4a21d257f83a2f9e2ee4203ceda6be" + integrity sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw== dependencies: - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-validator-identifier" "^7.19.1" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" "@babel/plugin-transform-modules-umd@^7.14.5": version "7.14.5" @@ -1315,13 +1217,13 @@ "@babel/helper-module-transforms" "^7.14.5" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-modules-umd@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" - integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== +"@babel/plugin-transform-modules-umd@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz#5d4395fccd071dfefe6585a4411aa7d6b7d769e9" + integrity sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg== dependencies: - "@babel/helper-module-transforms" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-named-capturing-groups-regex@^7.14.7": version "7.14.7" @@ -1330,13 +1232,13 @@ dependencies: "@babel/helper-create-regexp-features-plugin" "^7.14.5" -"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": - version "7.20.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz#626298dd62ea51d452c3be58b285d23195ba69a8" - integrity sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA== +"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz#67fe18ee8ce02d57c855185e27e3dc959b2e991f" + integrity sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.20.5" - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-new-target@^7.14.5": version "7.14.5" @@ -1345,12 +1247,39 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-new-target@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" - integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== +"@babel/plugin-transform-new-target@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz#5491bb78ed6ac87e990957cea367eab781c4d980" + integrity sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.22.5": + version "7.23.4" + resolved "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz#45556aad123fc6e52189ea749e33ce090637346e" + integrity sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-transform-numeric-separator@^7.22.5": + version "7.23.4" + resolved "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz#03d08e3691e405804ecdd19dd278a40cca531f29" + integrity sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-transform-object-rest-spread@^7.22.5": + version "7.24.0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.0.tgz#7b836ad0088fdded2420ce96d4e1d3ed78b71df1" + integrity sha512-y/yKMm7buHpFFXfxVFS4Vk1ToRJDilIa6fKRioB9Vjichv58TDGXTvqV0dN7plobAmTW5eSEGXDngE+Mm+uO+w== + dependencies: + "@babel/compat-data" "^7.23.5" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.23.3" "@babel/plugin-transform-object-super@^7.14.5": version "7.14.5" @@ -1360,13 +1289,30 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/helper-replace-supers" "^7.14.5" -"@babel/plugin-transform-object-super@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" - integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== +"@babel/plugin-transform-object-super@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz#81fdb636dcb306dd2e4e8fd80db5b2362ed2ebcd" + integrity sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-replace-supers" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.20" + +"@babel/plugin-transform-optional-catch-binding@^7.22.5": + version "7.23.4" + resolved "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz#318066de6dacce7d92fa244ae475aa8d91778017" + integrity sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-transform-optional-chaining@^7.22.10", "@babel/plugin-transform-optional-chaining@^7.23.3": + version "7.23.4" + resolved "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz#6acf61203bdfc4de9d4e52e64490aeb3e52bd017" + integrity sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-transform-parameters@^7.14.5": version "7.14.5" @@ -1375,12 +1321,30 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-parameters@^7.18.8", "@babel/plugin-transform-parameters@^7.20.7": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz#0ee349e9d1bc96e78e3b37a7af423a4078a7083f" - integrity sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA== +"@babel/plugin-transform-parameters@^7.22.5", "@babel/plugin-transform-parameters@^7.23.3": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz#83ef5d1baf4b1072fa6e54b2b0999a7b2527e2af" + integrity sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-private-methods@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz#b2d7a3c97e278bfe59137a978d53b2c2e038c0e4" + integrity sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-create-class-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-private-property-in-object@^7.22.5": + version "7.23.4" + resolved "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz#3ec711d05d6608fd173d9b8de39872d8dbf68bf5" + integrity sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-transform-property-literals@^7.14.5": version "7.14.5" @@ -1389,12 +1353,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-property-literals@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" - integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== +"@babel/plugin-transform-property-literals@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz#54518f14ac4755d22b92162e4a852d308a560875" + integrity sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-regenerator@^7.14.5": version "7.14.5" @@ -1403,13 +1367,13 @@ dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-regenerator@^7.18.6": - version "7.20.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz#57cda588c7ffb7f4f8483cc83bdcea02a907f04d" - integrity sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ== +"@babel/plugin-transform-regenerator@^7.22.10": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz#141afd4a2057298602069fce7f2dc5173e6c561c" + integrity sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - regenerator-transform "^0.15.1" + "@babel/helper-plugin-utils" "^7.22.5" + regenerator-transform "^0.15.2" "@babel/plugin-transform-reserved-words@^7.14.5": version "7.14.5" @@ -1418,12 +1382,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-reserved-words@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" - integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== +"@babel/plugin-transform-reserved-words@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz#4130dcee12bd3dd5705c587947eb715da12efac8" + integrity sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-shorthand-properties@^7.14.5": version "7.14.5" @@ -1432,12 +1396,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-shorthand-properties@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" - integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== +"@babel/plugin-transform-shorthand-properties@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz#97d82a39b0e0c24f8a981568a8ed851745f59210" + integrity sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-spread@^7.14.6": version "7.14.6" @@ -1447,13 +1411,13 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" -"@babel/plugin-transform-spread@^7.19.0": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz#c2d83e0b99d3bf83e07b11995ee24bf7ca09401e" - integrity sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw== +"@babel/plugin-transform-spread@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz#41d17aacb12bde55168403c6f2d6bdca563d362c" + integrity sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/plugin-transform-sticky-regex@^7.14.5": version "7.14.5" @@ -1462,12 +1426,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-sticky-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" - integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== +"@babel/plugin-transform-sticky-regex@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz#dec45588ab4a723cb579c609b294a3d1bd22ff04" + integrity sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-template-literals@^7.14.5": version "7.14.5" @@ -1476,12 +1440,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-template-literals@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" - integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== +"@babel/plugin-transform-template-literals@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz#5f0f028eb14e50b5d0f76be57f90045757539d07" + integrity sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-typeof-symbol@^7.14.5": version "7.14.5" @@ -1490,12 +1454,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-typeof-symbol@^7.18.9": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" - integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== +"@babel/plugin-transform-typeof-symbol@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz#9dfab97acc87495c0c449014eb9c547d8966bca4" + integrity sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-unicode-escapes@^7.14.5": version "7.14.5" @@ -1504,12 +1468,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-unicode-escapes@^7.18.10": - version "7.18.10" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" - integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== +"@babel/plugin-transform-unicode-escapes@^7.22.10": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz#1f66d16cab01fab98d784867d24f70c1ca65b925" + integrity sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-unicode-property-regex@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz#19e234129e5ffa7205010feec0d94c251083d7ad" + integrity sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-create-regexp-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-unicode-regex@^7.14.5": version "7.14.5" @@ -1519,46 +1491,42 @@ "@babel/helper-create-regexp-features-plugin" "^7.14.5" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-unicode-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" - integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/preset-env@7.19.4": - version "7.19.4" - resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.19.4.tgz#4c91ce2e1f994f717efb4237891c3ad2d808c94b" - integrity sha512-5QVOTXUdqTCjQuh2GGtdd7YEhoRXBMVGROAtsBeLGIbIz3obCBIfRMT1I3ZKkMgNzwkyCkftDXSSkHxnfVf4qg== - dependencies: - "@babel/compat-data" "^7.19.4" - "@babel/helper-compilation-targets" "^7.19.3" - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/helper-validator-option" "^7.18.6" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9" - "@babel/plugin-proposal-async-generator-functions" "^7.19.1" - "@babel/plugin-proposal-class-properties" "^7.18.6" - "@babel/plugin-proposal-class-static-block" "^7.18.6" - "@babel/plugin-proposal-dynamic-import" "^7.18.6" - "@babel/plugin-proposal-export-namespace-from" "^7.18.9" - "@babel/plugin-proposal-json-strings" "^7.18.6" - "@babel/plugin-proposal-logical-assignment-operators" "^7.18.9" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6" - "@babel/plugin-proposal-numeric-separator" "^7.18.6" - "@babel/plugin-proposal-object-rest-spread" "^7.19.4" - "@babel/plugin-proposal-optional-catch-binding" "^7.18.6" - "@babel/plugin-proposal-optional-chaining" "^7.18.9" - "@babel/plugin-proposal-private-methods" "^7.18.6" - "@babel/plugin-proposal-private-property-in-object" "^7.18.6" - "@babel/plugin-proposal-unicode-property-regex" "^7.18.6" +"@babel/plugin-transform-unicode-regex@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz#26897708d8f42654ca4ce1b73e96140fbad879dc" + integrity sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-unicode-sets-regex@^7.22.5": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz#4fb6f0a719c2c5859d11f6b55a050cc987f3799e" + integrity sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/preset-env@7.22.10": + version "7.22.10" + resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.10.tgz#3263b9fe2c8823d191d28e61eac60a79f9ce8a0f" + integrity sha512-riHpLb1drNkpLlocmSyEg4oYJIQFeXAK/d7rI6mbD0XsvoTOOweXDmQPG/ErxsEhWk3rl3Q/3F6RFQlVFS8m0A== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-compilation-targets" "^7.22.10" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.5" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.22.5" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.22.5" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.18.6" + "@babel/plugin-syntax-import-assertions" "^7.22.5" + "@babel/plugin-syntax-import-attributes" "^7.22.5" + "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" @@ -1568,45 +1536,62 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.18.6" - "@babel/plugin-transform-async-to-generator" "^7.18.6" - "@babel/plugin-transform-block-scoped-functions" "^7.18.6" - "@babel/plugin-transform-block-scoping" "^7.19.4" - "@babel/plugin-transform-classes" "^7.19.0" - "@babel/plugin-transform-computed-properties" "^7.18.9" - "@babel/plugin-transform-destructuring" "^7.19.4" - "@babel/plugin-transform-dotall-regex" "^7.18.6" - "@babel/plugin-transform-duplicate-keys" "^7.18.9" - "@babel/plugin-transform-exponentiation-operator" "^7.18.6" - "@babel/plugin-transform-for-of" "^7.18.8" - "@babel/plugin-transform-function-name" "^7.18.9" - "@babel/plugin-transform-literals" "^7.18.9" - "@babel/plugin-transform-member-expression-literals" "^7.18.6" - "@babel/plugin-transform-modules-amd" "^7.18.6" - "@babel/plugin-transform-modules-commonjs" "^7.18.6" - "@babel/plugin-transform-modules-systemjs" "^7.19.0" - "@babel/plugin-transform-modules-umd" "^7.18.6" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.1" - "@babel/plugin-transform-new-target" "^7.18.6" - "@babel/plugin-transform-object-super" "^7.18.6" - "@babel/plugin-transform-parameters" "^7.18.8" - "@babel/plugin-transform-property-literals" "^7.18.6" - "@babel/plugin-transform-regenerator" "^7.18.6" - "@babel/plugin-transform-reserved-words" "^7.18.6" - "@babel/plugin-transform-shorthand-properties" "^7.18.6" - "@babel/plugin-transform-spread" "^7.19.0" - "@babel/plugin-transform-sticky-regex" "^7.18.6" - "@babel/plugin-transform-template-literals" "^7.18.9" - "@babel/plugin-transform-typeof-symbol" "^7.18.9" - "@babel/plugin-transform-unicode-escapes" "^7.18.10" - "@babel/plugin-transform-unicode-regex" "^7.18.6" - "@babel/preset-modules" "^0.1.5" - "@babel/types" "^7.19.4" - babel-plugin-polyfill-corejs2 "^0.3.3" - babel-plugin-polyfill-corejs3 "^0.6.0" - babel-plugin-polyfill-regenerator "^0.4.1" - core-js-compat "^3.25.1" - semver "^6.3.0" + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.22.5" + "@babel/plugin-transform-async-generator-functions" "^7.22.10" + "@babel/plugin-transform-async-to-generator" "^7.22.5" + "@babel/plugin-transform-block-scoped-functions" "^7.22.5" + "@babel/plugin-transform-block-scoping" "^7.22.10" + "@babel/plugin-transform-class-properties" "^7.22.5" + "@babel/plugin-transform-class-static-block" "^7.22.5" + "@babel/plugin-transform-classes" "^7.22.6" + "@babel/plugin-transform-computed-properties" "^7.22.5" + "@babel/plugin-transform-destructuring" "^7.22.10" + "@babel/plugin-transform-dotall-regex" "^7.22.5" + "@babel/plugin-transform-duplicate-keys" "^7.22.5" + "@babel/plugin-transform-dynamic-import" "^7.22.5" + "@babel/plugin-transform-exponentiation-operator" "^7.22.5" + "@babel/plugin-transform-export-namespace-from" "^7.22.5" + "@babel/plugin-transform-for-of" "^7.22.5" + "@babel/plugin-transform-function-name" "^7.22.5" + "@babel/plugin-transform-json-strings" "^7.22.5" + "@babel/plugin-transform-literals" "^7.22.5" + "@babel/plugin-transform-logical-assignment-operators" "^7.22.5" + "@babel/plugin-transform-member-expression-literals" "^7.22.5" + "@babel/plugin-transform-modules-amd" "^7.22.5" + "@babel/plugin-transform-modules-commonjs" "^7.22.5" + "@babel/plugin-transform-modules-systemjs" "^7.22.5" + "@babel/plugin-transform-modules-umd" "^7.22.5" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" + "@babel/plugin-transform-new-target" "^7.22.5" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.22.5" + "@babel/plugin-transform-numeric-separator" "^7.22.5" + "@babel/plugin-transform-object-rest-spread" "^7.22.5" + "@babel/plugin-transform-object-super" "^7.22.5" + "@babel/plugin-transform-optional-catch-binding" "^7.22.5" + "@babel/plugin-transform-optional-chaining" "^7.22.10" + "@babel/plugin-transform-parameters" "^7.22.5" + "@babel/plugin-transform-private-methods" "^7.22.5" + "@babel/plugin-transform-private-property-in-object" "^7.22.5" + "@babel/plugin-transform-property-literals" "^7.22.5" + "@babel/plugin-transform-regenerator" "^7.22.10" + "@babel/plugin-transform-reserved-words" "^7.22.5" + "@babel/plugin-transform-shorthand-properties" "^7.22.5" + "@babel/plugin-transform-spread" "^7.22.5" + "@babel/plugin-transform-sticky-regex" "^7.22.5" + "@babel/plugin-transform-template-literals" "^7.22.5" + "@babel/plugin-transform-typeof-symbol" "^7.22.5" + "@babel/plugin-transform-unicode-escapes" "^7.22.10" + "@babel/plugin-transform-unicode-property-regex" "^7.22.5" + "@babel/plugin-transform-unicode-regex" "^7.22.5" + "@babel/plugin-transform-unicode-sets-regex" "^7.22.5" + "@babel/preset-modules" "0.1.6-no-external-plugins" + "@babel/types" "^7.22.10" + babel-plugin-polyfill-corejs2 "^0.4.5" + babel-plugin-polyfill-corejs3 "^0.8.3" + babel-plugin-polyfill-regenerator "^0.5.2" + core-js-compat "^3.31.0" + semver "^6.3.1" "@babel/preset-env@^7.11.0": version "7.14.7" @@ -1687,21 +1672,19 @@ core-js-compat "^3.15.0" semver "^6.3.0" -"@babel/preset-modules@^0.1.4": - version "0.1.4" - resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" - integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-modules@^0.1.5": - version "0.1.5" - resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" - integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== +"@babel/preset-modules@^0.1.4": + version "0.1.4" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" + integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" @@ -1709,6 +1692,11 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" +"@babel/regjsgen@^0.8.0": + version "0.8.0" + resolved "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" + integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== + "@babel/runtime@^7.8.4": version "7.14.6" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz#535203bc0892efc7dec60bdc27b2ecf6e409062d" @@ -1725,69 +1713,29 @@ "@babel/parser" "^7.14.5" "@babel/types" "^7.14.5" -"@babel/template@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/template@^7.18.10", "@babel/template@^7.20.7": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" - integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - -"@babel/traverse@^7.13.0", "@babel/traverse@^7.14.5": - version "7.14.7" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.7.tgz#64007c9774cfdc3abd23b0780bc18a3ce3631753" - integrity sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/generator" "^7.14.5" - "@babel/helper-function-name" "^7.14.5" - "@babel/helper-hoist-variables" "^7.14.5" - "@babel/helper-split-export-declaration" "^7.14.5" - "@babel/parser" "^7.14.7" - "@babel/types" "^7.14.5" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.17.10", "@babel/traverse@^7.17.3", "@babel/traverse@^7.17.9": - version "7.17.10" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.10.tgz#1ee1a5ac39f4eac844e6cf855b35520e5eb6f8b5" - integrity sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.10" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.17.9" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.10" - "@babel/types" "^7.17.10" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.20.10", "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7": - version "7.20.13" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.13.tgz#817c1ba13d11accca89478bd5481b2d168d07473" - integrity sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.7" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.20.13" - "@babel/types" "^7.20.7" - debug "^4.1.0" +"@babel/template@^7.22.15", "@babel/template@^7.24.0": + version "7.24.0" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" + integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/parser" "^7.24.0" + "@babel/types" "^7.24.0" + +"@babel/traverse@^7.13.0", "@babel/traverse@^7.14.5", "@babel/traverse@^7.24.1": + version "7.24.1" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz#d65c36ac9dd17282175d1e4a3c49d5b7988f530c" + integrity sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ== + dependencies: + "@babel/code-frame" "^7.24.1" + "@babel/generator" "^7.24.1" + "@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.24.1" + "@babel/types" "^7.24.0" + debug "^4.3.1" globals "^11.1.0" "@babel/types@^7.14.5", "@babel/types@^7.4.4": @@ -1798,15 +1746,7 @@ "@babel/helper-validator-identifier" "^7.14.5" to-fast-properties "^2.0.0" -"@babel/types@^7.16.7", "@babel/types@^7.17.0", "@babel/types@^7.17.10": - version "7.17.10" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.17.10.tgz#d35d7b4467e439fcf06d195f8100e0fea7fc82c4" - integrity sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.19.4", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7": +"@babel/types@^7.18.6": version "7.20.7" resolved "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f" integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg== @@ -1815,6 +1755,15 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" +"@babel/types@^7.22.10", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.24.0": + version "7.24.0" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf" + integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" @@ -1825,15 +1774,15 @@ resolved "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz#90420f9f9c6d3987f176a19a7d8e764271a2f55d" integrity sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g== -"@firebase/analytics-compat@0.2.3": - version "0.2.3" - resolved "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.3.tgz#ed60472dcd2bfa3f2fa7a5478b63bb7aece652ed" - integrity sha512-HmvbB4GMgh8AUlIDIo/OuFENLCGRXxMvtOueK+m8+DcfqBvG+mkii0Mi9ovo0TnMM62cy3oBYG7PHdjIQNLSLA== +"@firebase/analytics-compat@0.2.6": + version "0.2.6" + resolved "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.6.tgz#50063978c42f13eb800e037e96ac4b17236841f4" + integrity sha512-4MqpVLFkGK7NJf/5wPEEP7ePBJatwYpyjgJ+wQHQGHfzaCDgntOnl9rL2vbVGGKCnRqWtZDIWhctB86UWXaX2Q== dependencies: - "@firebase/analytics" "0.9.3" + "@firebase/analytics" "0.10.0" "@firebase/analytics-types" "0.8.0" - "@firebase/component" "0.6.3" - "@firebase/util" "1.9.2" + "@firebase/component" "0.6.4" + "@firebase/util" "1.9.3" tslib "^2.1.0" "@firebase/analytics-types@0.8.0": @@ -1841,58 +1790,58 @@ resolved "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.0.tgz#551e744a29adbc07f557306530a2ec86add6d410" integrity sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw== -"@firebase/analytics@0.9.3": - version "0.9.3" - resolved "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.9.3.tgz#ae653a6c6bcd667efd1d3cc5207e3e621d737028" - integrity sha512-XdYHBi6RvHYVAHGyLxXX0uRPwZmGeqw1JuWS1rMEeRF/jvbxnrL81kcFAHZVRkEvG9bXAJgL2fX9wmDo3e622w== +"@firebase/analytics@0.10.0": + version "0.10.0" + resolved "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.0.tgz#9c6986acd573c6c6189ffb52d0fd63c775db26d7" + integrity sha512-Locv8gAqx0e+GX/0SI3dzmBY5e9kjVDtD+3zCFLJ0tH2hJwuCAiL+5WkHuxKj92rqQj/rvkBUCfA1ewlX2hehg== dependencies: - "@firebase/component" "0.6.3" - "@firebase/installations" "0.6.3" + "@firebase/component" "0.6.4" + "@firebase/installations" "0.6.4" "@firebase/logger" "0.4.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" tslib "^2.1.0" -"@firebase/app-check-compat@0.3.3": - version "0.3.3" - resolved "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.3.tgz#a1d594ec722fa81f7e11977b407a187e8afdb19a" - integrity sha512-25AQ4W7WUL8OWas40GsABuNU622Dm1ojbfeZ03uKtLj5Af7FerJ25u7zkgm+11pc6rpr5v8E5oxEG9vmNRndEA== +"@firebase/app-check-compat@0.3.7": + version "0.3.7" + resolved "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.7.tgz#e150f61d653a0f2043a34dcb995616a717161839" + integrity sha512-cW682AxsyP1G+Z0/P7pO/WT2CzYlNxoNe5QejVarW2o5ZxeWSSPAiVEwpEpQR/bUlUmdeWThYTMvBWaopdBsqw== dependencies: - "@firebase/app-check" "0.6.3" + "@firebase/app-check" "0.8.0" "@firebase/app-check-types" "0.5.0" - "@firebase/component" "0.6.3" + "@firebase/component" "0.6.4" "@firebase/logger" "0.4.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" tslib "^2.1.0" -"@firebase/app-check-interop-types@0.2.0": - version "0.2.0" - resolved "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.2.0.tgz#9106270114ca4e7732457e8319333866a26285d8" - integrity sha512-+3PQIeX6/eiVK+x/yg8r6xTNR97fN7MahFDm+jiQmDjcyvSefoGuTTNQuuMScGyx3vYUBeZn+Cp9kC0yY/9uxQ== +"@firebase/app-check-interop-types@0.3.0": + version "0.3.0" + resolved "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.0.tgz#b27ea1397cb80427f729e4bbf3a562f2052955c4" + integrity sha512-xAxHPZPIgFXnI+vb4sbBjZcde7ZluzPPaSK7Lx3/nmuVk4TjZvnL8ONnkd4ERQKL8WePQySU+pRcWkh8rDf5Sg== "@firebase/app-check-types@0.5.0": version "0.5.0" resolved "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.0.tgz#1b02826213d7ce6a1cf773c329b46ea1c67064f4" integrity sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ== -"@firebase/app-check@0.6.3": - version "0.6.3" - resolved "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.6.3.tgz#221060e5e0eac1e20ee724478b61e89ad6e8420a" - integrity sha512-T9f9ceFLs7x4D2T6whu5a6j7B3qPuYHiZHZxW6DkMh/FoMmRA4/q/HVyu01i9+LyJJx2Xdo6eCcj6ofs9YZjqA== +"@firebase/app-check@0.8.0": + version "0.8.0" + resolved "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.0.tgz#b531ec40900af9c3cf1ec63de9094a0ddd733d6a" + integrity sha512-dRDnhkcaC2FspMiRK/Vbp+PfsOAEP6ZElGm9iGFJ9fDqHoPs0HOPn7dwpJ51lCFi1+2/7n5pRPGhqF/F03I97g== dependencies: - "@firebase/component" "0.6.3" + "@firebase/component" "0.6.4" "@firebase/logger" "0.4.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" tslib "^2.1.0" -"@firebase/app-compat@0.2.3": - version "0.2.3" - resolved "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.3.tgz#a31c823d415c041591ee8c355776cd5bca7ef6e2" - integrity sha512-sX6rD1KFX6K2CuCnQvc9jZLOgAFZ+sv2jKKahIl4SbTM561D682B8n4Jtx/SgDrvcTVTdb05g4NhZOws9hxYxA== +"@firebase/app-compat@0.2.13": + version "0.2.13" + resolved "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.13.tgz#c42d392f45f2c9fef1631cb3ae36d53296aa6407" + integrity sha512-j6ANZaWjeVy5zg6X7uiqh6lM6o3n3LD1+/SJFNs9V781xyryyZWXe+tmnWNWPkP086QfJoNkWN9pMQRqSG4vMg== dependencies: - "@firebase/app" "0.9.3" - "@firebase/component" "0.6.3" + "@firebase/app" "0.9.13" + "@firebase/component" "0.6.4" "@firebase/logger" "0.4.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" tslib "^2.1.0" "@firebase/app-types@0.9.0": @@ -1900,26 +1849,26 @@ resolved "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz#35b5c568341e9e263b29b3d2ba0e9cfc9ec7f01e" integrity sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q== -"@firebase/app@0.9.3": - version "0.9.3" - resolved "https://registry.npmjs.org/@firebase/app/-/app-0.9.3.tgz#6a9c9b2544fa9a50ad8f405355896c54339c228b" - integrity sha512-G79JUceVDaHRZ4WkA11GyVldVXhdyRJRwWVQFFvAAVfQJLvy2TA6lQjeUn28F6FmeUWxDGwPC30bxCRWq7Op8Q== +"@firebase/app@0.9.13": + version "0.9.13" + resolved "https://registry.npmjs.org/@firebase/app/-/app-0.9.13.tgz#b1d3ad63d52f235a0d70a9b4261cabb3a24690d7" + integrity sha512-GfiI1JxJ7ecluEmDjPzseRXk/PX31hS7+tjgBopL7XjB2hLUdR+0FTMXy2Q3/hXezypDvU6or7gVFizDESrkXw== dependencies: - "@firebase/component" "0.6.3" + "@firebase/component" "0.6.4" "@firebase/logger" "0.4.0" - "@firebase/util" "1.9.2" - idb "7.0.1" + "@firebase/util" "1.9.3" + idb "7.1.1" tslib "^2.1.0" -"@firebase/auth-compat@0.3.3": - version "0.3.3" - resolved "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.3.3.tgz#e52f654e3f14b81cecb2fe252e564778fbba0a47" - integrity sha512-9asUuGtkzUVELH3LYXdiom1nVVV9bqEPqzHohanoofHL/oVTNcHZ4AQ5CXjNATfb6c1WH32U+nEuPiYg26UUIw== +"@firebase/auth-compat@0.4.2": + version "0.4.2" + resolved "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.4.2.tgz#cb65edc2fbd5f72fff32310409f2fd702b5145e7" + integrity sha512-Q30e77DWXFmXEt5dg5JbqEDpjw9y3/PcP9LslDPR7fARmAOTIY9MM6HXzm9KC+dlrKH/+p6l8g9ifJiam9mc4A== dependencies: - "@firebase/auth" "0.21.3" + "@firebase/auth" "0.23.2" "@firebase/auth-types" "0.12.0" - "@firebase/component" "0.6.3" - "@firebase/util" "1.9.2" + "@firebase/component" "0.6.4" + "@firebase/util" "1.9.3" node-fetch "2.6.7" tslib "^2.1.0" @@ -1933,66 +1882,66 @@ resolved "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.0.tgz#f28e1b68ac3b208ad02a15854c585be6da3e8e79" integrity sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA== -"@firebase/auth@0.21.3": - version "0.21.3" - resolved "https://registry.npmjs.org/@firebase/auth/-/auth-0.21.3.tgz#277a3bf4b09db1b5dd471970cecd844d1835dcbf" - integrity sha512-HPbcwgArLBVTowFcn4qaQr6LCx7BidI9yrQ5MRbQNv4PsgK/3UGpzCYaNPPbvgr9fe+0jNdJO+uC0+dk4xIzCQ== +"@firebase/auth@0.23.2": + version "0.23.2" + resolved "https://registry.npmjs.org/@firebase/auth/-/auth-0.23.2.tgz#9e6d8dd550a28053c1825fb98c7dc9b37119254d" + integrity sha512-dM9iJ0R6tI1JczuGSxXmQbXAgtYie0K4WvKcuyuSTCu9V8eEDiz4tfa1sO3txsfvwg7nOY3AjoCyMYEdqZ8hdg== dependencies: - "@firebase/component" "0.6.3" + "@firebase/component" "0.6.4" "@firebase/logger" "0.4.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" node-fetch "2.6.7" tslib "^2.1.0" -"@firebase/component@0.6.3": - version "0.6.3" - resolved "https://registry.npmjs.org/@firebase/component/-/component-0.6.3.tgz#2baea3fa37861eef314a612eba194b0ff7c7ac11" - integrity sha512-rnhq5SOsB5nuJphZF50iwqnBiuuyg9kdnlUn1rBrKfu7/cUVJZF5IG1cWrL0rXXyiZW1WBI/J2pmTvVO8dStGQ== +"@firebase/component@0.6.4": + version "0.6.4" + resolved "https://registry.npmjs.org/@firebase/component/-/component-0.6.4.tgz#8981a6818bd730a7554aa5e0516ffc9b1ae3f33d" + integrity sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA== dependencies: - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" tslib "^2.1.0" -"@firebase/database-compat@0.3.3": - version "0.3.3" - resolved "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.3.3.tgz#4668e32527f57c1dde6cb03f5fde81eb04503ad4" - integrity sha512-r+L9jTbvsnb7sD+xz6UKU39DgBWqB2pyjzPNdBeriGC9Ssa2MAZe0bIqjCQg51RRXYc/aa/zK1Q2/4uesZeVgQ== +"@firebase/database-compat@0.3.4": + version "0.3.4" + resolved "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.3.4.tgz#4e57932f7a5ba761cd5ac946ab6b6ab3f660522c" + integrity sha512-kuAW+l+sLMUKBThnvxvUZ+Q1ZrF/vFJ58iUY9kAcbX48U03nVzIF6Tmkf0p3WVQwMqiXguSgtOPIB6ZCeF+5Gg== dependencies: - "@firebase/component" "0.6.3" - "@firebase/database" "0.14.3" - "@firebase/database-types" "0.10.3" + "@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.2" + "@firebase/util" "1.9.3" tslib "^2.1.0" -"@firebase/database-types@0.10.3": - version "0.10.3" - resolved "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.10.3.tgz#f057e150b8c2aff0c623162abef139ff5df9bfd2" - integrity sha512-Hu34CDhHYZsd2eielr0jeaWrTJk8Hz0nd7WsnYDnXtQX4i49ppgPesUzPdXVBdIBLJmT0ZZRvT7qWHknkOT+zg== +"@firebase/database-types@0.10.4": + version "0.10.4" + resolved "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.10.4.tgz#47ba81113512dab637abace61cfb65f63d645ca7" + integrity sha512-dPySn0vJ/89ZeBac70T+2tWWPiJXWbmRygYv0smT5TfE3hDrQ09eKMF3Y+vMlTdrMWq7mUdYW5REWPSGH4kAZQ== dependencies: "@firebase/app-types" "0.9.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" -"@firebase/database@0.14.3": - version "0.14.3" - resolved "https://registry.npmjs.org/@firebase/database/-/database-0.14.3.tgz#0ddd92e5eeef2dbebefd55ce78b39472a57dd5d3" - integrity sha512-J76W6N7JiVkLaAtPyjaGRkrsIu9pi6iZikuGGtGjqvV19vkn7oiL4Hbo5uTYCMd4waTUWoL9iI08eX184W+5GQ== +"@firebase/database@0.14.4": + version "0.14.4" + resolved "https://registry.npmjs.org/@firebase/database/-/database-0.14.4.tgz#9e7435a16a540ddfdeb5d99d45618e6ede179aa6" + integrity sha512-+Ea/IKGwh42jwdjCyzTmeZeLM3oy1h0mFPsTy6OqCWzcu/KFqRAr5Tt1HRCOBlNOdbh84JPZC47WLU18n2VbxQ== dependencies: "@firebase/auth-interop-types" "0.2.1" - "@firebase/component" "0.6.3" + "@firebase/component" "0.6.4" "@firebase/logger" "0.4.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" faye-websocket "0.11.4" tslib "^2.1.0" -"@firebase/firestore-compat@0.3.3": - version "0.3.3" - resolved "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.3.tgz#2fedc13e6242aa98a78cfb710242721d9822c1da" - integrity sha512-fMTsSC0s2cF5w2+JoB0dWD/o4kXtLrUCPGnZPuz4S0bqTN2t0vHr3gdAsQLtnadgwB78ACtinYmf4Udwx7TzDg== +"@firebase/firestore-compat@0.3.12": + version "0.3.12" + resolved "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.12.tgz#c08b24c76da7af75598f3c28432b6eb22f959b56" + integrity sha512-mazuNGAx5Kt9Nph0pm6ULJFp/+j7GSsx+Ncw1GrnKl+ft1CQ4q2LcUssXnjqkX2Ry0fNGqUzC1mfIUrk9bYtjQ== dependencies: - "@firebase/component" "0.6.3" - "@firebase/firestore" "3.8.3" + "@firebase/component" "0.6.4" + "@firebase/firestore" "3.13.0" "@firebase/firestore-types" "2.5.1" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" tslib "^2.1.0" "@firebase/firestore-types@2.5.1": @@ -2000,29 +1949,29 @@ resolved "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-2.5.1.tgz#464b2ee057956599ca34de50eae957c30fdbabb7" integrity sha512-xG0CA6EMfYo8YeUxC8FeDzf6W3FX1cLlcAGBYV6Cku12sZRI81oWcu61RSKM66K6kUENP+78Qm8mvroBcm1whw== -"@firebase/firestore@3.8.3": - version "3.8.3" - resolved "https://registry.npmjs.org/@firebase/firestore/-/firestore-3.8.3.tgz#8305113b9535747f982b585b0dd72e85122b5b89" - integrity sha512-4xR3Mqj95bxHg3hZnz0O+LQrHkjq+siT2y+B9da6u68qJ8bzzT42JaFgd1vifhbBpVbBzpFaS2RuCq2E+kGv9g== +"@firebase/firestore@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@firebase/firestore/-/firestore-3.13.0.tgz#f924a3bb462bc3ac666dc5d375f3f8c4e1a72345" + integrity sha512-NwcnU+madJXQ4fbLkGx1bWvL612IJN/qO6bZ6dlPmyf7QRyu5azUosijdAN675r+bOOJxMtP1Bv981bHBXAbUg== dependencies: - "@firebase/component" "0.6.3" + "@firebase/component" "0.6.4" "@firebase/logger" "0.4.0" - "@firebase/util" "1.9.2" - "@firebase/webchannel-wrapper" "0.9.0" + "@firebase/util" "1.9.3" + "@firebase/webchannel-wrapper" "0.10.1" "@grpc/grpc-js" "~1.7.0" "@grpc/proto-loader" "^0.6.13" node-fetch "2.6.7" tslib "^2.1.0" -"@firebase/functions-compat@0.3.3": - version "0.3.3" - resolved "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.3.tgz#530c30b4dfea14e71657f780d2c281e16209aed7" - integrity sha512-UIAJ2gzNq0p/61cXqkpi9DnlQt0hdlGqgmL5an7KuJth2Iv5uGpKg/+OapAZxPuiUNZgTEyZDB7kNBHvnxWq5w== +"@firebase/functions-compat@0.3.5": + version "0.3.5" + resolved "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.5.tgz#7a532d3a9764c6d5fbc1ec5541a989a704326647" + integrity sha512-uD4jwgwVqdWf6uc3NRKF8cSZ0JwGqSlyhPgackyUPe+GAtnERpS4+Vr66g0b3Gge0ezG4iyHo/EXW/Hjx7QhHw== dependencies: - "@firebase/component" "0.6.3" - "@firebase/functions" "0.9.3" + "@firebase/component" "0.6.4" + "@firebase/functions" "0.10.0" "@firebase/functions-types" "0.6.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" tslib "^2.1.0" "@firebase/functions-types@0.6.0": @@ -2030,28 +1979,28 @@ resolved "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.0.tgz#ccd7000dc6fc668f5acb4e6a6a042a877a555ef2" integrity sha512-hfEw5VJtgWXIRf92ImLkgENqpL6IWpYaXVYiRkFY1jJ9+6tIhWM7IzzwbevwIIud/jaxKVdRzD7QBWfPmkwCYw== -"@firebase/functions@0.9.3": - version "0.9.3" - resolved "https://registry.npmjs.org/@firebase/functions/-/functions-0.9.3.tgz#9ef33efcd38b0235e84ae472d9b51597efe3f871" - integrity sha512-tPJgYY2ROQSYuzvgxZRoHeDj+Ic07/bWHwaftgTriawtupmFOkt5iikuhJSJUhaOpFh9TB335OvCXJw1N+BIlQ== +"@firebase/functions@0.10.0": + version "0.10.0" + resolved "https://registry.npmjs.org/@firebase/functions/-/functions-0.10.0.tgz#c630ddf12cdf941c25bc8d554e30c3226cd560f6" + integrity sha512-2U+fMNxTYhtwSpkkR6WbBcuNMOVaI7MaH3cZ6UAeNfj7AgEwHwMIFLPpC13YNZhno219F0lfxzTAA0N62ndWzA== dependencies: - "@firebase/app-check-interop-types" "0.2.0" + "@firebase/app-check-interop-types" "0.3.0" "@firebase/auth-interop-types" "0.2.1" - "@firebase/component" "0.6.3" + "@firebase/component" "0.6.4" "@firebase/messaging-interop-types" "0.2.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" node-fetch "2.6.7" tslib "^2.1.0" -"@firebase/installations-compat@0.2.3": - version "0.2.3" - resolved "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.3.tgz#42b05f4e5204c354e0fa059378402bd47635e5bf" - integrity sha512-K9rKM/ym06lkpaKz7bMLxzHK/HEk65XfLJBV+dJkIuWeO0EqqC9VFGrpWAo0QmgC4BqbU58T6VBbzoJjb0gaFw== +"@firebase/installations-compat@0.2.4": + version "0.2.4" + resolved "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.4.tgz#b5557c897b4cd3635a59887a8bf69c3731aaa952" + integrity sha512-LI9dYjp0aT9Njkn9U4JRrDqQ6KXeAmFbRC0E7jI7+hxl5YmRWysq5qgQl22hcWpTk+cm3es66d/apoDU/A9n6Q== dependencies: - "@firebase/component" "0.6.3" - "@firebase/installations" "0.6.3" + "@firebase/component" "0.6.4" + "@firebase/installations" "0.6.4" "@firebase/installations-types" "0.5.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" tslib "^2.1.0" "@firebase/installations-types@0.5.0": @@ -2059,13 +2008,13 @@ resolved "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.0.tgz#2adad64755cd33648519b573ec7ec30f21fb5354" integrity sha512-9DP+RGfzoI2jH7gY4SlzqvZ+hr7gYzPODrbzVD82Y12kScZ6ZpRg/i3j6rleto8vTFC8n6Len4560FnV1w2IRg== -"@firebase/installations@0.6.3": - version "0.6.3" - resolved "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.3.tgz#b833cf12ac63666246a57100dbdd669fb76a23aa" - integrity sha512-20JFWm+tweNoRjRbz8/Y4I7O5pUJGZsFKCkLl1qNxfNYECSfrZUuozIDJDZC/MeVn5+kB9CwjThDlgQEPrfLdg== +"@firebase/installations@0.6.4": + version "0.6.4" + resolved "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.4.tgz#20382e33e6062ac5eff4bede8e468ed4c367609e" + integrity sha512-u5y88rtsp7NYkCHC3ElbFBrPtieUybZluXyzl7+4BsIz4sqb4vSAuwHEUgCgCeaQhvsnxDEU6icly8U9zsJigA== dependencies: - "@firebase/component" "0.6.3" - "@firebase/util" "1.9.2" + "@firebase/component" "0.6.4" + "@firebase/util" "1.9.3" idb "7.0.1" tslib "^2.1.0" @@ -2076,14 +2025,14 @@ dependencies: tslib "^2.1.0" -"@firebase/messaging-compat@0.2.3": - version "0.2.3" - resolved "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.3.tgz#2d222e4078643e49a708b61b6d0e51edc2bc73bd" - integrity sha512-MmuuohXV2YRzIoJmDngI5qqO/cF2q7SdAaw7k4r61W3ReJy7x4/rtqrIvwNVhM6X/X8NFGBbsYKsCfRHWjFdkg== +"@firebase/messaging-compat@0.2.4": + version "0.2.4" + resolved "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.4.tgz#323ca48deef77065b4fcda3cfd662c4337dffcfd" + integrity sha512-lyFjeUhIsPRYDPNIkYX1LcZMpoVbBWXX4rPl7c/rqc7G+EUea7IEtSt4MxTvh6fDfPuzLn7+FZADfscC+tNMfg== dependencies: - "@firebase/component" "0.6.3" - "@firebase/messaging" "0.12.3" - "@firebase/util" "1.9.2" + "@firebase/component" "0.6.4" + "@firebase/messaging" "0.12.4" + "@firebase/util" "1.9.3" tslib "^2.1.0" "@firebase/messaging-interop-types@0.2.0": @@ -2091,28 +2040,28 @@ resolved "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.0.tgz#6056f8904a696bf0f7fdcf5f2ca8f008e8f6b064" integrity sha512-ujA8dcRuVeBixGR9CtegfpU4YmZf3Lt7QYkcj693FFannwNuZgfAYaTmbJ40dtjB81SAu6tbFPL9YLNT15KmOQ== -"@firebase/messaging@0.12.3": - version "0.12.3" - resolved "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.3.tgz#3fd521e31deb9b81ec6316062deb1dcc8198d038" - integrity sha512-a3ZKcGDiV2sKmQDB56PpgL1yjFxXCtff2+v1grnAZZ4GnfNQ74t2EHCbmgY7xRX7ThzMqug54oxhuk4ur0MIoA== +"@firebase/messaging@0.12.4": + version "0.12.4" + resolved "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.4.tgz#ccb49df5ab97d5650c9cf5b8c77ddc34daafcfe0" + integrity sha512-6JLZct6zUaex4g7HI3QbzeUrg9xcnmDAPTWpkoMpd/GoSVWH98zDoWXMGrcvHeCAIsLpFMe4MPoZkJbrPhaASw== dependencies: - "@firebase/component" "0.6.3" - "@firebase/installations" "0.6.3" + "@firebase/component" "0.6.4" + "@firebase/installations" "0.6.4" "@firebase/messaging-interop-types" "0.2.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" idb "7.0.1" tslib "^2.1.0" -"@firebase/performance-compat@0.2.3": - version "0.2.3" - resolved "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.3.tgz#f3939bedc2017a95772fde64a72e97fe4b184268" - integrity sha512-I3rqZsIhauXn4iApfj1ttKQdlti/r8OZBG4YK10vxKSdhAzTIDWDKEsdoCXvvKLwplcMv36sM3WPAPGQLqY5MQ== +"@firebase/performance-compat@0.2.4": + version "0.2.4" + resolved "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.4.tgz#95cbf32057b5d9f0c75d804bc50e6ed3ba486274" + integrity sha512-nnHUb8uP9G8islzcld/k6Bg5RhX62VpbAb/Anj7IXs/hp32Eb2LqFPZK4sy3pKkBUO5wcrlRWQa6wKOxqlUqsg== dependencies: - "@firebase/component" "0.6.3" + "@firebase/component" "0.6.4" "@firebase/logger" "0.4.0" - "@firebase/performance" "0.6.3" + "@firebase/performance" "0.6.4" "@firebase/performance-types" "0.2.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" tslib "^2.1.0" "@firebase/performance-types@0.2.0": @@ -2120,27 +2069,27 @@ resolved "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.0.tgz#400685f7a3455970817136d9b48ce07a4b9562ff" integrity sha512-kYrbr8e/CYr1KLrLYZZt2noNnf+pRwDq2KK9Au9jHrBMnb0/C9X9yWSXmZkFt4UIdsQknBq8uBB7fsybZdOBTA== -"@firebase/performance@0.6.3": - version "0.6.3" - resolved "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.3.tgz#663c468dc4d62b6e211938377e21a01854803646" - integrity sha512-NQmQN6Ete7i9jz1mzULJZEGvsOmwwdUy6vpqnhUxSFMYPnlBKjX+yypCUUJDDN5zff5+kfwSD1qCyUAaS0xWUA== +"@firebase/performance@0.6.4": + version "0.6.4" + resolved "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.4.tgz#0ad766bfcfab4f386f4fe0bef43bbcf505015069" + integrity sha512-HfTn/bd8mfy/61vEqaBelNiNnvAbUtME2S25A67Nb34zVuCSCRIX4SseXY6zBnOFj3oLisaEqhVcJmVPAej67g== dependencies: - "@firebase/component" "0.6.3" - "@firebase/installations" "0.6.3" + "@firebase/component" "0.6.4" + "@firebase/installations" "0.6.4" "@firebase/logger" "0.4.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" tslib "^2.1.0" -"@firebase/remote-config-compat@0.2.3": - version "0.2.3" - resolved "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.3.tgz#b0c0ef9978186bc58b262a39b9a41ec1bf819df3" - integrity sha512-w/ZL03YgYaXq03xIRyJ5oPhXZi6iDsY/v0J9Y7I7SqxCYytEnHVrL9nvBqd9R94y5LRAVNPCLokJeeizaUz4VQ== +"@firebase/remote-config-compat@0.2.4": + version "0.2.4" + resolved "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.4.tgz#1f494c81a6c9560b1f9ca1b4fbd4bbbe47cf4776" + integrity sha512-FKiki53jZirrDFkBHglB3C07j5wBpitAaj8kLME6g8Mx+aq7u9P7qfmuSRytiOItADhWUj7O1JIv7n9q87SuwA== dependencies: - "@firebase/component" "0.6.3" + "@firebase/component" "0.6.4" "@firebase/logger" "0.4.0" - "@firebase/remote-config" "0.4.3" + "@firebase/remote-config" "0.4.4" "@firebase/remote-config-types" "0.3.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" tslib "^2.1.0" "@firebase/remote-config-types@0.3.0": @@ -2148,26 +2097,26 @@ resolved "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.0.tgz#689900dcdb3e5c059e8499b29db393e4e51314b4" integrity sha512-RtEH4vdcbXZuZWRZbIRmQVBNsE7VDQpet2qFvq6vwKLBIQRQR5Kh58M4ok3A3US8Sr3rubYnaGqZSurCwI8uMA== -"@firebase/remote-config@0.4.3": - version "0.4.3" - resolved "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.3.tgz#85c4934d093a4c7b8a336af70ada83e936347a2b" - integrity sha512-Q6d4jBWZoNt6SYq87bjtDGUHFkKwAmGnNjWyRjl14AZqE1ilgd9NZHmutharlYJ3LvxMsid80HdK5SgGEpIPfg== +"@firebase/remote-config@0.4.4": + version "0.4.4" + resolved "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.4.tgz#6a496117054de58744bc9f382d2a6d1e14060c65" + integrity sha512-x1ioTHGX8ZwDSTOVp8PBLv2/wfwKzb4pxi0gFezS5GCJwbLlloUH4YYZHHS83IPxnua8b6l0IXUaWd0RgbWwzQ== dependencies: - "@firebase/component" "0.6.3" - "@firebase/installations" "0.6.3" + "@firebase/component" "0.6.4" + "@firebase/installations" "0.6.4" "@firebase/logger" "0.4.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" tslib "^2.1.0" -"@firebase/storage-compat@0.3.1": - version "0.3.1" - resolved "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.1.tgz#b8536c3a435f8ce5eb07796ca10fda16896a9bae" - integrity sha512-6HaTvWsT5Yy3j4UpCZpMcFUYEkJ2XYWukdyTl02u6VjSBRLvkhOXPzEfMvgVWqhnF/rYVfPdjrZ904wk5OxtmQ== +"@firebase/storage-compat@0.3.2": + version "0.3.2" + resolved "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.2.tgz#51a97170fd652a516f729f82b97af369e5a2f8d7" + integrity sha512-wvsXlLa9DVOMQJckbDNhXKKxRNNewyUhhbXev3t8kSgoCotd1v3MmqhKKz93ePhDnhHnDs7bYHy+Qa8dRY6BXw== dependencies: - "@firebase/component" "0.6.3" - "@firebase/storage" "0.11.1" + "@firebase/component" "0.6.4" + "@firebase/storage" "0.11.2" "@firebase/storage-types" "0.8.0" - "@firebase/util" "1.9.2" + "@firebase/util" "1.9.3" tslib "^2.1.0" "@firebase/storage-types@0.8.0": @@ -2175,27 +2124,27 @@ resolved "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.0.tgz#f1e40a5361d59240b6e84fac7fbbbb622bfaf707" integrity sha512-isRHcGrTs9kITJC0AVehHfpraWFui39MPaU7Eo8QfWlqW7YPymBmRgjDrlOgFdURh6Cdeg07zmkLP5tzTKRSpg== -"@firebase/storage@0.11.1": - version "0.11.1" - resolved "https://registry.npmjs.org/@firebase/storage/-/storage-0.11.1.tgz#602ddb7bce77077800a46bcdfa76f36d7a265c51" - integrity sha512-Xv8EG2j52ugF2xayBz26U9J0VBXHXPMVxSN+ph3R3BSoHxvMLaPu+qUYKHavSt+zbcgPH2GyBhrCdJK6SaDFPA== +"@firebase/storage@0.11.2": + version "0.11.2" + resolved "https://registry.npmjs.org/@firebase/storage/-/storage-0.11.2.tgz#c5e0316543fe1c4026b8e3910f85ad73f5b77571" + integrity sha512-CtvoFaBI4hGXlXbaCHf8humajkbXhs39Nbh6MbNxtwJiCqxPy9iH3D3CCfXAvP0QvAAwmJUTK3+z9a++Kc4nkA== dependencies: - "@firebase/component" "0.6.3" - "@firebase/util" "1.9.2" + "@firebase/component" "0.6.4" + "@firebase/util" "1.9.3" node-fetch "2.6.7" tslib "^2.1.0" -"@firebase/util@1.9.2": - version "1.9.2" - resolved "https://registry.npmjs.org/@firebase/util/-/util-1.9.2.tgz#f5e9e393c5bae3547b9c823ee12076be1e23b1e2" - integrity sha512-9l0uMGPGw3GsoD5khjMmYCCcMq/OR/OOSViiWMN+s2Q0pxM+fYzrii1H+r8qC/uoMjSVXomjLZt0vZIyryCqtQ== +"@firebase/util@1.9.3": + version "1.9.3" + resolved "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz#45458dd5cd02d90e55c656e84adf6f3decf4b7ed" + integrity sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA== dependencies: tslib "^2.1.0" -"@firebase/webchannel-wrapper@0.9.0": - version "0.9.0" - resolved "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.9.0.tgz#9340bce56560a8bdba1d25d6281d4bfc397450dc" - integrity sha512-BpiZLBWdLFw+qFel9p3Zs1jD6QmH7Ii4aTDu6+vx8ShdidChZUXqDhYJly4ZjSgQh54miXbBgBrk0S+jTIh/Qg== +"@firebase/webchannel-wrapper@0.10.1": + version "0.10.1" + resolved "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.10.1.tgz#60bb2aaf129f9e00621f8d698722ddba6ee1f8ac" + integrity sha512-Dq5rYfEpdeel0bLVN+nfD1VWmzCkK+pJbSjIawGE+RY4+NIJqhbUDDQjvV0NUK84fMfwxvtFoCtEe70HfZjFcw== "@grpc/grpc-js@~1.7.0": version "1.7.3" @@ -2232,50 +2181,42 @@ resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jridgewell/gen-mapping@^0.1.0": - version "0.1.1" - resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" - integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/gen-mapping@^0.3.2": - version "0.3.2" - resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== dependencies: - "@jridgewell/set-array" "^1.0.1" + "@jridgewell/set-array" "^1.2.1" "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/resolve-uri@^3.0.3": - version "3.0.7" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" - integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== - -"@jridgewell/set-array@^1.0.0": - version "1.1.1" - resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea" - integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ== +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.13" resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.10" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.10.tgz#db436f0917d655393851bc258918c00226c9b183" - integrity sha512-Q0YbBd6OTsXm8Y21+YUSDXupHnodNC2M4O18jtd3iwJ3+vMZNdKGols0a9G6JOK0dcJ3IdUUHoh908ZI6qhk8Q== +"@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" @@ -2355,10 +2296,10 @@ dependencies: "@types/node" "*" -"@types/chai@4.3.4": - version "4.3.4" - resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" - integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== +"@types/chai@4.3.14": + version "4.3.14" + resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz#ae3055ea2be43c91c9fd700a36d67820026d96e6" + integrity sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w== "@types/component-emitter@^1.2.10": version "1.2.10" @@ -2773,9 +2714,9 @@ ansi-html-community@^0.0.8: integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== ansi-regex@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" - integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + version "5.0.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-styles@^3.2.1: version "3.2.1" @@ -2814,6 +2755,15 @@ array-flatten@^2.1.2: resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== +asn1.js@^4.10.1: + version "4.10.1" + resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + asn1.js@^5.2.0: version "5.4.1" resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" @@ -2840,19 +2790,19 @@ assertion-error@^1.1.0: integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== async@^3.0.1: - version "3.2.0" - resolved "https://registry.npmjs.org/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720" - integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw== + version "3.2.5" + resolved "https://registry.npmjs.org/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66" + integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg== available-typed-arrays@^1.0.2: version "1.0.4" resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz#9e0ae84ecff20caae6a94a1c3bc39b955649b7a9" integrity sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA== -babel-loader@8.2.5: - version "8.2.5" - resolved "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.5.tgz#d45f585e654d5a5d90f5350a779d7647c5ed512e" - integrity sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ== +babel-loader@8.3.0: + version "8.3.0" + resolved "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz#124936e841ba4fe8176786d6ff28add1f134d6a8" + integrity sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q== dependencies: find-cache-dir "^3.3.1" loader-utils "^2.0.0" @@ -2875,14 +2825,14 @@ babel-plugin-polyfill-corejs2@^0.2.2: "@babel/helper-define-polyfill-provider" "^0.2.2" semver "^6.1.1" -babel-plugin-polyfill-corejs2@^0.3.3: - version "0.3.3" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" - integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== +babel-plugin-polyfill-corejs2@^0.4.5: + version "0.4.10" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz#276f41710b03a64f6467433cab72cbc2653c38b1" + integrity sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ== dependencies: - "@babel/compat-data" "^7.17.7" - "@babel/helper-define-polyfill-provider" "^0.3.3" - semver "^6.1.1" + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.6.1" + semver "^6.3.1" babel-plugin-polyfill-corejs3@^0.2.2: version "0.2.3" @@ -2892,13 +2842,13 @@ babel-plugin-polyfill-corejs3@^0.2.2: "@babel/helper-define-polyfill-provider" "^0.2.2" core-js-compat "^3.14.0" -babel-plugin-polyfill-corejs3@^0.6.0: - version "0.6.0" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" - integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== +babel-plugin-polyfill-corejs3@^0.8.3: + version "0.8.7" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz#941855aa7fdaac06ed24c730a93450d2b2b76d04" + integrity sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.3" - core-js-compat "^3.25.1" + "@babel/helper-define-polyfill-provider" "^0.4.4" + core-js-compat "^3.33.1" babel-plugin-polyfill-regenerator@^0.2.2: version "0.2.2" @@ -2907,12 +2857,12 @@ babel-plugin-polyfill-regenerator@^0.2.2: dependencies: "@babel/helper-define-polyfill-provider" "^0.2.2" -babel-plugin-polyfill-regenerator@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" - integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== +babel-plugin-polyfill-regenerator@^0.5.2: + version "0.5.5" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz#8b0c8fc6434239e5d7b8a9d1f832bb2b0310f06a" + integrity sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.3" + "@babel/helper-define-polyfill-provider" "^0.5.0" balanced-match@^1.0.0: version "1.0.2" @@ -2949,11 +2899,16 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.1.1: +bn.js@^5.0.0: version "5.2.0" resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + body-parser@1.20.0: version "1.20.0" resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" @@ -3030,7 +2985,7 @@ browser-stdout@1.3.1: resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -browserify-aes@^1.0.0, browserify-aes@^1.0.4: +browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== @@ -3061,7 +3016,7 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: +browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== @@ -3070,19 +3025,20 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: randombytes "^2.0.1" browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + version "4.2.3" + resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz#7afe4c01ec7ee59a89a558a4b75bd85ae62d4208" + integrity sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw== dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" + bn.js "^5.2.1" + browserify-rsa "^4.1.0" create-hash "^1.2.0" create-hmac "^1.1.7" - elliptic "^6.5.3" + elliptic "^6.5.5" + hash-base "~3.0" inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" + parse-asn1 "^5.1.7" + readable-stream "^2.3.8" + safe-buffer "^5.2.1" browserify-zlib@^0.2.0: version "0.2.0" @@ -3102,26 +3058,15 @@ browserslist@^4.14.5, browserslist@^4.16.6: escalade "^3.1.1" node-releases "^1.1.71" -browserslist@^4.20.2: - version "4.20.3" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz#eb7572f49ec430e054f56d52ff0ebe9be915f8bf" - integrity sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg== - dependencies: - caniuse-lite "^1.0.30001332" - electron-to-chromium "^1.4.118" - escalade "^3.1.1" - node-releases "^2.0.3" - picocolors "^1.0.0" - -browserslist@^4.21.3, browserslist@^4.21.4: - version "4.21.5" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" - integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== +browserslist@^4.22.2, browserslist@^4.22.3: + version "4.23.0" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" + integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== dependencies: - caniuse-lite "^1.0.30001449" - electron-to-chromium "^1.4.284" - node-releases "^2.0.8" - update-browserslist-db "^1.0.10" + caniuse-lite "^1.0.30001587" + electron-to-chromium "^1.4.668" + node-releases "^2.0.14" + update-browserslist-db "^1.0.13" buffer-from@^1.0.0: version "1.1.1" @@ -3179,30 +3124,25 @@ caniuse-lite@^1.0.30001219: resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001245.tgz#45b941bbd833cb0fa53861ff2bae746b3c6ca5d4" integrity sha512-768fM9j1PKXpOCKws6eTo3RHmvTUsG9UrpT4WoREFeZgJBTi4/X9g565azS/rVUGtqb8nt7FjLeF5u4kukERnA== -caniuse-lite@^1.0.30001332: - version "1.0.30001339" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001339.tgz#f9aece4ea8156071613b27791547ba0b33f176cf" - integrity sha512-Es8PiVqCe+uXdms0Gu5xP5PF2bxLR7OBp3wUzUnuO7OHzhOfCyg3hdiGWVPVxhiuniOzng+hTc1u3fEQ0TlkSQ== - -caniuse-lite@^1.0.30001449: - version "1.0.30001449" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001449.tgz#a8d11f6a814c75c9ce9d851dc53eb1d1dfbcd657" - integrity sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw== +caniuse-lite@^1.0.30001587: + version "1.0.30001597" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001597.tgz#8be94a8c1d679de23b22fbd944232aa1321639e6" + integrity sha512-7LjJvmQU6Sj7bL0j5b5WY/3n7utXUJvAe1lxhsHDbLmwX9mdL86Yjtr+5SRCyf8qME4M7pU2hswj0FpyBVCv9w== -chai@4.3.7: - version "4.3.7" - resolved "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" - integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== +chai@4.4.1: + version "4.4.1" + resolved "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz#3603fa6eba35425b0f2ac91a009fe924106e50d1" + integrity sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g== dependencies: assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^4.1.2" - get-func-name "^2.0.0" - loupe "^2.3.1" + check-error "^1.0.3" + deep-eql "^4.1.3" + get-func-name "^2.0.2" + loupe "^2.3.6" pathval "^1.1.1" - type-detect "^4.0.5" + type-detect "^4.0.8" -chalk@^2.0.0: +chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3219,10 +3159,12 @@ chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= +check-error@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" + integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== + dependencies: + get-func-name "^2.0.2" chokidar@3.5.3, chokidar@^3.5.3: version "3.5.3" @@ -3428,6 +3370,11 @@ convert-source-map@^1.7.0: dependencies: safe-buffer "~5.1.1" +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + convert-source-map@~1.1.0: version "1.1.3" resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860" @@ -3456,12 +3403,12 @@ core-js-compat@^3.14.0, core-js-compat@^3.15.0: browserslist "^4.16.6" semver "7.0.0" -core-js-compat@^3.25.1: - version "3.27.2" - resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.27.2.tgz#607c50ad6db8fd8326af0b2883ebb987be3786da" - integrity sha512-welaYuF7ZtbYKGrIy7y3eb40d37rG1FvzEOfe7hSLd2iD6duMDqUhRfSvCGyC46HhR6Y8JXXdZ2lnRUMkPBpvg== +core-js-compat@^3.31.0, core-js-compat@^3.33.1: + version "3.36.0" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz#087679119bc2fdbdefad0d45d8e5d307d45ba190" + integrity sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw== dependencies: - browserslist "^4.21.4" + browserslist "^4.22.3" core-util-is@~1.0.0: version "1.0.2" @@ -3562,12 +3509,19 @@ debug@4.3.3, debug@^4.1.0, debug@^4.1.1, debug@^4.3.3, debug@~4.3.1, debug@~4.3. dependencies: ms "2.1.2" +debug@^4.3.1: + version "4.3.4" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + decamelize@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== -deep-eql@^4.1.2: +deep-eql@^4.1.3: version "4.1.3" resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== @@ -3689,15 +3643,10 @@ electron-to-chromium@^1.3.723: resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.775.tgz#046517d1f2cea753e06fff549995b9dc45e20082" integrity sha512-EGuiJW4yBPOTj2NtWGZcX93ZE8IGj33HJAx4d3ouE2zOfW2trbWU+t1e0yzLr1qQIw81++txbM3BH52QwSRE6Q== -electron-to-chromium@^1.4.118: - version "1.4.137" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz#186180a45617283f1c012284458510cd99d6787f" - integrity sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA== - -electron-to-chromium@^1.4.284: - version "1.4.284" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" - integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== +electron-to-chromium@^1.4.668: + version "1.4.705" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.705.tgz#ef4f912620bd7c9555a20554ffc568184c0ddceb" + integrity sha512-LKqhpwJCLhYId2VVwEzFXWrqQI5n5zBppz1W9ehhTlfYU8CUUW6kClbN8LHF/v7flMgRdETS772nqywJ+ckVAw== elliptic@^6.5.3: version "6.5.4" @@ -3712,6 +3661,19 @@ elliptic@^6.5.3: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +elliptic@^6.5.5: + version "6.5.5" + resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.5.tgz#c715e09f78b6923977610d4c2346d6ce22e6dded" + integrity sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -4019,37 +3981,37 @@ find-up@^4.0.0: locate-path "^5.0.0" path-exists "^4.0.0" -firebase@9.17.1: - version "9.17.1" - resolved "https://registry.npmjs.org/firebase/-/firebase-9.17.1.tgz#91c56fe9d9bf5ed1c405030e4fe8133c6069fd40" - integrity sha512-MSZaTRaaRLgDFLqoEnoPYK8zkLwQNvYeLZ3YSKdcQxG8hDifNO22ywS1cSA1ZCGHlQeOsDtfDwBejKcANf/RQw== - dependencies: - "@firebase/analytics" "0.9.3" - "@firebase/analytics-compat" "0.2.3" - "@firebase/app" "0.9.3" - "@firebase/app-check" "0.6.3" - "@firebase/app-check-compat" "0.3.3" - "@firebase/app-compat" "0.2.3" +firebase@9.23.0: + version "9.23.0" + resolved "https://registry.npmjs.org/firebase/-/firebase-9.23.0.tgz#71fea60d704bfed8e92162911544fd6564a04d0e" + integrity sha512-/4lUVY0lUvBDIaeY1q6dUYhS8Sd18Qb9CgWkPZICUo9IXpJNCEagfNZXBBFCkMTTN5L5gx2Hjr27y21a9NzUcA== + dependencies: + "@firebase/analytics" "0.10.0" + "@firebase/analytics-compat" "0.2.6" + "@firebase/app" "0.9.13" + "@firebase/app-check" "0.8.0" + "@firebase/app-check-compat" "0.3.7" + "@firebase/app-compat" "0.2.13" "@firebase/app-types" "0.9.0" - "@firebase/auth" "0.21.3" - "@firebase/auth-compat" "0.3.3" - "@firebase/database" "0.14.3" - "@firebase/database-compat" "0.3.3" - "@firebase/firestore" "3.8.3" - "@firebase/firestore-compat" "0.3.3" - "@firebase/functions" "0.9.3" - "@firebase/functions-compat" "0.3.3" - "@firebase/installations" "0.6.3" - "@firebase/installations-compat" "0.2.3" - "@firebase/messaging" "0.12.3" - "@firebase/messaging-compat" "0.2.3" - "@firebase/performance" "0.6.3" - "@firebase/performance-compat" "0.2.3" - "@firebase/remote-config" "0.4.3" - "@firebase/remote-config-compat" "0.2.3" - "@firebase/storage" "0.11.1" - "@firebase/storage-compat" "0.3.1" - "@firebase/util" "1.9.2" + "@firebase/auth" "0.23.2" + "@firebase/auth-compat" "0.4.2" + "@firebase/database" "0.14.4" + "@firebase/database-compat" "0.3.4" + "@firebase/firestore" "3.13.0" + "@firebase/firestore-compat" "0.3.12" + "@firebase/functions" "0.10.0" + "@firebase/functions-compat" "0.3.5" + "@firebase/installations" "0.6.4" + "@firebase/installations-compat" "0.2.4" + "@firebase/messaging" "0.12.4" + "@firebase/messaging-compat" "0.2.4" + "@firebase/performance" "0.6.4" + "@firebase/performance-compat" "0.2.4" + "@firebase/remote-config" "0.4.4" + "@firebase/remote-config-compat" "0.2.4" + "@firebase/storage" "0.11.2" + "@firebase/storage-compat" "0.3.2" + "@firebase/util" "1.9.3" flat@^5.0.2: version "5.0.2" @@ -4067,9 +4029,9 @@ flatted@^3.2.5: integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== follow-redirects@^1.0.0: - version "1.14.1" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43" - integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg== + version "1.15.6" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== foreach@^2.0.5: version "2.0.5" @@ -4104,10 +4066,10 @@ fs-extra@^10.0.1: jsonfile "^6.0.1" universalify "^2.0.0" -fs-monkey@1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" - integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== +fs-monkey@^1.0.4: + version "1.0.5" + resolved "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz#fe450175f0db0d7ea758102e1d84096acb925788" + integrity sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew== fs.realpath@^1.0.0: version "1.0.0" @@ -4134,10 +4096,10 @@ get-caller-file@^2.0.5: resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= +get-func-name@^2.0.1, get-func-name@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: version "1.1.1" @@ -4255,6 +4217,14 @@ hash-base@^3.0.0: readable-stream "^3.6.0" safe-buffer "^5.2.0" +hash-base@~3.0: + version "3.0.4" + resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" @@ -4381,6 +4351,11 @@ idb@7.0.1: resolved "https://registry.npmjs.org/idb/-/idb-7.0.1.tgz#d2875b3a2f205d854ee307f6d196f246fea590a7" integrity sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg== +idb@7.1.1: + version "7.1.1" + resolved "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b" + integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ== + ieee754@^1.1.13: version "1.2.1" resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -4711,10 +4686,10 @@ json5@^2.1.2: dependencies: minimist "^1.2.5" -json5@^2.2.1: - version "2.2.1" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonfile@^6.0.1: version "6.1.0" @@ -4725,10 +4700,10 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -karma-chrome-launcher@3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz#baca9cc071b1562a1db241827257bfe5cab597ea" - integrity sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ== +karma-chrome-launcher@3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz#eb9c95024f2d6dfbb3748d3415ac9b381906b9a9" + integrity sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q== dependencies: which "^1.2.1" @@ -4739,17 +4714,17 @@ karma-mocha@2.0.1: dependencies: minimist "^1.2.3" -karma-spec-reporter@0.0.34: - version "0.0.34" - resolved "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.34.tgz#7dc79cdc76b0e37f17006921439600ae3c648669" - integrity sha512-l5H/Nh9q4g2Ysx2CDU2m+NIPyLQpCVbk9c4V02BTZHw3NM6RO1dq3eRpKXCSSdPt4RGfhHk8jDt3XYkGp+5PWg== +karma-spec-reporter@0.0.36: + version "0.0.36" + resolved "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.36.tgz#c54dc155dec2ded1f92ea68dbbdd67fcedbef350" + integrity sha512-11bvOl1x6ryKZph7kmbmMpbi8vsngEGxGOoeTlIcDaH3ab3j8aPJnZ+r+K/SS0sBSGy5VGkGYO2+hLct7hw/6w== dependencies: colors "1.4.0" -karma-typescript-es6-transform@5.5.3: - version "5.5.3" - resolved "https://registry.npmjs.org/karma-typescript-es6-transform/-/karma-typescript-es6-transform-5.5.3.tgz#5396da512c20b69d49e3e362a41f250342da5c03" - integrity sha512-vB1Cv8z9yxyR2KQuvks5soNKASyS2RPApdMsB3Ad55RqFJeag9G+xyGIwxOdyCHtgOwa4yn1rngMwaN7WBQTbQ== +karma-typescript-es6-transform@5.5.4: + version "5.5.4" + resolved "https://registry.npmjs.org/karma-typescript-es6-transform/-/karma-typescript-es6-transform-5.5.4.tgz#bca1eb2f3ba50601c083fe6277ae6df0f7cdb7c8" + integrity sha512-SKUNU4cAxNgmJnF/zCAzMRnBaciQjFumSDrsf1j8TTJvAtwAk/tLM+hru88Dr4Q4SmFUFa+PzIK8NJmykQ2F7Q== dependencies: "@babel/core" "^7.11.1" "@babel/preset-env" "^7.11.0" @@ -4758,10 +4733,10 @@ karma-typescript-es6-transform@5.5.3: log4js "^6.3.0" magic-string "^0.25.7" -karma-typescript@5.5.3: - version "5.5.3" - resolved "https://registry.npmjs.org/karma-typescript/-/karma-typescript-5.5.3.tgz#29c04d9677f8bd78dfacd89e8fa6f475dd25aba2" - integrity sha512-l1FHurolXEBIzRa9ExpNtjzysAhsi/vLpTazpwLHWWK86mknvVpqor6pRZ5Nid7jvOPrTBqAq0JRuLgiCdRkFw== +karma-typescript@5.5.4: + version "5.5.4" + resolved "https://registry.npmjs.org/karma-typescript/-/karma-typescript-5.5.4.tgz#969871512b8476dfc7a496f48da9ca9c73d710e5" + integrity sha512-D7nQ96xu/UekuqCmiPimnCuOFqp8+BxiND6MU6IJVN37E7DgXzr7SUeTzwuTHtKSYpgxKv4iOTUteYTxpeZL9A== dependencies: acorn "^8.1.0" acorn-walk "^8.0.2" @@ -4807,10 +4782,10 @@ karma-typescript@5.5.3: util "^0.12.1" vm-browserify "^1.1.2" -karma@6.4.1: - version "6.4.1" - resolved "https://registry.npmjs.org/karma/-/karma-6.4.1.tgz#f2253716dd3a41aaa813fa9f54b6ee047e1127d9" - integrity sha512-Cj57NKOskK7wtFWSlMvZf459iX+kpYIPXmkNUzP2WAFcA7nhr/ALn5R7sw3w+1udFDcpMx/tuB8d5amgm3ijaA== +karma@6.4.2: + version "6.4.2" + resolved "https://registry.npmjs.org/karma/-/karma-6.4.2.tgz#a983f874cee6f35990c4b2dcc3d274653714de8e" + integrity sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ== dependencies: "@colors/colors" "1.5.0" body-parser "^1.19.0" @@ -4930,12 +4905,12 @@ long@^5.0.0: resolved "https://registry.npmjs.org/long/-/long-5.2.1.tgz#e27595d0083d103d2fa2c20c7699f8e0c92b897f" integrity sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A== -loupe@^2.3.1: - version "2.3.4" - resolved "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" - integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== +loupe@^2.3.6: + version "2.3.7" + resolved "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" + integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== dependencies: - get-func-name "^2.0.0" + get-func-name "^2.0.1" lru-cache@^5.1.1: version "5.1.1" @@ -4972,12 +4947,12 @@ media-typer@0.3.0: resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -memfs@^3.4.1: - version "3.4.1" - resolved "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305" - integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw== +memfs@^3.4.3: + version "3.6.0" + resolved "https://registry.npmjs.org/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" + integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== dependencies: - fs-monkey "1.0.3" + fs-monkey "^1.0.4" merge-descriptors@1.0.1: version "1.0.1" @@ -5086,9 +5061,9 @@ minimatch@^3.0.4: brace-expansion "^1.1.7" minimist@^1.2.3, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + version "1.2.8" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== mkdirp@^0.5.5: version "0.5.5" @@ -5187,15 +5162,10 @@ node-releases@^1.1.71: resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20" integrity sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg== -node-releases@^2.0.3: - version "2.0.4" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz#f38252370c43854dc48aa431c766c6c398f40476" - integrity sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ== - -node-releases@^2.0.8: - version "2.0.9" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.9.tgz#fe66405285382b0c4ac6bcfbfbe7e8a510650b4d" - integrity sha512-2xfmOrRkGogbTK9R6Leda0DGiXeY3p2NJpy4+gNCffdUvV6mdEJnaDEic1i3Ec2djAo8jWYoJMR5PB0MSMpxUA== +node-releases@^2.0.14: + version "2.0.14" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" @@ -5352,7 +5322,7 @@ pako@~1.0.5: resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== -parse-asn1@^5.0.0, parse-asn1@^5.1.5: +parse-asn1@^5.0.0: version "5.1.6" resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== @@ -5363,6 +5333,18 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" +parse-asn1@^5.1.7: + version "5.1.7" + resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz#73cdaaa822125f9647165625eb45f8a051d2df06" + integrity sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg== + dependencies: + asn1.js "^4.10.1" + browserify-aes "^1.2.0" + evp_bytestokey "^1.0.3" + hash-base "~3.0" + pbkdf2 "^3.1.2" + safe-buffer "^5.2.1" + parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -5403,7 +5385,7 @@ pathval@^1.1.1: resolved "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -pbkdf2@^3.0.3: +pbkdf2@^3.0.3, pbkdf2@^3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== @@ -5447,9 +5429,9 @@ process@^0.11.10: integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= protobufjs@^6.11.3: - version "6.11.3" - resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz#637a527205a35caa4f3e2a9a4a13ddffe0e7af74" - integrity sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg== + version "6.11.4" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz#29a412c38bf70d89e537b6d02d904a6f448173aa" + integrity sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -5466,9 +5448,9 @@ protobufjs@^6.11.3: long "^4.0.0" protobufjs@^7.0.0: - version "7.2.2" - resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.2.tgz#2af401d8c547b9476fb37ffc65782cf302342ca3" - integrity sha512-++PrQIjrom+bFDPpfmqXfAGSQs40116JRrqqyf53dymUMvvb5d/LMRyicRoF1AUKoXVS1/IgJXlEgcpr4gTF3Q== + version "7.2.6" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz#4a0ccd79eb292717aacf07530a07e0ed20278215" + integrity sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -5593,6 +5575,19 @@ readable-stream@^2.0.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^2.3.8: + version "2.3.8" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + 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" + readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -5647,10 +5642,10 @@ regenerator-transform@^0.14.2: dependencies: "@babel/runtime" "^7.8.4" -regenerator-transform@^0.15.1: - version "0.15.1" - resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56" - integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg== +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== dependencies: "@babel/runtime" "^7.8.4" @@ -5678,6 +5673,18 @@ regexpu-core@^5.2.1: unicode-match-property-ecmascript "^2.0.0" unicode-match-property-value-ecmascript "^2.1.0" +regexpu-core@^5.3.1: + version "5.3.2" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== + dependencies: + "@babel/regjsgen" "^0.8.0" + regenerate "^1.4.2" + regenerate-unicode-properties "^10.1.0" + regjsparser "^0.9.1" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" + regjsgen@^0.5.1: version "0.5.2" resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" @@ -5767,7 +5774,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -5831,10 +5838,10 @@ semver@7.0.0: resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== send@0.18.0: version "0.18.0" @@ -6237,7 +6244,7 @@ tty-browserify@^0.0.1: resolved "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== -type-detect@^4.0.0, type-detect@^4.0.5: +type-detect@^4.0.0, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== @@ -6326,10 +6333,10 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= -update-browserslist-db@^1.0.10: - version "1.0.10" - resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" - integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== +update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== dependencies: escalade "^3.1.1" picocolors "^1.0.0" @@ -6437,12 +6444,12 @@ webpack-cli@4.10.0: webpack-merge "^5.7.3" webpack-dev-middleware@^5.3.1: - version "5.3.1" - resolved "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz#aa079a8dedd7e58bfeab358a9af7dab304cee57f" - integrity sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg== + version "5.3.4" + resolved "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz#eb7b39281cbce10e104eb2b8bf2b63fce49a3517" + integrity sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q== dependencies: colorette "^2.0.10" - memfs "^3.4.1" + memfs "^3.4.3" mime-types "^2.1.31" range-parser "^1.2.1" schema-utils "^4.0.0" diff --git a/integration/compat-interop/package.json b/integration/compat-interop/package.json index 559bb85903a..6015fd9be53 100644 --- a/integration/compat-interop/package.json +++ b/integration/compat-interop/package.json @@ -8,20 +8,20 @@ "test:debug": "karma start --browsers Chrome --auto-watch" }, "dependencies": { - "@firebase/app": "0.9.25", - "@firebase/app-compat": "0.2.25", - "@firebase/analytics": "0.10.0", - "@firebase/analytics-compat": "0.2.6", - "@firebase/auth": "1.5.1", - "@firebase/auth-compat": "0.5.1", - "@firebase/functions": "0.11.0", - "@firebase/functions-compat": "0.3.6", - "@firebase/messaging": "0.12.5", - "@firebase/messaging-compat": "0.2.5", - "@firebase/performance": "0.6.4", - "@firebase/performance-compat": "0.2.4", - "@firebase/remote-config": "0.4.4", - "@firebase/remote-config-compat": "0.2.4" + "@firebase/app": "0.10.2", + "@firebase/app-compat": "0.2.32", + "@firebase/analytics": "0.10.2", + "@firebase/analytics-compat": "0.2.8", + "@firebase/auth": "1.7.2", + "@firebase/auth-compat": "0.5.7", + "@firebase/functions": "0.11.4", + "@firebase/functions-compat": "0.3.10", + "@firebase/messaging": "0.12.8", + "@firebase/messaging-compat": "0.2.8", + "@firebase/performance": "0.6.6", + "@firebase/performance-compat": "0.2.6", + "@firebase/remote-config": "0.4.6", + "@firebase/remote-config-compat": "0.2.6" }, "devDependencies": { "typescript": "4.7.4" diff --git a/integration/firebase/package.json b/integration/firebase/package.json index 3a33089e5f7..5e107f6e28c 100644 --- a/integration/firebase/package.json +++ b/integration/firebase/package.json @@ -7,14 +7,14 @@ "test:ci": "node ../../scripts/run_tests_in_ci.js -s test" }, "devDependencies": { - "firebase": "10.7.1", - "@types/chai": "4.3.5", + "firebase": "10.11.1", + "@types/chai": "4.3.14", "@types/mocha": "9.1.1", - "chai": "4.3.7", + "chai": "4.4.1", "karma": "6.4.2", "karma-babel-preprocessor": "8.0.2", "karma-chrome-launcher": "3.2.0", - "karma-firefox-launcher": "2.1.2", + "karma-firefox-launcher": "2.1.3", "karma-mocha": "2.0.1", "karma-spec-reporter": "0.0.36", "karma-typescript": "5.5.4", diff --git a/integration/firestore/package.json b/integration/firestore/package.json index b98c3d8c6c2..a849f14b5b2 100644 --- a/integration/firestore/package.json +++ b/integration/firestore/package.json @@ -14,8 +14,8 @@ "test:memory:debug": "yarn build:memory; karma start --auto-watch --browsers Chrome" }, "dependencies": { - "@firebase/app": "0.9.25", - "@firebase/firestore": "4.4.0" + "@firebase/app": "0.10.2", + "@firebase/firestore": "4.6.1" }, "devDependencies": { "@types/mocha": "9.1.1", @@ -24,11 +24,11 @@ "gulp-replace": "1.1.4", "karma": "6.4.2", "karma-chrome-launcher": "3.2.0", - "karma-firefox-launcher": "2.1.2", + "karma-firefox-launcher": "2.1.3", "karma-mocha": "2.0.1", "karma-spec-reporter": "0.0.36", "mocha": "9.2.2", - "ts-loader": "8.4.0", + "ts-loader": "9.5.1", "typescript": "4.2.2", "webpack": "5.76.0", "webpack-stream": "7.0.0" diff --git a/integration/messaging/package.json b/integration/messaging/package.json index 16f150fb074..51ee047220f 100644 --- a/integration/messaging/package.json +++ b/integration/messaging/package.json @@ -9,13 +9,13 @@ "test:manual": "mocha --exit" }, "devDependencies": { - "firebase": "10.7.1", - "chai": "4.3.7", - "chromedriver": "114.0.2", - "express": "4.18.2", + "firebase": "10.11.1", + "chai": "4.4.1", + "chromedriver": "119.0.1", + "express": "4.19.2", "geckodriver": "2.0.4", "mocha": "9.2.2", - "undici": "5.26.5", + "undici": "5.28.4", "selenium-assistant": "6.1.1" } } diff --git a/package.json b/package.json index 1bda3af3eec..0f11f89a6ce 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "workspaces": [ "packages/*", @@ -60,38 +60,38 @@ "repo-scripts/*" ], "devDependencies": { - "@babel/core": "7.22.11", + "@babel/core": "7.24.3", "@babel/plugin-transform-modules-commonjs": "7.22.11", "@babel/preset-env": "7.22.10", "@babel/preset-typescript": "7.22.11", - "@babel/register": "7.22.5", + "@babel/register": "7.23.7", "@changesets/changelog-github": "0.4.8", "@changesets/cli": "2.26.2", - "@types/chai": "4.3.5", - "@types/chai-as-promised": "7.1.5", - "@types/child-process-promise": "2.2.2", + "@types/chai": "4.3.14", + "@types/chai-as-promised": "7.1.8", + "@types/child-process-promise": "2.2.6", "@types/clone": "2.1.1", "@types/eslint": "7.29.0", - "@types/inquirer": "8.2.6", - "@types/js-yaml": "4.0.5", - "@types/listr": "0.14.4", + "@types/inquirer": "8.2.10", + "@types/js-yaml": "4.0.9", + "@types/listr": "0.14.9", "@types/long": "4.0.2", "@types/mocha": "9.1.1", - "@types/mz": "2.7.4", + "@types/mz": "2.7.8", "@types/node": "16.18.68", - "@types/request": "2.48.8", + "@types/request": "2.48.12", "@types/sinon": "9.0.11", - "@types/sinon-chai": "3.2.9", - "@types/tmp": "0.2.3", - "@types/trusted-types": "2.0.3", - "@types/yargs": "17.0.24", + "@types/sinon-chai": "3.2.12", + "@types/tmp": "0.2.6", + "@types/trusted-types": "2.0.7", + "@types/yargs": "17.0.32", "@typescript-eslint/eslint-plugin": "5.62.0", "@typescript-eslint/eslint-plugin-tslint": "5.62.0", "@typescript-eslint/parser": "5.62.0", "api-documenter-me": "0.1.1", "api-extractor-me": "0.1.2", "babel-loader": "8.3.0", - "chai": "4.3.7", + "chai": "4.4.1", "chai-as-promised": "7.1.1", "chalk": "4.1.2", "child-process-promise": "2.2.1", @@ -102,7 +102,7 @@ "eslint": "7.32.0", "eslint-plugin-import": "2.26.0", "eslint-plugin-unused-imports": "2.0.0", - "express": "4.18.2", + "express": "4.19.2", "find-free-port": "2.0.0", "firebase-tools": "11.30.0", "glob": "7.2.3", @@ -115,12 +115,12 @@ "karma-chrome-launcher": "3.2.0", "karma-cli": "2.0.0", "karma-coverage-istanbul-reporter": "3.0.3", - "karma-firefox-launcher": "2.1.2", + "karma-firefox-launcher": "2.1.3", "karma-mocha": "2.0.1", "karma-mocha-reporter": "2.2.5", "karma-safari-launcher": "1.0.0", "karma-sourcemap-loader": "0.4.0", - "karma-spec-reporter": "0.0.34", + "karma-spec-reporter": "0.0.36", "karma-summary-reporter": "3.1.1", "karma-webpack": "5.0.0", "lcov-result-merger": "3.3.0", @@ -136,24 +136,24 @@ "npm-run-all": "4.1.5", "nyc": "15.1.0", "ora": "5.4.1", - "patch-package": "7.0.0", + "patch-package": "7.0.2", "postinstall-postinstall": "2.1.0", "prettier": "2.8.7", "protractor": "5.4.2", "request": "2.88.2", - "semver": "7.3.8", - "simple-git": "3.19.1", + "semver": "7.5.3", + "simple-git": "3.24.0", "sinon": "9.2.4", "sinon-chai": "3.7.0", "source-map-loader": "1.1.3", "sqlite3": "5.1.6", "terser": "5.16.1", - "ts-loader": "8.4.0", + "ts-loader": "9.5.1", "ts-node": "10.9.1", "tslint": "6.1.3", "typedoc": "0.16.11", "typescript": "4.7.4", - "undici": "5.26.5", + "undici": "5.28.4", "watch": "1.0.2", "webpack": "5.76.0", "yargs": "17.7.2" diff --git a/packages/analytics-compat/CHANGELOG.md b/packages/analytics-compat/CHANGELOG.md index 03d5fde24da..bf76437198c 100644 --- a/packages/analytics-compat/CHANGELOG.md +++ b/packages/analytics-compat/CHANGELOG.md @@ -1,5 +1,26 @@ # @firebase/analytics-compat +## 0.2.8 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/analytics-types@0.8.1 + - @firebase/analytics@0.10.2 + - @firebase/component@0.6.6 + - @firebase/util@1.9.5 + +## 0.2.7 + +### Patch Changes + +- Updated dependencies [[`bf59c0aed`](https://github.com/firebase/firebase-js-sdk/commit/bf59c0aedefabae9bff4d777e1591fe496259293), [`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/analytics@0.10.1 + - @firebase/util@1.9.4 + - @firebase/component@0.6.5 + ## 0.2.6 ### Patch Changes diff --git a/packages/analytics-compat/package.json b/packages/analytics-compat/package.json index 2f6e88757f8..c58b9d04571 100644 --- a/packages/analytics-compat/package.json +++ b/packages/analytics-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/analytics-compat", - "version": "0.2.6", + "version": "0.2.8", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -24,7 +24,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.2.25", + "@firebase/app-compat": "0.2.32", "rollup": "2.79.1", "@rollup/plugin-json": "4.1.0", "rollup-plugin-typescript2": "0.31.2", @@ -33,7 +33,7 @@ "repository": { "directory": "packages/analytics-compat", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" @@ -53,10 +53,10 @@ }, "typings": "dist/src/index.d.ts", "dependencies": { - "@firebase/component": "0.6.4", - "@firebase/analytics": "0.10.0", - "@firebase/analytics-types": "0.8.0", - "@firebase/util": "1.9.3", + "@firebase/component": "0.6.6", + "@firebase/analytics": "0.10.2", + "@firebase/analytics-types": "0.8.1", + "@firebase/util": "1.9.5", "tslib": "^2.1.0" }, "nyc": { diff --git a/packages/analytics-interop-types/CHANGELOG.md b/packages/analytics-interop-types/CHANGELOG.md index 6c01a4a0cc2..592e98d1285 100644 --- a/packages/analytics-interop-types/CHANGELOG.md +++ b/packages/analytics-interop-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/analytics-interop-types +## 0.3.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.3.0 ### Minor Changes diff --git a/packages/analytics-interop-types/package.json b/packages/analytics-interop-types/package.json index 23cafeb93b2..d6d5e9926de 100644 --- a/packages/analytics-interop-types/package.json +++ b/packages/analytics-interop-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/analytics-interop-types", - "version": "0.3.0", + "version": "0.3.1", "description": "@firebase/analytics Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -14,7 +14,7 @@ "repository": { "directory": "packages/analytics-interop-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/analytics-types/CHANGELOG.md b/packages/analytics-types/CHANGELOG.md index a11948e4114..7638c94460e 100644 --- a/packages/analytics-types/CHANGELOG.md +++ b/packages/analytics-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/analytics-types +## 0.8.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.8.0 ### Minor Changes diff --git a/packages/analytics-types/index.d.ts b/packages/analytics-types/index.d.ts index b502af099bd..9a9f27499ae 100644 --- a/packages/analytics-types/index.d.ts +++ b/packages/analytics-types/index.d.ts @@ -197,7 +197,7 @@ export interface FirebaseAnalytics { * automatically associates this logged event with this Firebase web * app instance on this device. * See - * {@link https://developers.google.com/analytics/devguides/collection/ga4/page-view + * {@link https://developers.google.com/analytics/devguides/collection/ga4/views * | Page views}. */ logEvent( diff --git a/packages/analytics-types/package.json b/packages/analytics-types/package.json index d90df40d77e..069bc03ecb1 100644 --- a/packages/analytics-types/package.json +++ b/packages/analytics-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/analytics-types", - "version": "0.8.0", + "version": "0.8.1", "description": "@firebase/analytics Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -14,7 +14,7 @@ "repository": { "directory": "packages/analytics-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/analytics/CHANGELOG.md b/packages/analytics/CHANGELOG.md index 81313900343..8094e5d0ef0 100644 --- a/packages/analytics/CHANGELOG.md +++ b/packages/analytics/CHANGELOG.md @@ -1,5 +1,28 @@ # @firebase/analytics +## 0.10.2 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/installations@0.6.6 + - @firebase/component@0.6.6 + - @firebase/logger@0.4.1 + - @firebase/util@1.9.5 + +## 0.10.1 + +### Patch Changes + +- [`bf59c0aed`](https://github.com/firebase/firebase-js-sdk/commit/bf59c0aedefabae9bff4d777e1591fe496259293) - Analytics - added two new consent options to the ConsentSettings interface: ad_personalization and ad_user_data. + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/installations@0.6.5 + - @firebase/component@0.6.5 + ## 0.10.0 ### Minor Changes diff --git a/packages/analytics/package.json b/packages/analytics/package.json index a1d44677ec9..126ebe2e042 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/analytics", - "version": "0.10.0", + "version": "0.10.2", "description": "A analytics package for new firebase packages", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -40,15 +40,15 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.4", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.3", - "@firebase/component": "0.6.4", + "@firebase/installations": "0.6.6", + "@firebase/logger": "0.4.1", + "@firebase/util": "1.9.5", + "@firebase/component": "0.6.6", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.9.25", + "@firebase/app": "0.10.2", "rollup": "2.79.1", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "4.1.0", @@ -59,7 +59,7 @@ "repository": { "directory": "packages/analytics", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/analytics/src/api.ts b/packages/analytics/src/api.ts index f44cbad2de9..baf136b3e35 100644 --- a/packages/analytics/src/api.ts +++ b/packages/analytics/src/api.ts @@ -441,7 +441,7 @@ export function logEvent( * app instance on this device. * @public * See - * {@link https://developers.google.com/analytics/devguides/collection/ga4/page-view + * {@link https://developers.google.com/analytics/devguides/collection/ga4/views * | Page views}. */ export function logEvent( diff --git a/packages/analytics/src/public-types.ts b/packages/analytics/src/public-types.ts index 930ba17b1eb..188f3c097e7 100644 --- a/packages/analytics/src/public-types.ts +++ b/packages/analytics/src/public-types.ts @@ -27,17 +27,17 @@ export interface GtagConfigParams { * Whether or not a page view should be sent. * If set to true (default), a page view is automatically sent upon initialization * of analytics. - * See {@link https://developers.google.com/analytics/devguides/collection/ga4/page-view | Page views } + * See {@link https://developers.google.com/analytics/devguides/collection/ga4/views | Page views } */ 'send_page_view'?: boolean; /** * The title of the page. - * See {@link https://developers.google.com/analytics/devguides/collection/ga4/page-view | Page views } + * See {@link https://developers.google.com/analytics/devguides/collection/ga4/views | Page views } */ 'page_title'?: string; /** * The URL of the page. - * See {@link https://developers.google.com/analytics/devguides/collection/ga4/page-view | Page views } + * See {@link https://developers.google.com/analytics/devguides/collection/ga4/views | Page views } */ 'page_location'?: string; /** @@ -299,6 +299,10 @@ export interface EventParams { export interface ConsentSettings { /** Enables storage, such as cookies, related to advertising */ ad_storage?: ConsentStatusString; + /** Sets consent for sending user data to Google for advertising purposes. */ + ad_user_data?: ConsentStatusString; + /** Sets consent for personalized advertising. */ + ad_personalization?: ConsentStatusString; /** Enables storage, such as cookies, related to analytics (for example, visit duration) */ analytics_storage?: ConsentStatusString; /** diff --git a/packages/app-check-compat/CHANGELOG.md b/packages/app-check-compat/CHANGELOG.md index dd898c13b20..29148f5f78a 100644 --- a/packages/app-check-compat/CHANGELOG.md +++ b/packages/app-check-compat/CHANGELOG.md @@ -1,5 +1,27 @@ # @firebase/app-check-compat +## 0.3.10 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/app-check-types@0.5.1 + - @firebase/app-check@0.8.3 + - @firebase/component@0.6.6 + - @firebase/logger@0.4.1 + - @firebase/util@1.9.5 + +## 0.3.9 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/app-check@0.8.2 + - @firebase/component@0.6.5 + ## 0.3.8 ### Patch Changes diff --git a/packages/app-check-compat/package.json b/packages/app-check-compat/package.json index 9edaed90a5d..4451258c4c5 100644 --- a/packages/app-check-compat/package.json +++ b/packages/app-check-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-check-compat", - "version": "0.3.8", + "version": "0.3.10", "description": "A compat App Check package for new firebase packages", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -35,16 +35,16 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/app-check": "0.8.1", - "@firebase/app-check-types": "0.5.0", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.3", - "@firebase/component": "0.6.4", + "@firebase/app-check": "0.8.3", + "@firebase/app-check-types": "0.5.1", + "@firebase/logger": "0.4.1", + "@firebase/util": "1.9.5", + "@firebase/component": "0.6.6", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.2.25", + "@firebase/app-compat": "0.2.32", "rollup": "2.79.1", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "4.1.0", @@ -55,7 +55,7 @@ "repository": { "directory": "packages/app-check", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/app-check-interop-types/CHANGELOG.md b/packages/app-check-interop-types/CHANGELOG.md index e0b0bdfe571..9aad6372e88 100644 --- a/packages/app-check-interop-types/CHANGELOG.md +++ b/packages/app-check-interop-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/app-check-interop-types +## 0.3.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.3.0 ### Minor Changes diff --git a/packages/app-check-interop-types/package.json b/packages/app-check-interop-types/package.json index 59fa4c24e73..3c498ef4117 100644 --- a/packages/app-check-interop-types/package.json +++ b/packages/app-check-interop-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-check-interop-types", - "version": "0.3.0", + "version": "0.3.1", "description": "@firebase/app-check-interop-types Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -14,7 +14,7 @@ "repository": { "directory": "packages/app-check-interop-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/app-check-types/CHANGELOG.md b/packages/app-check-types/CHANGELOG.md index c45f6e88f40..b44b1d20f59 100644 --- a/packages/app-check-types/CHANGELOG.md +++ b/packages/app-check-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/app-check-types +## 0.5.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.5.0 ### Minor Changes diff --git a/packages/app-check-types/package.json b/packages/app-check-types/package.json index 0ad29af290a..0507bdb7d54 100644 --- a/packages/app-check-types/package.json +++ b/packages/app-check-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-check-types", - "version": "0.5.0", + "version": "0.5.1", "description": "@firebase/app-check Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -14,7 +14,7 @@ "repository": { "directory": "packages/app-check-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/app-check/CHANGELOG.md b/packages/app-check/CHANGELOG.md index 50987b1c78b..41fc7627fa9 100644 --- a/packages/app-check/CHANGELOG.md +++ b/packages/app-check/CHANGELOG.md @@ -1,5 +1,24 @@ # @firebase/app-check +## 0.8.3 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/component@0.6.6 + - @firebase/logger@0.4.1 + - @firebase/util@1.9.5 + +## 0.8.2 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/component@0.6.5 + ## 0.8.1 ### Patch Changes diff --git a/packages/app-check/package.json b/packages/app-check/package.json index f8028e23d44..1caae064ca1 100644 --- a/packages/app-check/package.json +++ b/packages/app-check/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-check", - "version": "0.8.1", + "version": "0.8.3", "description": "The App Check component of the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -38,14 +38,14 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/util": "1.9.3", - "@firebase/component": "0.6.4", - "@firebase/logger": "0.4.0", + "@firebase/util": "1.9.5", + "@firebase/component": "0.6.6", + "@firebase/logger": "0.4.1", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.9.25", + "@firebase/app": "0.10.2", "rollup": "2.79.1", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "4.1.0", @@ -56,7 +56,7 @@ "repository": { "directory": "packages/app-check", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/app-compat/CHANGELOG.md b/packages/app-compat/CHANGELOG.md index 0cdffb9ab1a..fdcd50b8191 100644 --- a/packages/app-compat/CHANGELOG.md +++ b/packages/app-compat/CHANGELOG.md @@ -1,5 +1,61 @@ # @firebase/app-compat +## 0.2.32 + +### Patch Changes + +- Updated dependencies []: + - @firebase/app@0.10.2 + +## 0.2.31 + +### Patch Changes + +- Updated dependencies [[`6d31930b3`](https://github.com/firebase/firebase-js-sdk/commit/6d31930b3abe1588ae81a5c14b59cd386fddc718), [`ad8d5470d`](https://github.com/firebase/firebase-js-sdk/commit/ad8d5470dad9b9ec1bcd939609da4a1c439c8414)]: + - @firebase/app@0.10.1 + +## 0.2.30 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`ed84efe50`](https://github.com/firebase/firebase-js-sdk/commit/ed84efe50bfc365da8ebfacdd2b17b5cc2a9e596), [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/app@0.10.0 + - @firebase/component@0.6.6 + - @firebase/logger@0.4.1 + - @firebase/util@1.9.5 + +## 0.2.29 + +### Patch Changes + +- Updated dependencies []: + - @firebase/app@0.9.29 + +## 0.2.28 + +### Patch Changes + +- Updated dependencies []: + - @firebase/app@0.9.28 + +## 0.2.27 + +### Patch Changes + +- Updated dependencies [[`3f8cbcd18`](https://github.com/firebase/firebase-js-sdk/commit/3f8cbcd18f47fcae8c0d8060fd8c245c025784c0), [`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/app@0.9.27 + - @firebase/util@1.9.4 + - @firebase/component@0.6.5 + +## 0.2.26 + +### Patch Changes + +- Updated dependencies [[`16728cf3c`](https://github.com/firebase/firebase-js-sdk/commit/16728cf3c6b4e358dc3d12f80623e5966f104c31)]: + - @firebase/app@0.9.26 + ## 0.2.25 ### Patch Changes diff --git a/packages/app-compat/package.json b/packages/app-compat/package.json index bff020c956a..375afdb7a8f 100644 --- a/packages/app-compat/package.json +++ b/packages/app-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-compat", - "version": "0.2.25", + "version": "0.2.32", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -40,10 +40,10 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/app": "0.9.25", - "@firebase/util": "1.9.3", - "@firebase/logger": "0.4.0", - "@firebase/component": "0.6.4", + "@firebase/app": "0.10.2", + "@firebase/util": "1.9.5", + "@firebase/logger": "0.4.1", + "@firebase/component": "0.6.6", "tslib": "^2.1.0" }, "devDependencies": { @@ -56,7 +56,7 @@ "repository": { "directory": "packages/app-compat", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/app-types/CHANGELOG.md b/packages/app-types/CHANGELOG.md index 769e1fe9243..7e0db374b72 100644 --- a/packages/app-types/CHANGELOG.md +++ b/packages/app-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/app-types +## 0.9.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.9.0 ### Minor Changes diff --git a/packages/app-types/package.json b/packages/app-types/package.json index 640b1cf88cc..8747173e1fd 100644 --- a/packages/app-types/package.json +++ b/packages/app-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app-types", - "version": "0.9.0", + "version": "0.9.1", "description": "@firebase/app Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -15,7 +15,7 @@ "repository": { "directory": "packages/app-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 6164fa3334b..a445874836e 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,63 @@ # @firebase/app +## 0.10.2 + +### Patch Changes + +- Update SDK_VERSION. + +## 0.10.1 + +### Patch Changes + +- [`6d31930b3`](https://github.com/firebase/firebase-js-sdk/commit/6d31930b3abe1588ae81a5c14b59cd386fddc718) [#8109](https://github.com/firebase/firebase-js-sdk/pull/8109) - FirebaseServerApp should not be JSON serializable + +- [`ad8d5470d`](https://github.com/firebase/firebase-js-sdk/commit/ad8d5470dad9b9ec1bcd939609da4a1c439c8414) [#8134](https://github.com/firebase/firebase-js-sdk/pull/8134) - Updated dependencies. See GitHub PR #8098. + +## 0.10.0 + +### Minor Changes + +- [`ed84efe50`](https://github.com/firebase/firebase-js-sdk/commit/ed84efe50bfc365da8ebfacdd2b17b5cc2a9e596) [#8005](https://github.com/firebase/firebase-js-sdk/pull/8005) - Added the new `FirebaseServerApp` interface to bridge state + data between client and server runtime environments. This interface extends `FirebaseApp`. + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/component@0.6.6 + - @firebase/logger@0.4.1 + - @firebase/util@1.9.5 + +## 0.9.29 + +### Patch Changes + +- Update SDK_VERSION. + +## 0.9.28 + +### Patch Changes + +- Update SDK_VERSION. + +## 0.9.27 + +### Patch Changes + +- [`3f8cbcd18`](https://github.com/firebase/firebase-js-sdk/commit/3f8cbcd18f47fcae8c0d8060fd8c245c025784c0) [#7984](https://github.com/firebase/firebase-js-sdk/pull/7984) - Catch `transaction.done` errors in `readHeartbeatsFromIndexedDB` and log them as a warning, because platform logging errors should never throw or block user app functionality. + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/component@0.6.5 + +## 0.9.26 + +### Patch Changes + +- [`16728cf3c`](https://github.com/firebase/firebase-js-sdk/commit/16728cf3c6b4e358dc3d12f80623e5966f104c31) [#7890](https://github.com/firebase/firebase-js-sdk/pull/7890) (fixes [#7829](https://github.com/firebase/firebase-js-sdk/issues/7829)) - Catch possible error in Safari browsers. + ## 0.9.25 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index a736724ccc4..0e8b0a1772c 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/app", - "version": "0.9.25", + "version": "0.10.2", "description": "The primary entrypoint to the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -38,9 +38,9 @@ "typings:internal": "node ../../scripts/build/use_typings.js ./dist/app.d.ts" }, "dependencies": { - "@firebase/util": "1.9.3", - "@firebase/logger": "0.4.0", - "@firebase/component": "0.6.4", + "@firebase/util": "1.9.5", + "@firebase/logger": "0.4.1", + "@firebase/component": "0.6.6", "idb": "7.1.1", "tslib": "^2.1.0" }, @@ -50,13 +50,13 @@ "rollup": "2.79.1", "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.31.2", - "rollup-plugin-dts": "5.3.0", + "rollup-plugin-dts": "5.3.1", "typescript": "4.7.4" }, "repository": { "directory": "packages/app", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/app/src/api.test.ts b/packages/app/src/api.test.ts index ab361df6ff1..f5577d092e2 100644 --- a/packages/app/src/api.test.ts +++ b/packages/app/src/api.test.ts @@ -20,6 +20,7 @@ import { stub, spy } from 'sinon'; import '../test/setup'; import { initializeApp, + initializeServerApp, getApps, deleteApp, getApp, @@ -28,7 +29,7 @@ import { onLog } from './api'; import { DEFAULT_ENTRY_NAME } from './constants'; -import { _FirebaseService } from './public-types'; +import { FirebaseServerAppSettings, _FirebaseService } from './public-types'; import { _clearComponents, _components, @@ -39,6 +40,8 @@ import { createTestComponent } from '../test/util'; import { Component, ComponentType } from '@firebase/component'; import { Logger } from '@firebase/logger'; import { FirebaseAppImpl } from './firebaseApp'; +import { FirebaseServerAppImpl } from './firebaseServerApp'; +import { isBrowser } from '@firebase/util'; declare module '@firebase/component' { interface NameServiceMapping { @@ -54,7 +57,7 @@ describe('API tests', () => { }); describe('initializeApp', () => { - it('creats DEFAULT App', () => { + it('creates DEFAULT App', () => { const app = initializeApp({}); expect(app.name).to.equal(DEFAULT_ENTRY_NAME); }); @@ -91,7 +94,7 @@ describe('API tests', () => { ).to.equal(app); }); - it('throws when creating duplicate DEDAULT Apps with different options', () => { + it('throws when creating duplicate DEFAULT Apps with different options', () => { initializeApp({ apiKey: 'test1' }); @@ -120,7 +123,7 @@ describe('API tests', () => { ).throws(/'MyApp'.*exists/i); }); - it('throws when creating duplicate DEDAULT Apps with different config values', () => { + it('throws when creating duplicate DEFAULT Apps with different config values', () => { initializeApp( { apiKey: 'test1' @@ -161,12 +164,6 @@ describe('API tests', () => { expect(app.name).to.equal(appName); }); - it('takes an object as the second parameter to create named App', () => { - const appName = 'MyApp'; - const app = initializeApp({}, { name: appName }); - expect(app.name).to.equal(appName); - }); - it('sets automaticDataCollectionEnabled', () => { const app = initializeApp({}, { automaticDataCollectionEnabled: true }); expect(app.automaticDataCollectionEnabled).to.be.true; @@ -187,6 +184,213 @@ describe('API tests', () => { }); }); + describe('initializeServerApp', () => { + it('creates FirebaseServerApp fails in browsers.', () => { + if (isBrowser()) { + const options = { + apiKey: 'APIKEY' + }; + const serverAppSettings: FirebaseServerAppSettings = {}; + expect(() => initializeServerApp(options, serverAppSettings)).throws( + /FirebaseServerApp is not for use in browser environments./ + ); + } + }); + + it('creates FirebaseServerApp with options', async () => { + if (isBrowser()) { + // FirebaseServerApp isn't supported for execution in browser environments. + return; + } + + const options = { + apiKey: 'APIKEY' + }; + + const serverAppSettings: FirebaseServerAppSettings = {}; + + const app = initializeServerApp(options, serverAppSettings); + expect(app).to.not.equal(null); + expect(app.automaticDataCollectionEnabled).to.be.false; + await deleteApp(app); + expect((app as FirebaseServerAppImpl).isDeleted).to.be.true; + }); + + it('creates FirebaseServerApp with automaticDataCollectionEnabled', async () => { + if (isBrowser()) { + // FirebaseServerApp isn't supported for execution in browser environments. + return; + } + + const options = { + apiKey: 'APIKEY' + }; + + const serverAppSettings: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: true + }; + + const app = initializeServerApp(options, serverAppSettings); + expect(app).to.not.equal(null); + expect(app.automaticDataCollectionEnabled).to.be.true; + await deleteApp(app); + expect((app as FirebaseServerAppImpl).isDeleted).to.be.true; + }); + + it('creates FirebaseServerApp with releaseOnDeref', async () => { + if (isBrowser()) { + // FirebaseServerApp isn't supported for execution in browser environments. + return; + } + + const options = { apiKey: 'APIKEY' }; + const serverAppSettings: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false, + releaseOnDeref: options + }; + + const app = initializeServerApp(options, serverAppSettings); + expect(app).to.not.equal(null); + expect(app.automaticDataCollectionEnabled).to.be.false; + await deleteApp(app); + expect((app as FirebaseServerAppImpl).isDeleted).to.be.true; + }); + + it('creates FirebaseServerApp with FirebaseApp', async () => { + if (isBrowser()) { + // FirebaseServerApp isn't supported for execution in browser environments. + return; + } + + const options = { + apiKey: 'test1' + }; + const standardApp = initializeApp(options); + expect(standardApp.name).to.equal(DEFAULT_ENTRY_NAME); + expect(standardApp.options.apiKey).to.equal('test1'); + + const serverAppSettings: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false + }; + + const app = initializeServerApp(standardApp, serverAppSettings); + expect(app).to.not.equal(null); + expect(app.options.apiKey).to.equal('test1'); + await deleteApp(app); + expect((app as FirebaseServerAppImpl).isDeleted).to.be.true; + }); + }); + + it('create similar FirebaseServerApps does not return the same object', async () => { + if (isBrowser()) { + // FirebaseServerApp isn't supported for execution in browser environments. + return; + } + + const options = { apiKey: 'APIKEY' }; + const serverAppSettingsOne: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: true + }; + + const serverAppSettingsTwo: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false + }; + + const appOne = initializeServerApp(options, serverAppSettingsOne); + expect(appOne).to.not.equal(null); + expect(appOne.automaticDataCollectionEnabled).to.be.true; + const appTwo = initializeServerApp(options, serverAppSettingsTwo); + expect(appTwo).to.not.equal(null); + expect(appTwo.automaticDataCollectionEnabled).to.be.false; + expect(appTwo).to.not.equal(appOne); + await deleteApp(appOne); + await deleteApp(appTwo); + expect((appOne as FirebaseServerAppImpl).isDeleted).to.be.true; + expect((appTwo as FirebaseServerAppImpl).isDeleted).to.be.true; + }); + + it('create FirebaseServerApps with varying deleteOnDeref, and they still return same object ', async () => { + if (isBrowser()) { + // FirebaseServerApp isn't supported for execution in browser environments. + return; + } + + const options = { apiKey: 'APIKEY' }; + const serverAppSettingsOne: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false + }; + + const serverAppSettingsTwo: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false, + releaseOnDeref: options + }; + + const appOne = initializeServerApp(options, serverAppSettingsOne); + expect(appOne).to.not.equal(null); + expect(appOne.automaticDataCollectionEnabled).to.be.false; + const appTwo = initializeServerApp(options, serverAppSettingsTwo); + expect(appTwo).to.not.equal(null); + expect(appTwo.automaticDataCollectionEnabled).to.be.false; + expect(appTwo).to.equal(appOne); + await deleteApp(appOne); + await deleteApp(appTwo); + }); + + it('create duplicate FirebaseServerApps returns the same object', async () => { + if (isBrowser()) { + // FirebaseServerApp isn't supported for execution in browser environments. + return; + } + + const options = { apiKey: 'APIKEY' }; + const serverAppSettings: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false, + releaseOnDeref: options + }; + + const appOne = initializeServerApp(options, serverAppSettings); + expect(appOne).to.not.equal(null); + expect(appOne.automaticDataCollectionEnabled).to.be.false; + const appTwo = initializeServerApp(options, serverAppSettings); + expect(appTwo).to.not.equal(null); + expect(appTwo).to.equal(appOne); + await deleteApp(appOne); + await deleteApp(appTwo); + }); + + it('deleting FirebaseServerApps is ref counted', async () => { + if (isBrowser()) { + // FirebaseServerApp isn't supported for execution in browser environments. + return; + } + + const options = { apiKey: 'APIKEY' }; + const serverAppSettings: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false, + releaseOnDeref: options + }; + + const appOne = initializeServerApp(options, serverAppSettings); + expect((appOne as FirebaseServerAppImpl).refCount).to.equal(1); + + const appTwo = initializeServerApp(options, serverAppSettings); + expect(appTwo).to.equal(appOne); + expect((appOne as FirebaseServerAppImpl).refCount).to.equal(2); + expect((appTwo as FirebaseServerAppImpl).refCount).to.equal(2); + + await deleteApp(appOne); + expect((appOne as FirebaseServerAppImpl).refCount).to.equal(1); + expect((appTwo as FirebaseServerAppImpl).refCount).to.equal(1); + expect((appOne as FirebaseServerAppImpl).isDeleted).to.be.false; + expect((appTwo as FirebaseServerAppImpl).isDeleted).to.be.false; + + await deleteApp(appTwo); + expect((appOne as FirebaseServerAppImpl).refCount).to.equal(0); + expect((appTwo as FirebaseServerAppImpl).refCount).to.equal(0); + expect((appOne as FirebaseServerAppImpl).isDeleted).to.be.true; + expect((appTwo as FirebaseServerAppImpl).isDeleted).to.be.true; + }); + describe('getApp', () => { it('retrieves DEFAULT App', () => { const app = initializeApp({}); diff --git a/packages/app/src/api.ts b/packages/app/src/api.ts index d43c4ac65c2..5928fd737a8 100644 --- a/packages/app/src/api.ts +++ b/packages/app/src/api.ts @@ -17,8 +17,10 @@ import { FirebaseApp, + FirebaseServerApp, FirebaseOptions, - FirebaseAppSettings + FirebaseAppSettings, + FirebaseServerAppSettings } from './public-types'; import { DEFAULT_ENTRY_NAME, PLATFORM_LOG_STRING } from './constants'; import { ERROR_FACTORY, AppError } from './errors'; @@ -30,7 +32,14 @@ import { } from '@firebase/component'; import { version } from '../../firebase/package.json'; import { FirebaseAppImpl } from './firebaseApp'; -import { _apps, _components, _registerComponent } from './internal'; +import { FirebaseServerAppImpl } from './firebaseServerApp'; +import { + _apps, + _components, + _isFirebaseApp, + _registerComponent, + _serverApps +} from './internal'; import { logger } from './logger'; import { LogLevelString, @@ -39,7 +48,7 @@ import { LogOptions, setUserLogHandler } from '@firebase/logger'; -import { deepEqual, getDefaultAppConfig } from '@firebase/util'; +import { deepEqual, getDefaultAppConfig, isBrowser } from '@firebase/util'; export { FirebaseError } from '@firebase/util'; @@ -171,6 +180,126 @@ export function initializeApp( return newApp; } +/** + * Creates and initializes a {@link @firebase/app#FirebaseServerApp} instance. + * + * The `FirebaseServerApp` is similar to `FirebaseApp`, but is intended for execution in + * server side rendering environments only. Initialization will fail if invoked from a + * browser environment. + * + * See + * {@link + * https://firebase.google.com/docs/web/setup#add_firebase_to_your_app + * | Add Firebase to your app} and + * {@link + * https://firebase.google.com/docs/web/setup#multiple-projects + * | Initialize multiple projects} for detailed documentation. + * + * @example + * ```javascript + * + * // Initialize an instance of `FirebaseServerApp`. + * // Retrieve your own options values by adding a web app on + * // https://console.firebase.google.com + * initializeServerApp({ + * apiKey: "AIza....", // Auth / General Use + * authDomain: "YOUR_APP.firebaseapp.com", // Auth with popup/redirect + * databaseURL: "https://YOUR_APP.firebaseio.com", // Realtime Database + * storageBucket: "YOUR_APP.appspot.com", // Storage + * messagingSenderId: "123456789" // Cloud Messaging + * }, + * { + * authIdToken: "Your Auth ID Token" + * }); + * ``` + * + * @param options - `Firebase.AppOptions` to configure the app's services, or a + * a `FirebaseApp` instance which contains the `AppOptions` within. + * @param config - `FirebaseServerApp` configuration. + * + * @returns The initialized `FirebaseServerApp`. + * + * @public + */ +export function initializeServerApp( + options: FirebaseOptions | FirebaseApp, + config: FirebaseServerAppSettings +): FirebaseServerApp; + +export function initializeServerApp( + _options: FirebaseOptions | FirebaseApp, + _serverAppConfig: FirebaseServerAppSettings +): FirebaseServerApp { + if (isBrowser()) { + // FirebaseServerApp isn't designed to be run in browsers. + throw ERROR_FACTORY.create(AppError.INVALID_SERVER_APP_ENVIRONMENT); + } + + if (_serverAppConfig.automaticDataCollectionEnabled === undefined) { + _serverAppConfig.automaticDataCollectionEnabled = false; + } + + let appOptions: FirebaseOptions; + if (_isFirebaseApp(_options)) { + appOptions = _options.options; + } else { + appOptions = _options; + } + + // Build an app name based on a hash of the configuration options. + const nameObj = { + ..._serverAppConfig, + ...appOptions + }; + + // However, Do not mangle the name based on releaseOnDeref, since it will vary between the + // construction of FirebaseServerApp instances. For example, if the object is the request headers. + if (nameObj.releaseOnDeref !== undefined) { + delete nameObj.releaseOnDeref; + } + + const hashCode = (s: string): number => { + return [...s].reduce( + (hash, c) => (Math.imul(31, hash) + c.charCodeAt(0)) | 0, + 0 + ); + }; + + if (_serverAppConfig.releaseOnDeref !== undefined) { + if (typeof FinalizationRegistry === 'undefined') { + throw ERROR_FACTORY.create( + AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED, + {} + ); + } + } + + const nameString = '' + hashCode(JSON.stringify(nameObj)); + const existingApp = _serverApps.get(nameString) as FirebaseServerApp; + if (existingApp) { + (existingApp as FirebaseServerAppImpl).incRefCount( + _serverAppConfig.releaseOnDeref + ); + return existingApp; + } + + const container = new ComponentContainer(nameString); + for (const component of _components.values()) { + container.addComponent(component); + } + + const newApp = new FirebaseServerAppImpl( + appOptions, + _serverAppConfig, + nameString, + container + ); + + _serverApps.set(nameString, newApp); + + return newApp; +} + /** * Retrieves a {@link @firebase/app#FirebaseApp} instance. * @@ -238,9 +367,20 @@ export function getApps(): FirebaseApp[] { * @public */ export async function deleteApp(app: FirebaseApp): Promise { + let cleanupProviders = false; const name = app.name; if (_apps.has(name)) { + cleanupProviders = true; _apps.delete(name); + } else if (_serverApps.has(name)) { + const firebaseServerApp = app as FirebaseServerAppImpl; + if (firebaseServerApp.decRefCount() <= 0) { + _serverApps.delete(name); + cleanupProviders = true; + } + } + + if (cleanupProviders) { await Promise.all( (app as FirebaseAppImpl).container .getProviders() diff --git a/packages/app/src/constants.ts b/packages/app/src/constants.ts index e251c75647b..92102192e93 100644 --- a/packages/app/src/constants.ts +++ b/packages/app/src/constants.ts @@ -38,6 +38,7 @@ import { name as remoteConfigCompatName } from '../../../packages/remote-config- import { name as storageName } from '../../../packages/storage/package.json'; import { name as storageCompatName } from '../../../packages/storage-compat/package.json'; import { name as firestoreName } from '../../../packages/firestore/package.json'; +import { name as vertexName } from '../../../packages/vertexai/package.json'; import { name as firestoreCompatName } from '../../../packages/firestore-compat/package.json'; import { name as packageName } from '../../../packages/firebase/package.json'; @@ -73,6 +74,7 @@ export const PLATFORM_LOG_STRING = { [storageCompatName]: 'fire-gcs-compat', [firestoreName]: 'fire-fst', [firestoreCompatName]: 'fire-fst-compat', + [vertexName]: 'fire-vertex', 'fire-js': 'fire-js', // Platform identifier for JS SDK. [packageName]: 'fire-js-all' } as const; diff --git a/packages/app/src/errors.ts b/packages/app/src/errors.ts index 25582398663..0149ef3dcb1 100644 --- a/packages/app/src/errors.ts +++ b/packages/app/src/errors.ts @@ -22,23 +22,27 @@ export const enum AppError { BAD_APP_NAME = 'bad-app-name', DUPLICATE_APP = 'duplicate-app', APP_DELETED = 'app-deleted', + SERVER_APP_DELETED = 'server-app-deleted', NO_OPTIONS = 'no-options', INVALID_APP_ARGUMENT = 'invalid-app-argument', INVALID_LOG_ARGUMENT = 'invalid-log-argument', IDB_OPEN = 'idb-open', IDB_GET = 'idb-get', IDB_WRITE = 'idb-set', - IDB_DELETE = 'idb-delete' + IDB_DELETE = 'idb-delete', + FINALIZATION_REGISTRY_NOT_SUPPORTED = 'finalization-registry-not-supported', + INVALID_SERVER_APP_ENVIRONMENT = 'invalid-server-app-environment' } const ERRORS: ErrorMap = { [AppError.NO_APP]: "No Firebase App '{$appName}' has been created - " + 'call initializeApp() first', - [AppError.BAD_APP_NAME]: "Illegal App name: '{$appName}", + [AppError.BAD_APP_NAME]: "Illegal App name: '{$appName}'", [AppError.DUPLICATE_APP]: "Firebase App named '{$appName}' already exists with different options or config", [AppError.APP_DELETED]: "Firebase App named '{$appName}' already deleted", + [AppError.SERVER_APP_DELETED]: 'Firebase Server App has been deleted', [AppError.NO_OPTIONS]: 'Need to provide options, when not being deployed to hosting via source.', [AppError.INVALID_APP_ARGUMENT]: @@ -53,7 +57,11 @@ const ERRORS: ErrorMap = { [AppError.IDB_WRITE]: 'Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.', [AppError.IDB_DELETE]: - 'Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.' + 'Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.', + [AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED]: + 'FirebaseServerApp deleteOnDeref field defined but the JS runtime does not support FinalizationRegistry.', + [AppError.INVALID_SERVER_APP_ENVIRONMENT]: + 'FirebaseServerApp is not for use in browser environments.' }; interface ErrorParams { @@ -66,6 +74,7 @@ interface ErrorParams { [AppError.IDB_GET]: { originalErrorMessage?: string }; [AppError.IDB_WRITE]: { originalErrorMessage?: string }; [AppError.IDB_DELETE]: { originalErrorMessage?: string }; + [AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED]: { appName?: string }; } export const ERROR_FACTORY = new ErrorFactory( diff --git a/packages/app/src/firebaseApp.ts b/packages/app/src/firebaseApp.ts index 60d3b29a3ea..4f36e818f96 100644 --- a/packages/app/src/firebaseApp.ts +++ b/packages/app/src/firebaseApp.ts @@ -28,8 +28,8 @@ import { import { ERROR_FACTORY, AppError } from './errors'; export class FirebaseAppImpl implements FirebaseApp { - private readonly _options: FirebaseOptions; - private readonly _name: string; + protected readonly _options: FirebaseOptions; + protected readonly _name: string; /** * Original config values passed in as a constructor parameter. * It is only used to compare with another config object to support idempotent initializeApp(). @@ -38,7 +38,7 @@ export class FirebaseAppImpl implements FirebaseApp { */ private readonly _config: Required; private _automaticDataCollectionEnabled: boolean; - private _isDeleted = false; + protected _isDeleted = false; private readonly _container: ComponentContainer; constructor( @@ -98,7 +98,7 @@ export class FirebaseAppImpl implements FirebaseApp { * This function will throw an Error if the App has already been deleted - * use before performing API actions on the App. */ - private checkDestroyed(): void { + protected checkDestroyed(): void { if (this.isDeleted) { throw ERROR_FACTORY.create(AppError.APP_DELETED, { appName: this._name }); } diff --git a/packages/app/src/firebaseServerApp.test.ts b/packages/app/src/firebaseServerApp.test.ts new file mode 100644 index 00000000000..bf2da5c06d5 --- /dev/null +++ b/packages/app/src/firebaseServerApp.test.ts @@ -0,0 +1,158 @@ +/** + * @license + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'chai'; +import '../test/setup'; +import { ComponentContainer } from '@firebase/component'; +import { FirebaseServerAppImpl } from './firebaseServerApp'; +import { FirebaseServerAppSettings } from './public-types'; + +describe('FirebaseServerApp', () => { + it('has various accessors', () => { + const options = { + apiKey: 'APIKEY' + }; + + const serverAppSettings: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false, + releaseOnDeref: options + }; + + const firebaseServerAppImpl = new FirebaseServerAppImpl( + options, + serverAppSettings, + 'testName', + new ComponentContainer('test') + ); + + expect(firebaseServerAppImpl.automaticDataCollectionEnabled).to.be.false; + expect(firebaseServerAppImpl.options).to.deep.equal(options); + }); + + it('deep-copies options', () => { + const options = { + apiKey: 'APIKEY' + }; + + const serverAppSettings: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false, + releaseOnDeref: options + }; + + const firebaseServerAppImpl = new FirebaseServerAppImpl( + options, + serverAppSettings, + 'testName', + new ComponentContainer('test') + ); + + expect(firebaseServerAppImpl.options).to.not.equal(options); + expect(firebaseServerAppImpl.options).to.deep.equal(options); + }); + + it('sets automaticDataCollectionEnabled', () => { + const options = { + apiKey: 'APIKEY' + }; + + const serverAppSettings: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false, + releaseOnDeref: options + }; + + const firebaseServerAppImpl = new FirebaseServerAppImpl( + options, + serverAppSettings, + 'testName', + new ComponentContainer('test') + ); + + expect(firebaseServerAppImpl.automaticDataCollectionEnabled).to.be.false; + firebaseServerAppImpl.automaticDataCollectionEnabled = true; + expect(firebaseServerAppImpl.automaticDataCollectionEnabled).to.be.true; + }); + + it('throws accessing any property after being deleted', () => { + const options = { + apiKey: 'APIKEY' + }; + + const serverAppSettings: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false, + releaseOnDeref: options + }; + + const app = new FirebaseServerAppImpl( + options, + serverAppSettings, + 'testName', + new ComponentContainer('test') + ); + + expect(() => app.options).to.not.throw(); + (app as unknown as FirebaseServerAppImpl).isDeleted = true; + + expect(() => app.options).throws('Firebase Server App has been deleted'); + + expect(() => app.automaticDataCollectionEnabled).throws( + 'Firebase Server App has been deleted' + ); + }); + + it('throws accessing any method after being deleted', () => { + const options = { + apiKey: 'APIKEY' + }; + + const serverAppSettings: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false, + releaseOnDeref: options + }; + + const app = new FirebaseServerAppImpl( + options, + serverAppSettings, + 'testName', + new ComponentContainer('test') + ); + + expect(() => app.settings).to.not.throw(); + (app as unknown as FirebaseServerAppImpl).isDeleted = true; + + expect(() => app.settings).throws('Firebase Server App has been deleted'); + }); + + it('should not be JSON serializable', () => { + const options = { + apiKey: 'APIKEY' + }; + + const serverAppSettings: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false, + releaseOnDeref: options + }; + + const app = new FirebaseServerAppImpl( + options, + serverAppSettings, + 'testName', + new ComponentContainer('test') + ); + + expect(JSON.stringify(app)).to.eql(undefined); + }); +}); diff --git a/packages/app/src/firebaseServerApp.ts b/packages/app/src/firebaseServerApp.ts new file mode 100644 index 00000000000..6b6c33d316b --- /dev/null +++ b/packages/app/src/firebaseServerApp.ts @@ -0,0 +1,134 @@ +/** + * @license + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + FirebaseAppSettings, + FirebaseServerApp, + FirebaseServerAppSettings, + FirebaseOptions +} from './public-types'; +import { deleteApp, registerVersion } from './api'; +import { ComponentContainer } from '@firebase/component'; +import { FirebaseAppImpl } from './firebaseApp'; +import { ERROR_FACTORY, AppError } from './errors'; +import { name as packageName, version } from '../package.json'; + +export class FirebaseServerAppImpl + extends FirebaseAppImpl + implements FirebaseServerApp +{ + private readonly _serverConfig: FirebaseServerAppSettings; + private _finalizationRegistry: FinalizationRegistry; + private _refCount: number; + + constructor( + options: FirebaseOptions | FirebaseAppImpl, + serverConfig: FirebaseServerAppSettings, + name: string, + container: ComponentContainer + ) { + // Build configuration parameters for the FirebaseAppImpl base class. + const automaticDataCollectionEnabled = + serverConfig.automaticDataCollectionEnabled !== undefined + ? serverConfig.automaticDataCollectionEnabled + : false; + + // Create the FirebaseAppSettings object for the FirebaseAppImp constructor. + const config: Required = { + name, + automaticDataCollectionEnabled + }; + + if ((options as FirebaseOptions).apiKey !== undefined) { + // Construct the parent FirebaseAppImp object. + super(options as FirebaseOptions, config, container); + } else { + const appImpl: FirebaseAppImpl = options as FirebaseAppImpl; + super(appImpl.options, config, container); + } + + // Now construct the data for the FirebaseServerAppImpl. + this._serverConfig = { + automaticDataCollectionEnabled, + ...serverConfig + }; + + this._finalizationRegistry = new FinalizationRegistry(() => { + this.automaticCleanup(); + }); + + this._refCount = 0; + this.incRefCount(this._serverConfig.releaseOnDeref); + + // Do not retain a hard reference to the dref object, otherwise the FinalizationRegisry + // will never trigger. + this._serverConfig.releaseOnDeref = undefined; + serverConfig.releaseOnDeref = undefined; + + registerVersion(packageName, version, 'serverapp'); + } + + toJSON(): undefined { + return undefined; + } + + get refCount(): number { + return this._refCount; + } + + // Increment the reference count of this server app. If an object is provided, register it + // with the finalization registry. + incRefCount(obj: object | undefined): void { + if (this.isDeleted) { + return; + } + this._refCount++; + if (obj !== undefined) { + this._finalizationRegistry.register(obj, this); + } + } + + // Decrement the reference count. + decRefCount(): number { + if (this.isDeleted) { + return 0; + } + return --this._refCount; + } + + // Invoked by the FinalizationRegistry callback to note that this app should go through its + // reference counts and delete itself if no reference count remain. The coordinating logic that + // handles this is in deleteApp(...). + private automaticCleanup(): void { + void deleteApp(this); + } + + get settings(): FirebaseServerAppSettings { + this.checkDestroyed(); + return this._serverConfig; + } + + /** + * This function will throw an Error if the App has already been deleted - + * use before performing API actions on the App. + */ + protected checkDestroyed(): void { + if (this.isDeleted) { + throw ERROR_FACTORY.create(AppError.SERVER_APP_DELETED); + } + } +} diff --git a/packages/app/src/indexeddb.ts b/packages/app/src/indexeddb.ts index 07f18d807b6..7cd1c29eaa5 100644 --- a/packages/app/src/indexeddb.ts +++ b/packages/app/src/indexeddb.ts @@ -69,10 +69,11 @@ export async function readHeartbeatsFromIndexedDB( ): Promise { try { const db = await getDbPromise(); - const result = await db - .transaction(STORE_NAME) - .objectStore(STORE_NAME) - .get(computeKey(app)); + const tx = db.transaction(STORE_NAME); + const result = await tx.objectStore(STORE_NAME).get(computeKey(app)); + // We already have the value but tx.done can throw, + // so we need to await it here to catch errors + await tx.done; return result; } catch (e) { if (e instanceof FirebaseError) { diff --git a/packages/app/src/internal.ts b/packages/app/src/internal.ts index 9026a36b26a..7e0c1545962 100644 --- a/packages/app/src/internal.ts +++ b/packages/app/src/internal.ts @@ -15,17 +15,27 @@ * limitations under the License. */ -import { FirebaseApp } from './public-types'; +import { + FirebaseApp, + FirebaseOptions, + FirebaseServerApp +} from './public-types'; import { Component, Provider, Name } from '@firebase/component'; import { logger } from './logger'; import { DEFAULT_ENTRY_NAME } from './constants'; import { FirebaseAppImpl } from './firebaseApp'; +import { FirebaseServerAppImpl } from './firebaseServerApp'; /** * @internal */ export const _apps = new Map(); +/** + * @internal + */ +export const _serverApps = new Map(); + /** * Registered components. * @@ -90,6 +100,10 @@ export function _registerComponent( _addComponent(app as FirebaseAppImpl, component); } + for (const serverApp of _serverApps.values()) { + _addComponent(serverApp as FirebaseServerAppImpl, component); + } + return true; } @@ -131,6 +145,34 @@ export function _removeServiceInstance( _getProvider(app, name).clearInstance(instanceIdentifier); } +/** + * + * @param obj - an object of type FirebaseApp or FirebaseOptions. + * + * @returns true if the provide object is of type FirebaseApp. + * + * @internal + */ +export function _isFirebaseApp( + obj: FirebaseApp | FirebaseOptions +): obj is FirebaseApp { + return (obj as FirebaseApp).options !== undefined; +} + +/** + * + * @param obj - an object of type FirebaseApp. + * + * @returns true if the provided object is of type FirebaseServerAppImpl. + * + * @internal + */ +export function _isFirebaseServerApp( + obj: FirebaseApp | FirebaseServerApp +): obj is FirebaseServerApp { + return (obj as FirebaseServerApp).settings !== undefined; +} + /** * Test only * diff --git a/packages/app/src/public-types.ts b/packages/app/src/public-types.ts index 3ca76c47889..eb963a54adf 100644 --- a/packages/app/src/public-types.ts +++ b/packages/app/src/public-types.ts @@ -71,6 +71,37 @@ export interface FirebaseApp { automaticDataCollectionEnabled: boolean; } +/** + * A {@link @firebase/app#FirebaseServerApp} holds the initialization information + * for a collection of services running in server environments. + * + * Do not call this constructor directly. Instead, use + * {@link (initializeServerApp:1) | initializeServerApp()} to create + * an app. + * + * @public + */ +export interface FirebaseServerApp extends FirebaseApp { + /** + * There is no `getApp()` operation for `FirebaseServerApp`, so the name is not relevant for + * applications. However, it may be used internally, and is declared here so that + * `FirebaseServerApp` conforms to the `FirebaseApp` interface. + */ + name: string; + + /** + * The (read-only) configuration settings for this server app. These are the original + * parameters given in {@link (initializeServerApp:1) | initializeServerApp()}. + * + * @example + * ```javascript + * const app = initializeServerApp(settings); + * console.log(app.settings.authIdToken === options.authIdToken); // true + * ``` + */ + readonly settings: FirebaseServerAppSettings; +} + /** * @public * @@ -139,6 +170,60 @@ export interface FirebaseAppSettings { automaticDataCollectionEnabled?: boolean; } +/** + * @public + * + * Configuration options given to {@link (initializeServerApp:1) | initializeServerApp()} + */ +export interface FirebaseServerAppSettings extends FirebaseAppSettings { + /** + * An optional Auth ID token used to resume a signed in user session from a client + * runtime environment. + * + * Invoking `getAuth` with a `FirebaseServerApp` configured with a validated `authIdToken` + * causes an automatic attempt to sign in the user that the `authIdToken` represents. The token + * needs to have been recently minted for this operation to succeed. + * + * If the token fails local verification, or if the Auth service has failed to validate it when + * the Auth SDK is initialized, then a warning is logged to the console and the Auth SDK will not + * sign in a user on initialization. + * + * If a user is successfully signed in, then the Auth instance's `onAuthStateChanged` callback + * is invoked with the `User` object as per standard Auth flows. However, `User` objects + * created via an `authIdToken` do not have a refresh token. Attempted `refreshToken` + * operations fail. + */ + authIdToken?: string; + + /** + * An optional object. If provided, the Firebase SDK uses a `FinalizationRegistry` + * object to monitor the garbage collection status of the provided object. The + * Firebase SDK releases its reference on the `FirebaseServerApp` instance when the + * provided `releaseOnDeref` object is garbage collected. + * + * You can use this field to reduce memory management overhead for your application. + * If provided, an app running in a SSR pass does not need to perform + * `FirebaseServerApp` cleanup, so long as the reference object is deleted (by falling out of + * SSR scope, for instance.) + * + * If an object is not provided then the application must clean up the `FirebaseServerApp` + * instance by invoking `deleteApp`. + * + * If the application provides an object in this parameter, but the application is + * executed in a JavaScript engine that predates the support of `FinalizationRegistry` + * (introduced in node v14.6.0, for instance), then an error is thrown at `FirebaseServerApp` + * initialization. + */ + releaseOnDeref?: object; + + /** + * There is no `getApp()` operation for `FirebaseServerApp`, so the name is not relevant for + * applications. However, it may be used internally, and is declared here so that + * `FirebaseServerApp` conforms to the `FirebaseApp` interface. + */ + name?: undefined; +} + /** * @internal */ diff --git a/packages/auth-compat/CHANGELOG.md b/packages/auth-compat/CHANGELOG.md index 8f3576cfb26..d0f7ddc96a3 100644 --- a/packages/auth-compat/CHANGELOG.md +++ b/packages/auth-compat/CHANGELOG.md @@ -1,5 +1,62 @@ # @firebase/auth-compat +## 0.5.7 + +### Patch Changes + +- [`55fef6d62`](https://github.com/firebase/firebase-js-sdk/commit/55fef6d627791f4704194c3913ebeb339a564906) [#7001](https://github.com/firebase/firebase-js-sdk/pull/7001) - Update jszip transient dependency from 3.7.1 to 3.10.1 in auth. + +- Updated dependencies [[`36b283f3f`](https://github.com/firebase/firebase-js-sdk/commit/36b283f3fc317d0fa7dde47e1048d2ee3690a9a0), [`55fef6d62`](https://github.com/firebase/firebase-js-sdk/commit/55fef6d627791f4704194c3913ebeb339a564906)]: + - @firebase/auth@1.7.2 + +## 0.5.6 + +### Patch Changes + +- [`fe09d8338`](https://github.com/firebase/firebase-js-sdk/commit/fe09d8338d7d5f7a82d8cd73cf825adbe5551975) [#8138](https://github.com/firebase/firebase-js-sdk/pull/8138) (fixes [#8132](https://github.com/firebase/firebase-js-sdk/issues/8132)) - Update undici version to 5.28.4 due to CVE-2024-30260. + +- [`ad8d5470d`](https://github.com/firebase/firebase-js-sdk/commit/ad8d5470dad9b9ec1bcd939609da4a1c439c8414) [#8134](https://github.com/firebase/firebase-js-sdk/pull/8134) - Updated dependencies. See GitHub PR #8098. + +- Updated dependencies [[`fe09d8338`](https://github.com/firebase/firebase-js-sdk/commit/fe09d8338d7d5f7a82d8cd73cf825adbe5551975), [`ad8d5470d`](https://github.com/firebase/firebase-js-sdk/commit/ad8d5470dad9b9ec1bcd939609da4a1c439c8414)]: + - @firebase/auth@1.7.1 + +## 0.5.5 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`ed84efe50`](https://github.com/firebase/firebase-js-sdk/commit/ed84efe50bfc365da8ebfacdd2b17b5cc2a9e596), [`9ca1a4e4f`](https://github.com/firebase/firebase-js-sdk/commit/9ca1a4e4f9f13d56cde93cab6d83a8bc54f83539), [`c8a2568dd`](https://github.com/firebase/firebase-js-sdk/commit/c8a2568ddd2acd9162a99bce9ff4203fe8d6e0da), [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/auth@1.7.0 + - @firebase/auth-types@0.12.1 + - @firebase/component@0.6.6 + - @firebase/util@1.9.5 + +## 0.5.4 + +### Patch Changes + +- Updated dependencies [[`6d487d7de`](https://github.com/firebase/firebase-js-sdk/commit/6d487d7dee631498bed1aeccbb45d8f14ae911d1), [`245dd26e1`](https://github.com/firebase/firebase-js-sdk/commit/245dd26e19b6c16aca7e1b7e597ed5784c2984ba)]: + - @firebase/auth@1.6.2 + +## 0.5.3 + +### Patch Changes + +- [`f3cec28df`](https://github.com/firebase/firebase-js-sdk/commit/f3cec28dfbdfc7f19c8218cf9d26956235d03fb0) [#8044](https://github.com/firebase/firebase-js-sdk/pull/8044) (fixes [#8038](https://github.com/firebase/firebase-js-sdk/issues/8038)) - Bump undici version to 5.28.3 due to security issue. + +- Updated dependencies [[`f3cec28df`](https://github.com/firebase/firebase-js-sdk/commit/f3cec28dfbdfc7f19c8218cf9d26956235d03fb0)]: + - @firebase/auth@1.6.1 + +## 0.5.2 + +### Patch Changes + +- Updated dependencies [[`2f7ad0ac4`](https://github.com/firebase/firebase-js-sdk/commit/2f7ad0ac43f5d085604324f6dc3921d9420bfccd), [`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/auth@1.6.0 + - @firebase/util@1.9.4 + - @firebase/component@0.6.5 + ## 0.5.1 ### Patch Changes diff --git a/packages/auth-compat/demo/functions/package.json b/packages/auth-compat/demo/functions/package.json index de794491ce0..70a35abdd84 100644 --- a/packages/auth-compat/demo/functions/package.json +++ b/packages/auth-compat/demo/functions/package.json @@ -9,7 +9,7 @@ "logs": "firebase functions:log" }, "dependencies": { - "firebase-admin": "11.10.1", + "firebase-admin": "11.11.1", "firebase-functions": "3.24.1" }, "private": true diff --git a/packages/auth-compat/demo/functions/yarn.lock b/packages/auth-compat/demo/functions/yarn.lock index 8383cf43122..08302e6e6c2 100644 --- a/packages/auth-compat/demo/functions/yarn.lock +++ b/packages/auth-compat/demo/functions/yarn.lock @@ -2,94 +2,91 @@ # yarn lockfile v1 -"@firebase/app-types@0.7.0": - version "0.7.0" - resolved "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.7.0.tgz#c9e16d1b8bed1a991840b8d2a725fb58d0b5899f" - integrity sha512-6fbHQwDv2jp/v6bXhBw2eSRbNBpxHcd1NBF864UksSMVIqIyri9qpJB1Mn6sGZE+bnDsSQBC5j2TbMxYsJQkQg== - -"@firebase/auth-interop-types@0.1.6": - version "0.1.6" - resolved "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.6.tgz#5ce13fc1c527ad36f1bb1322c4492680a6cf4964" - integrity sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g== - -"@firebase/component@0.5.13": - version "0.5.13" - resolved "https://registry.npmjs.org/@firebase/component/-/component-0.5.13.tgz#65a382e83bddd109380c9aa1f280791b1b4567c4" - integrity sha512-hxhJtpD8Ppf/VU2Rlos6KFCEV77TGIGD5bJlkPK1+B/WUe0mC6dTjW7KhZtXTc+qRBp9nFHWcsIORnT8liHP9w== - dependencies: - "@firebase/util" "1.5.2" - tslib "^2.1.0" +"@babel/parser@^7.20.15": + version "7.24.0" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac" + integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg== -"@firebase/database-compat@^0.1.8": - version "0.1.8" - resolved "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.1.8.tgz#ab627f2bdbe94367f515d5bded880c86886bbd28" - integrity sha512-dhXr5CSieBuKNdU96HgeewMQCT9EgOIkfF1GNy+iRrdl7BWLxmlKuvLfK319rmIytSs/vnCzcD9uqyxTeU/A3A== +"@fastify/busboy@^1.2.1": + version "1.2.1" + resolved "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.2.1.tgz#9c6db24a55f8b803b5222753b24fe3aea2ba9ca3" + integrity sha512-7PQA7EH43S0CxcOa9OeAnaeA0oQ+e/DHNPZwSQM9CQHW76jle5+OvLdibRp/Aafs9KXbLhxyjOTkRjWUbQEd3Q== dependencies: - "@firebase/component" "0.5.13" - "@firebase/database" "0.12.8" - "@firebase/database-types" "0.9.7" - "@firebase/logger" "0.3.2" - "@firebase/util" "1.5.2" - tslib "^2.1.0" + text-decoding "^1.0.0" -"@firebase/database-types@0.9.7": - version "0.9.7" - resolved "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.7.tgz#c5ee0ea9bb2703a13c1c47fe880fc577d5ce7f33" - integrity sha512-EFhgL89Fz6DY3kkB8TzdHvdu8XaqqvzcF2DLVOXEnQ3Ms7L755p5EO42LfxXoJqb9jKFvgLpFmKicyJG25WFWw== - dependencies: - "@firebase/app-types" "0.7.0" - "@firebase/util" "1.5.2" +"@firebase/app-types@0.9.0": + version "0.9.0" + resolved "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz#35b5c568341e9e263b29b3d2ba0e9cfc9ec7f01e" + integrity sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q== -"@firebase/database-types@^0.9.7": - version "0.9.8" - resolved "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.8.tgz#5a9bb1d2c492ad635eff5f3cfbe6a0ea6a2463e7" - integrity sha512-bI7bwF5xc0nPi6Oa3JVt6JJdfhVAnEpCwgfTNILR4lYDPtxdxlRXhZzQ5lfqlCj7PR+drKh9RvMu6C24N1q04w== +"@firebase/auth-interop-types@0.2.1": + version "0.2.1" + resolved "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz#78884f24fa539e34a06c03612c75f222fcc33742" + integrity sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg== + +"@firebase/component@0.6.4": + version "0.6.4" + resolved "https://registry.npmjs.org/@firebase/component/-/component-0.6.4.tgz#8981a6818bd730a7554aa5e0516ffc9b1ae3f33d" + integrity sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA== dependencies: - "@firebase/app-types" "0.7.0" - "@firebase/util" "1.6.0" + "@firebase/util" "1.9.3" + tslib "^2.1.0" -"@firebase/database@0.12.8": - version "0.12.8" - resolved "https://registry.npmjs.org/@firebase/database/-/database-0.12.8.tgz#11a1b6752ba0614892af15c71958e00ce16f5824" - integrity sha512-JBQVfFLzfhxlQbl4OU6ov9fdsddkytBQdtSSR49cz48homj38ccltAhK6seum+BI7f28cV2LFHF9672lcN+qxA== +"@firebase/database-compat@^0.3.4": + version "0.3.4" + resolved "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.3.4.tgz#4e57932f7a5ba761cd5ac946ab6b6ab3f660522c" + integrity sha512-kuAW+l+sLMUKBThnvxvUZ+Q1ZrF/vFJ58iUY9kAcbX48U03nVzIF6Tmkf0p3WVQwMqiXguSgtOPIB6ZCeF+5Gg== dependencies: - "@firebase/auth-interop-types" "0.1.6" - "@firebase/component" "0.5.13" - "@firebase/logger" "0.3.2" - "@firebase/util" "1.5.2" - faye-websocket "0.11.4" + "@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" -"@firebase/logger@0.3.2": - version "0.3.2" - resolved "https://registry.npmjs.org/@firebase/logger/-/logger-0.3.2.tgz#5046ffa8295c577846d54b6ca95645a03809800e" - integrity sha512-lzLrcJp9QBWpo40OcOM9B8QEtBw2Fk1zOZQdvv+rWS6gKmhQBCEMc4SMABQfWdjsylBcDfniD1Q+fUX1dcBTXA== +"@firebase/database-types@0.10.4", "@firebase/database-types@^0.10.4": + version "0.10.4" + resolved "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.10.4.tgz#47ba81113512dab637abace61cfb65f63d645ca7" + integrity sha512-dPySn0vJ/89ZeBac70T+2tWWPiJXWbmRygYv0smT5TfE3hDrQ09eKMF3Y+vMlTdrMWq7mUdYW5REWPSGH4kAZQ== dependencies: + "@firebase/app-types" "0.9.0" + "@firebase/util" "1.9.3" + +"@firebase/database@0.14.4": + version "0.14.4" + resolved "https://registry.npmjs.org/@firebase/database/-/database-0.14.4.tgz#9e7435a16a540ddfdeb5d99d45618e6ede179aa6" + integrity sha512-+Ea/IKGwh42jwdjCyzTmeZeLM3oy1h0mFPsTy6OqCWzcu/KFqRAr5Tt1HRCOBlNOdbh84JPZC47WLU18n2VbxQ== + 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" -"@firebase/util@1.5.2": - version "1.5.2" - resolved "https://registry.npmjs.org/@firebase/util/-/util-1.5.2.tgz#bdd2bc11c956a8a6a0fa25fbd752a13e033558bc" - integrity sha512-YvBH2UxFcdWG2HdFnhxZptPl2eVFlpOyTH66iDo13JPEYraWzWToZ5AMTtkyRHVmu7sssUpQlU9igy1KET7TOw== +"@firebase/logger@0.4.0": + version "0.4.0" + resolved "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz#15ecc03c452525f9d47318ad9491b81d1810f113" + integrity sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA== dependencies: tslib "^2.1.0" -"@firebase/util@1.6.0": - version "1.6.0" - resolved "https://registry.npmjs.org/@firebase/util/-/util-1.6.0.tgz#31aea6bba3ee98fc83a60eb189cb187243f4ef4b" - integrity sha512-6+hhqb4Zzjoo12xofTDHPkgW3FnN4ydBsjd5X2KuQI268DR3W3Ld64W/gkKPZrKRgUxeNeb+pykfP3qRe7q+vA== +"@firebase/util@1.9.3": + version "1.9.3" + resolved "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz#45458dd5cd02d90e55c656e84adf6f3decf4b7ed" + integrity sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA== dependencies: tslib "^2.1.0" -"@google-cloud/firestore@^4.15.1": - version "4.15.1" - resolved "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-4.15.1.tgz#ed764fc76823ce120e68fe8c27ef1edd0650cd93" - integrity sha512-2PWsCkEF1W02QbghSeRsNdYKN1qavrHBP3m72gPDMHQSYrGULOaTi7fSJquQmAtc4iPVB2/x6h80rdLHTATQtA== +"@google-cloud/firestore@^6.6.0": + version "6.8.0" + resolved "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-6.8.0.tgz#d8c852844c381afaf62592796606c10e178400b5" + integrity sha512-JRpk06SmZXLGz0pNx1x7yU3YhkUXheKgH5hbDZ4kMsdhtfV5qPLJLRI4wv69K0cZorIk+zTMOwptue7hizo0eA== dependencies: fast-deep-equal "^3.1.1" functional-red-black-tree "^1.0.1" - google-gax "^2.24.1" - protobufjs "^6.8.6" + google-gax "^3.5.7" + protobufjs "^7.2.5" "@google-cloud/paginator@^3.0.7": version "3.0.7" @@ -99,70 +96,64 @@ arrify "^2.0.0" extend "^3.0.2" -"@google-cloud/projectify@^2.0.0": - version "2.1.1" - resolved "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.1.1.tgz#ae6af4fee02d78d044ae434699a630f8df0084ef" - integrity sha512-+rssMZHnlh0twl122gXY4/aCrk0G1acBqkHFfYddtsqpYXGxA29nj9V5V9SfC+GyOG00l650f6lG9KL+EpFEWQ== +"@google-cloud/projectify@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz#302b25f55f674854dce65c2532d98919b118a408" + integrity sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA== -"@google-cloud/promisify@^2.0.0": - version "2.0.4" - resolved "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.4.tgz#9d8705ecb2baa41b6b2673f3a8e9b7b7e1abc52a" - integrity sha512-j8yRSSqswWi1QqUGKVEKOG03Q7qOoZP6/h2zN2YO+F5h2+DHU0bSrHCK9Y7lo2DI9fBd8qGAw795sf+3Jva4yA== +"@google-cloud/promisify@^3.0.0": + version "3.0.1" + resolved "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-3.0.1.tgz#8d724fb280f47d1ff99953aee0c1669b25238c2e" + integrity sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA== -"@google-cloud/storage@^5.18.3": - version "5.19.3" - resolved "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.19.3.tgz#0624f57a7ed5a4e3e0e23d5aaab849cb015f903a" - integrity sha512-l+8X0BoA7rg9jyZaS4p2DwMg1Ivju+VAL6PeQZE1u2q52LQ0KemrZmdQWhtrplHYo8UdYtqpbj4A6Fc5fKDZdg== +"@google-cloud/storage@^6.9.5": + version "6.12.0" + resolved "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.12.0.tgz#a5d3093cc075252dca5bd19a3cfda406ad3a9de1" + integrity sha512-78nNAY7iiZ4O/BouWMWTD/oSF2YtYgYB3GZirn0To6eBOugjXVoK+GXgUXOl+HlqbAOyHxAVXOlsj3snfbQ1dw== dependencies: "@google-cloud/paginator" "^3.0.7" - "@google-cloud/projectify" "^2.0.0" - "@google-cloud/promisify" "^2.0.0" + "@google-cloud/projectify" "^3.0.0" + "@google-cloud/promisify" "^3.0.0" abort-controller "^3.0.0" - arrify "^2.0.0" async-retry "^1.3.3" compressible "^2.0.12" - configstore "^5.0.0" - date-and-time "^2.0.0" duplexify "^4.0.0" ent "^2.2.0" extend "^3.0.2" - gaxios "^4.0.0" - get-stream "^6.0.0" - google-auth-library "^7.14.1" - hash-stream-validation "^0.2.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" - pumpify "^2.0.0" - retry-request "^4.2.2" - snakeize "^0.1.0" - stream-events "^1.0.4" - teeny-request "^7.1.3" - xdg-basedir "^4.0.0" - -"@grpc/grpc-js@~1.6.0": - version "1.6.7" - resolved "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.7.tgz#4c4fa998ff719fe859ac19fe977fdef097bb99aa" - integrity sha512-eBM03pu9hd3VqDQG+kHahiG1x80RGkkqqRb1Pchcwqej/KkAH95gAvKs6laqaHCycYaPK+TKuNQnOz9UXYA8qw== - dependencies: - "@grpc/proto-loader" "^0.6.4" + retry-request "^5.0.0" + teeny-request "^8.0.0" + uuid "^8.0.0" + +"@grpc/grpc-js@~1.8.0": + version "1.8.21" + resolved "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.21.tgz#d282b122c71227859bf6c5866f4c40f4a2696513" + integrity sha512-KeyQeZpxeEBSqFVTi3q2K7PiPXmgBfECc4updA1ejCLjYmoAlvvM3ZMp5ztTDUCUQmoY3CpDxvchjO1+rFkoHg== + dependencies: + "@grpc/proto-loader" "^0.7.0" "@types/node" ">=12.12.47" -"@grpc/proto-loader@^0.6.1", "@grpc/proto-loader@^0.6.4": - version "0.6.9" - resolved "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.9.tgz#4014eef366da733f8e04a9ddd7376fe8a58547b7" - integrity sha512-UlcCS8VbsU9d3XTXGiEVFonN7hXk+oMXZtoHHG2oSA1/GcDP1q6OUgs20PzHDGizzyi8ufGSUDlk3O2NyY7leg== +"@grpc/proto-loader@^0.7.0": + version "0.7.10" + resolved "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz#6bf26742b1b54d0a473067743da5d3189d06d720" + integrity sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ== dependencies: - "@types/long" "^4.0.1" lodash.camelcase "^4.3.0" - long "^4.0.0" - protobufjs "^6.10.0" - yargs "^16.2.0" + long "^5.0.0" + protobufjs "^7.2.4" + yargs "^17.7.2" -"@panva/asn1.js@^1.0.0": - version "1.0.0" - resolved "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz#dd55ae7b8129e02049f009408b97c61ccf9032f6" - integrity sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw== +"@jsdoc/salty@^0.2.1": + version "0.2.7" + resolved "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.7.tgz#98ddce519fd95d7bee605a658fabf6e8cbf7556d" + integrity sha512-mh8LbS9d4Jq84KLw8pzho7XC2q2/IJGiJss3xwRoLD1A+EE16SjN4PfaG4jRCzKegTFLlN0Zd8SdUPE6XdoPFg== + dependencies: + lodash "^4.17.21" "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" @@ -242,14 +233,6 @@ resolved "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== -"@types/express-jwt@0.0.42": - version "0.0.42" - resolved "https://registry.npmjs.org/@types/express-jwt/-/express-jwt-0.0.42.tgz#4f04e1fadf9d18725950dc041808a4a4adf7f5ae" - integrity sha512-WszgUddvM1t5dPpJ3LhWNH8kfNN8GPIBrAGxgIYXVCEGx6Bx4A036aAuf/r5WH9DIEdlmp7gHOYvSM6U87B0ag== - dependencies: - "@types/express" "*" - "@types/express-unless" "*" - "@types/express-serve-static-core@*": version "4.17.24" resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz#ea41f93bf7e0d59cd5a76665068ed6aab6815c07" @@ -259,31 +242,15 @@ "@types/qs" "*" "@types/range-parser" "*" -"@types/express-serve-static-core@^4.17.18": - version "4.17.28" - resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" - integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== +"@types/express-serve-static-core@^4.17.33": + version "4.17.43" + resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz#10d8444be560cb789c4735aea5eac6e5af45df54" + integrity sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg== dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" - -"@types/express-unless@*": - version "0.5.3" - resolved "https://registry.npmjs.org/@types/express-unless/-/express-unless-0.5.3.tgz#271f8603617445568ed0d6efe25a7d2f338544c1" - integrity sha512-TyPLQaF6w8UlWdv4gj8i46B+INBVzURBNRahCozCSXfsK2VTlL1wNyTlMKw817VHygBtlcl5jfnPadlydr06Yw== - dependencies: - "@types/express" "*" - -"@types/express@*": - version "4.17.13" - resolved "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" - integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.18" - "@types/qs" "*" - "@types/serve-static" "*" + "@types/send" "*" "@types/express@4.17.3": version "4.17.3" @@ -294,16 +261,64 @@ "@types/express-serve-static-core" "*" "@types/serve-static" "*" -"@types/long@^4.0.0", "@types/long@^4.0.1": +"@types/express@^4.17.17": + version "4.17.21" + resolved "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/glob@*": + version "8.1.0" + resolved "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc" + integrity sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w== + dependencies: + "@types/minimatch" "^5.1.2" + "@types/node" "*" + +"@types/jsonwebtoken@^9.0.2": + version "9.0.6" + resolved "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz#d1af3544d99ad992fb6681bbe60676e06b032bd3" + integrity sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw== + dependencies: + "@types/node" "*" + +"@types/linkify-it@*": + version "3.0.5" + resolved "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz#1e78a3ac2428e6d7e6c05c1665c242023a4601d8" + integrity sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw== + +"@types/long@^4.0.0": version "4.0.1" resolved "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9" integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== +"@types/markdown-it@^12.2.3": + version "12.2.3" + resolved "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz#0d6f6e5e413f8daaa26522904597be3d6cd93b51" + integrity sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ== + dependencies: + "@types/linkify-it" "*" + "@types/mdurl" "*" + +"@types/mdurl@*": + version "1.0.5" + resolved "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz#3e0d2db570e9fb6ccb2dc8fde0be1d79ac810d39" + integrity sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA== + "@types/mime@^1": version "1.3.2" resolved "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== +"@types/minimatch@^5.1.2": + version "5.1.2" + resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" + integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== + "@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0": version "16.9.6" resolved "https://registry.npmjs.org/@types/node/-/node-16.9.6.tgz#040a64d7faf9e5d9e940357125f0963012e66f04" @@ -319,6 +334,22 @@ resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== +"@types/rimraf@^3.0.2": + version "3.0.2" + resolved "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz#a63d175b331748e5220ad48c901d7bbf1f44eef8" + integrity sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ== + dependencies: + "@types/glob" "*" + "@types/node" "*" + +"@types/send@*": + version "0.17.4" + resolved "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + "@types/serve-static@*": version "1.13.10" resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" @@ -342,6 +373,16 @@ accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.9.0: + version "8.11.3" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== + agent-base@6: version "6.0.2" resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -354,13 +395,18 @@ ansi-regex@^5.0.1: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^4.0.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -378,6 +424,11 @@ async-retry@^1.3.3: dependencies: retry "0.13.1" +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + base64-js@^1.3.0: version "1.5.1" resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -388,6 +439,11 @@ bignumber.js@^9.0.0: resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== +bluebird@^3.7.2: + version "3.7.2" + resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + body-parser@1.19.0: version "1.19.0" resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" @@ -404,6 +460,13 @@ body-parser@1.19.0: raw-body "2.4.0" type-is "~1.6.17" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" @@ -414,13 +477,28 @@ bytes@3.1.0: resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== +catharsis@^0.9.0: + version "0.9.0" + resolved "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz#40382a168be0e6da308c277d3a2b3eb40c7d2121" + integrity sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A== + dependencies: + lodash "^4.17.15" + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: string-width "^4.2.0" - strip-ansi "^6.0.0" + strip-ansi "^6.0.1" wrap-ansi "^7.0.0" color-convert@^2.0.1: @@ -442,18 +520,6 @@ compressible@^2.0.12: dependencies: mime-db ">= 1.43.0 < 2" -configstore@^5.0.0: - version "5.0.1" - resolved "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" - integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== - 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" - content-disposition@0.5.3: version "0.5.3" resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -484,16 +550,6 @@ cors@^2.8.5: object-assign "^4" vary "^1" -crypto-random-string@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" - integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== - -date-and-time@^2.0.0: - version "2.3.1" - resolved "https://registry.npmjs.org/date-and-time/-/date-and-time-2.3.1.tgz#006675ec4943a0a5f85810e3a3fd6aa96f6130c9" - integrity sha512-OaIRmSJXifwEN21rMVVDs0Kz8uhJ3wWPYd86atkRiqN54liaMQYEbbrgjZQea75YXOBWL4ZFb3rG/waenw1TEg== - debug@2.6.9: version "2.6.9" resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -515,6 +571,11 @@ debug@^4.3.4: dependencies: ms "2.1.2" +deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + depd@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -525,21 +586,7 @@ destroy@~1.0.4: resolved "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= -dicer@^0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872" - integrity sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA== - dependencies: - streamsearch "0.1.2" - -dot-prop@^5.2.0: - version "5.3.0" - resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" - integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== - dependencies: - is-obj "^2.0.0" - -duplexify@^4.0.0, duplexify@^4.1.1: +duplexify@^4.0.0: version "4.1.2" resolved "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0" integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw== @@ -571,7 +618,7 @@ encodeurl@~1.0.2: resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -end-of-stream@^1.1.0, end-of-stream@^1.4.1: +end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -583,6 +630,11 @@ ent@^2.2.0: resolved "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= +entities@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" + integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== + escalade@^3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -593,6 +645,57 @@ escape-html@~1.0.3: resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escodegen@^1.13.0: + version "1.14.3" + resolved "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" + integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== + dependencies: + esprima "^4.0.1" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +eslint-visitor-keys@^3.4.1: + version "3.4.3" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +espree@^9.0.0: + version "9.6.1" + resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esprima@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +estraverse@^4.2.0: + version "4.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0: + version "5.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + etag@~1.8.1: version "1.8.1" resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" @@ -649,11 +752,23 @@ fast-deep-equal@^3.1.1: resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz#ec02ac8e01ab8a319af182dae2681213cfe9ce53" integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig== +fast-xml-parser@^4.2.2: + version "4.3.5" + resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.5.tgz#e2f2a2ae8377e9c3dc321b151e58f420ca7e5ccc" + integrity sha512-sWvP1Pl8H03B8oFJpFR3HE31HUfwtX7Rlf9BNsvdpujD4n7WMhfmu8h9wOV2u+c1k0ZilTADhPqypzx2J690ZQ== + dependencies: + strnum "^1.0.5" + faye-websocket@0.11.4: version "0.11.4" resolved "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" @@ -674,27 +789,27 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -firebase-admin@10.2.0: - version "10.2.0" - resolved "https://registry.npmjs.org/firebase-admin/-/firebase-admin-10.2.0.tgz#e5a97d35819b5872e3e29384b48f67dab59ede04" - integrity sha512-6ehn5J9UEFgi4+naqYvozmGpnZae3cJLdwSkSsDc8/Y0eTBjVMFdf9N2ft7N81UNHA0N5DknOyXhlsdAdyBLCA== +firebase-admin@11.10.1: + version "11.10.1" + resolved "https://registry.npmjs.org/firebase-admin/-/firebase-admin-11.10.1.tgz#5f0f83a44627e89938d350c5e4bbac76596c963e" + integrity sha512-atv1E6GbuvcvWaD3eHwrjeP5dAVs+EaHEJhu9CThMzPY6In8QYDiUR6tq5SwGl4SdA/GcAU0nhwWc/FSJsAzfQ== dependencies: - "@firebase/database-compat" "^0.1.8" - "@firebase/database-types" "^0.9.7" + "@fastify/busboy" "^1.2.1" + "@firebase/database-compat" "^0.3.4" + "@firebase/database-types" "^0.10.4" "@types/node" ">=12.12.47" - dicer "^0.3.0" - jsonwebtoken "^8.5.1" - jwks-rsa "^2.0.2" + jsonwebtoken "^9.0.0" + jwks-rsa "^3.0.1" node-forge "^1.3.1" - uuid "^8.3.2" + uuid "^9.0.0" optionalDependencies: - "@google-cloud/firestore" "^4.15.1" - "@google-cloud/storage" "^5.18.3" + "@google-cloud/firestore" "^6.6.0" + "@google-cloud/storage" "^6.9.5" -firebase-functions@3.21.0: - version "3.21.0" - resolved "https://registry.npmjs.org/firebase-functions/-/firebase-functions-3.21.0.tgz#46b4c771781891929408bd4424959fe552d6cd6c" - integrity sha512-Xl0EFV05+RSB9hJHlo12LguoRqAmpSXmBnpI0MANeNj07dGW0QCWPHtaAewxYEzRS3RfSCL8WH12rjvo0PPKGw== +firebase-functions@3.24.1: + version "3.24.1" + resolved "https://registry.npmjs.org/firebase-functions/-/firebase-functions-3.24.1.tgz#50d13274c4ae96b2308a67e9fc76f1a74cff690d" + integrity sha512-GYhoyOV0864HFMU1h/JNBXYNmDk2MlbvU7VO/5qliHX6u/6vhSjTJjlyCG4leDEI8ew8IvmkIC5QquQ1U8hAuA== dependencies: "@types/cors" "^2.8.5" "@types/express" "4.17.3" @@ -713,28 +828,32 @@ fresh@0.5.2: resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gaxios@^4.0.0: - version "4.3.3" - resolved "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz#d44bdefe52d34b6435cc41214fdb160b64abfc22" - integrity sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA== +gaxios@^5.0.0, gaxios@^5.0.1: + version "5.1.3" + resolved "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz#f7fa92da0fe197c846441e5ead2573d4979e9013" + integrity sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA== 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" + node-fetch "^2.6.9" -gcp-metadata@^4.2.0: - version "4.3.1" - resolved "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz#fb205fe6a90fef2fd9c85e6ba06e5559ee1eefa9" - integrity sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A== +gcp-metadata@^5.3.0: + version "5.3.0" + resolved "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz#6f45eb473d0cb47d15001476b48b663744d25408" + integrity sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w== dependencies: - gaxios "^4.0.0" + gaxios "^5.0.0" json-bigint "^1.0.0" get-caller-file@^2.0.5: @@ -742,70 +861,78 @@ get-caller-file@^2.0.5: resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== +glob@^8.0.0: + version "8.1.0" + resolved "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" -google-auth-library@^7.14.0, google-auth-library@^7.14.1: - version "7.14.1" - resolved "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz#e3483034162f24cc71b95c8a55a210008826213c" - integrity sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA== +google-auth-library@^8.0.1, google-auth-library@^8.0.2: + version "8.9.0" + resolved "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.9.0.tgz#15a271eb2ec35d43b81deb72211bd61b1ef14dd0" + integrity sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg== 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" + gaxios "^5.0.0" + gcp-metadata "^5.3.0" + gtoken "^6.1.0" jws "^4.0.0" lru-cache "^6.0.0" -google-gax@^2.24.1: - version "2.30.2" - resolved "https://registry.npmjs.org/google-gax/-/google-gax-2.30.2.tgz#ba16940bad5a116099547a5966fdf83f6c026356" - integrity sha512-BCNCT26kb0iC52zj2SosyOZMhI5sVfXuul1h0Aw5uT9nGAbmS5eOvQ49ft53ft6XotDj11sUSDV6XESEiQqCqg== +google-gax@^3.5.7: + version "3.6.1" + resolved "https://registry.npmjs.org/google-gax/-/google-gax-3.6.1.tgz#02c78fc496f5adf86f2ca9145545f4b6575f6118" + integrity sha512-g/lcUjGcB6DSw2HxgEmCDOrI/CByOwqRvsuUvNalHUK2iPPPlmAIpbMbl62u0YufGMr8zgE3JL7th6dCb1Ry+w== dependencies: - "@grpc/grpc-js" "~1.6.0" - "@grpc/proto-loader" "^0.6.1" + "@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 "^7.14.0" + 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 "^0.1.8" - protobufjs "6.11.2" - retry-request "^4.0.0" + proto3-json-serializer "^1.0.0" + protobufjs "7.2.4" + protobufjs-cli "1.1.1" + retry-request "^5.0.0" -google-p12-pem@^3.1.3: - version "3.1.4" - resolved "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz#123f7b40da204de4ed1fbf2fd5be12c047fc8b3b" - integrity sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg== +google-p12-pem@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-4.0.1.tgz#82841798253c65b7dc2a4e5fe9df141db670172a" + integrity sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ== dependencies: node-forge "^1.3.1" -graceful-fs@^4.1.2: - version "4.2.8" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== +graceful-fs@^4.1.9: + version "4.2.11" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -gtoken@^5.0.4: - version "5.3.2" - resolved "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz#deb7dc876abe002178e0515e383382ea9446d58f" - integrity sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ== +gtoken@^6.1.0: + version "6.1.2" + resolved "https://registry.npmjs.org/gtoken/-/gtoken-6.1.2.tgz#aeb7bdb019ff4c3ba3ac100bbe7b6e74dce0e8bc" + integrity sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ== dependencies: - gaxios "^4.0.0" - google-p12-pem "^3.1.3" + gaxios "^5.0.1" + google-p12-pem "^4.0.0" jws "^4.0.0" -hash-stream-validation@^0.2.2: - version "0.2.4" - resolved "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz#ee68b41bf822f7f44db1142ec28ba9ee7ccb7512" - integrity sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ== +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== http-errors@1.7.2: version "1.7.2" @@ -858,21 +985,24 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== inherits@2.0.3: version "2.0.3" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -inherits@2.0.4, inherits@^2.0.3: - version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" @@ -883,11 +1013,6 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - is-stream-ended@^0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda" @@ -898,17 +1023,38 @@ is-stream@^2.0.0: resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== -is-typedarray@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +jose@^4.14.6: + version "4.15.5" + resolved "https://registry.npmjs.org/jose/-/jose-4.15.5.tgz#6475d0f467ecd3c630a1b5dadd2735a7288df706" + integrity sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg== -jose@^2.0.5: - version "2.0.5" - resolved "https://registry.npmjs.org/jose/-/jose-2.0.5.tgz#29746a18d9fff7dcf9d5d2a6f62cb0c7cd27abd3" - integrity sha512-BAiDNeDKTMgk4tvD0BbxJ8xHEHBZgpeRZ1zGPPsitSyMgjoMWiLGYAE7H7NpP5h0lPppQajQs871E8NHUrzVPA== +js2xmlparser@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz#2a1fdf01e90585ef2ae872a01bc169c6a8d5e60a" + integrity sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA== dependencies: - "@panva/asn1.js" "^1.0.0" + xmlcreate "^2.0.4" + +jsdoc@^4.0.0: + version "4.0.2" + resolved "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz#a1273beba964cf433ddf7a70c23fd02c3c60296e" + integrity sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg== + 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" json-bigint@^1.0.0: version "1.0.0" @@ -917,10 +1063,10 @@ json-bigint@^1.0.0: dependencies: bignumber.js "^9.0.0" -jsonwebtoken@^8.5.1: - version "8.5.1" - resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" - integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== +jsonwebtoken@^9.0.0: + version "9.0.2" + resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" + integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== dependencies: jws "^3.2.2" lodash.includes "^4.3.0" @@ -931,7 +1077,7 @@ jsonwebtoken@^8.5.1: lodash.isstring "^4.0.1" lodash.once "^4.0.0" ms "^2.1.1" - semver "^5.6.0" + semver "^7.5.4" jwa@^1.4.1: version "1.4.1" @@ -951,16 +1097,17 @@ jwa@^2.0.0: ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" -jwks-rsa@^2.0.2: - version "2.1.0" - resolved "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.1.0.tgz#00e4c5eecc40ba41de199b71ab7e489807a1727f" - integrity sha512-GKOSDBWWBCiQTzawei6mEdRQvji5gecj8F9JwMt0ZOPnBPSmTjo5CKFvvbhE7jGPkU159Cpi0+OTLuABFcNOQQ== +jwks-rsa@^3.0.1: + version "3.1.0" + resolved "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.1.0.tgz#50406f23e38c9b2682cd437f824d7d61aa983171" + integrity sha512-v7nqlfezb9YfHHzYII3ef2a2j1XnGeSE/bK3WfumaYCqONAIstJbrEGapz4kadScZzEt7zYCN7bucj8C0Mv/Rg== dependencies: - "@types/express-jwt" "0.0.42" + "@types/express" "^4.17.17" + "@types/jsonwebtoken" "^9.0.2" debug "^4.3.4" - jose "^2.0.5" + jose "^4.14.6" limiter "^1.1.5" - lru-memoizer "^2.1.4" + lru-memoizer "^2.2.0" jws@^3.2.2: version "3.2.2" @@ -978,11 +1125,33 @@ jws@^4.0.0: jwa "^2.0.0" safe-buffer "^5.0.1" +klaw@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz#b11bec9cf2492f06756d6e809ab73a2910259146" + integrity sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g== + dependencies: + graceful-fs "^4.1.9" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + limiter@^1.1.5: version "1.1.5" resolved "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz#8f92a25b3b16c6131293a0cc834b4a838a2aa7c2" integrity sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA== +linkify-it@^3.0.1: + version "3.0.3" + resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e" + integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ== + dependencies: + uc.micro "^1.0.1" + lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" @@ -1028,15 +1197,15 @@ lodash.once@^4.0.0: resolved "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= -lodash@^4.17.14: +lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -long@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" - integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== +long@^5.0.0: + version "5.2.3" + resolved "https://registry.npmjs.org/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" + integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== lru-cache@^6.0.0: version "6.0.0" @@ -1053,20 +1222,39 @@ lru-cache@~4.0.0: pseudomap "^1.0.1" yallist "^2.0.0" -lru-memoizer@^2.1.4: - version "2.1.4" - resolved "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.1.4.tgz#b864d92b557f00b1eeb322156a0409cb06dafac6" - integrity sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ== +lru-memoizer@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.2.0.tgz#b9d90c91637b4b1a423ef76f3156566691293df8" + integrity sha512-QfOZ6jNkxCcM/BkIPnFsqDhtrazLRsghi9mBwFAzol5GCvj4EkFT899Za3+QwikCg5sRX8JstioBDwOxEyzaNw== dependencies: lodash.clonedeep "^4.5.0" lru-cache "~4.0.0" -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== +markdown-it-anchor@^8.4.1: + version "8.6.7" + resolved "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz#ee6926daf3ad1ed5e4e3968b1740eef1c6399634" + integrity sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA== + +markdown-it@^12.3.2: + version "12.3.2" + resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90" + integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg== dependencies: - semver "^6.0.0" + argparse "^2.0.1" + entities "~2.1.0" + linkify-it "^3.0.1" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +marked@^4.0.10: + version "4.3.0" + resolved "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== media-typer@0.3.0: version "0.3.0" @@ -1110,6 +1298,23 @@ mime@^3.0.0: resolved "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0: + version "1.2.8" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + ms@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -1142,6 +1347,13 @@ node-fetch@^2.6.1, node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" +node-fetch@^2.6.9: + version "2.7.0" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-forge@^1.3.1: version "1.3.1" resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -1164,13 +1376,25 @@ on-finished@~2.3.0: dependencies: ee-first "1.1.1" -once@^1.3.1, once@^1.4.0: +once@^1.3.0, once@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + 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" + p-limit@^3.0.1: version "3.1.0" resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" @@ -1188,17 +1412,38 @@ path-to-regexp@0.1.7: resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= -proto3-json-serializer@^0.1.8: - version "0.1.8" - resolved "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-0.1.8.tgz#f80f9afc1efe5ed9a9856bbbd17dc7cabd7ce9a3" - integrity sha512-ACilkB6s1U1gWnl5jtICpnDai4VCxmI9GFxuEaYdxtDG2oVI3sVFIUsvUZcQbJgtPM6p+zqKbjTKQZp6Y4FpQw== +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== + +proto3-json-serializer@^1.0.0: + version "1.1.1" + resolved "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-1.1.1.tgz#1b5703152b6ce811c5cdcc6468032caf53521331" + integrity sha512-AwAuY4g9nxx0u52DnSMkqqgyLHaW/XaPLtaAo3y/ZCfeaQB/g4YDH4kb8Wc/mWzWvu0YjOznVnfn373MVZZrgw== dependencies: - protobufjs "^6.11.2" + protobufjs "^7.0.0" -protobufjs@6.11.2, protobufjs@^6.10.0, protobufjs@^6.11.2, protobufjs@^6.8.6: - version "6.11.2" - resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz#de39fabd4ed32beaa08e9bb1e30d08544c1edf8b" - integrity sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw== +protobufjs-cli@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.1.tgz#f531201b1c8c7772066aa822bf9a08318b24a704" + integrity sha512-VPWMgIcRNyQwWUv8OLPyGQ/0lQY/QTQAVN5fh+XzfDwsVw1FZ2L3DM/bcBf8WPiRz2tNpaov9lPZfNcmNo6LXA== + 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" + +protobufjs@7.2.4: + version "7.2.4" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz#3fc1ec0cdc89dd91aef9ba6037ba07408485c3ae" + integrity sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -1210,9 +1455,26 @@ protobufjs@6.11.2, protobufjs@^6.10.0, protobufjs@^6.11.2, protobufjs@^6.8.6: "@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" + long "^5.0.0" + +protobufjs@^7.0.0, protobufjs@^7.2.4, protobufjs@^7.2.5: + version "7.2.6" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz#4a0ccd79eb292717aacf07530a07e0ed20278215" + integrity sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw== + 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" proxy-addr@~2.0.5: version "2.0.7" @@ -1227,23 +1489,6 @@ pseudomap@^1.0.1: resolved "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pumpify@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz#abfc7b5a621307c728b551decbbefb51f0e4aa1e" - integrity sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw== - dependencies: - duplexify "^4.1.1" - inherits "^2.0.3" - pump "^3.0.0" - qs@6.7.0: version "6.7.0" resolved "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" @@ -1278,10 +1523,17 @@ require-directory@^2.1.1: resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= -retry-request@^4.0.0, retry-request@^4.2.2: - version "4.2.2" - resolved "https://registry.npmjs.org/retry-request/-/retry-request-4.2.2.tgz#b7d82210b6d2651ed249ba3497f07ea602f1a903" - integrity sha512-xA93uxUD/rogV7BV59agW/JHPGXeREMWiZc9jhcwY4YdZ7QOtC7qbomYg0n4wyk2lJhggjvKvhNX8wln/Aldhg== +requizzle@^0.2.3: + version "0.2.4" + resolved "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz#319eb658b28c370f0c20f968fa8ceab98c13d27c" + integrity sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw== + dependencies: + lodash "^4.17.21" + +retry-request@^5.0.0: + version "5.0.2" + resolved "https://registry.npmjs.org/retry-request/-/retry-request-5.0.2.tgz#143d85f90c755af407fcc46b7166a4ba520e44da" + integrity sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ== dependencies: debug "^4.1.1" extend "^3.0.2" @@ -1306,15 +1558,12 @@ safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@~5.2.0: resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -semver@^5.6.0: - version "5.7.1" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0: - version "6.3.0" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.1.2, semver@^7.5.4: + version "7.6.0" + resolved "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" send@0.17.1: version "0.17.1" @@ -1350,22 +1599,17 @@ setprototypeof@1.1.1: resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== -signal-exit@^3.0.2: - version "3.0.4" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.4.tgz#366a4684d175b9cab2081e3681fda3747b6c51d7" - integrity sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q== - -snakeize@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz#10c088d8b58eb076b3229bb5a04e232ce126422d" - integrity sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0= +source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== "statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= -stream-events@^1.0.4, stream-events@^1.0.5: +stream-events@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5" integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== @@ -1377,12 +1621,7 @@ stream-shift@^1.0.0: resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== -streamsearch@0.1.2: - version "0.1.2" - resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" - integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= - -string-width@^4.1.0, string-width@^4.2.0: +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -1405,21 +1644,48 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-json-comments@^3.1.0: + version "3.1.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + stubs@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" integrity sha1-6NK6H6nJBXAwPAMLaQD31fiavls= -teeny-request@^7.1.3: +supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.npmjs.org/teeny-request/-/teeny-request-7.2.0.tgz#41347ece068f08d741e7b86df38a4498208b2633" - integrity sha512-SyY0pek1zWsi0LRVAALem+avzMLc33MKW/JLLakdP4s9+D7+jHcy5x6P+h94g2QNZsAqQNfX5lsbd3WSeJXrrw== + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +teeny-request@^8.0.0: + version "8.0.3" + resolved "https://registry.npmjs.org/teeny-request/-/teeny-request-8.0.3.tgz#5cb9c471ef5e59f2fca8280dc3c5909595e6ca24" + integrity sha512-jJZpA5He2y52yUhA7pyAGZlgQpcB+xLjcN0eUFxr9c8hP/H7uOXbBNVo/O0C/xVfJLJs680jvkFgVJEEvk9+ww== dependencies: http-proxy-agent "^5.0.0" https-proxy-agent "^5.0.0" node-fetch "^2.6.1" stream-events "^1.0.5" - uuid "^8.0.0" + uuid "^9.0.0" + +text-decoding@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz#38a5692d23b5c2b12942d6e245599cb58b1bc52f" + integrity sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA== + +tmp@^0.2.1: + version "0.2.3" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" + integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== toidentifier@1.0.0: version "1.0.0" @@ -1436,6 +1702,13 @@ tslib@^2.1.0: resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== + dependencies: + prelude-ls "~1.1.2" + type-is@~1.6.17, type-is@~1.6.18: version "1.6.18" resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -1444,19 +1717,20 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== -unique-string@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" - integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== - dependencies: - crypto-random-string "^2.0.0" +uglify-js@^3.7.7: + version "3.17.4" + resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" + integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== + +underscore@~1.13.2: + version "1.13.6" + resolved "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" + integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" @@ -1473,11 +1747,16 @@ utils-merge@1.0.1: resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= -uuid@^8.0.0, uuid@^8.3.2: +uuid@^8.0.0: version "8.3.2" resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9.0.0: + version "9.0.1" + resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -1510,6 +1789,11 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" +word-wrap@~1.2.3: + version "1.2.5" + resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -1524,20 +1808,10 @@ wrappy@1: resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write-file-atomic@^3.0.0: - version "3.0.3" - resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -xdg-basedir@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" - integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== +xmlcreate@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz#0c5ab0f99cdd02a81065fa9cd8f8ae87624889be" + integrity sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg== y18n@^5.0.5: version "5.0.8" @@ -1554,25 +1828,25 @@ yallist@^4.0.0: resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@^20.2.2: - version "20.2.9" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^16.2.0: - version "16.2.0" - resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: - cliui "^7.0.2" + cliui "^8.0.1" escalade "^3.1.1" get-caller-file "^2.0.5" require-directory "^2.1.1" - string-width "^4.2.0" + string-width "^4.2.3" y18n "^5.0.5" - yargs-parser "^20.2.2" + yargs-parser "^21.1.1" yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== \ No newline at end of file diff --git a/packages/auth-compat/demo/package.json b/packages/auth-compat/demo/package.json index 6c33ac705b7..098a3ad3007 100644 --- a/packages/auth-compat/demo/package.json +++ b/packages/auth-compat/demo/package.json @@ -39,7 +39,7 @@ "repository": { "directory": "packages/auth-compat/demo", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/auth-compat/demo/yarn.lock b/packages/auth-compat/demo/yarn.lock index 2a2d5512b46..02d205be7cb 100644 --- a/packages/auth-compat/demo/yarn.lock +++ b/packages/auth-compat/demo/yarn.lock @@ -2232,9 +2232,9 @@ hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: lru-cache "^6.0.0" http-cache-semantics@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + version "4.1.1" + resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== http-proxy-agent@^4.0.1: version "4.0.1" @@ -2391,9 +2391,9 @@ internal-slot@^1.0.3: side-channel "^1.0.4" ip@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= + version "1.1.9" + resolved "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz#8dfbcc99a754d07f425310b86a99546b1151e396" + integrity sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ== is-arrayish@^0.2.1: version "0.2.1" @@ -2961,9 +2961,9 @@ minimist-options@4.1.0: kind-of "^6.0.3" minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + version "1.2.8" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== minipass-collect@^1.0.2: version "1.0.2" @@ -3990,10 +3990,10 @@ rollup-pluginutils@^2.6.0: dependencies: estree-walker "^0.6.1" -rollup@2.72.1: - version "2.72.1" - resolved "https://registry.npmjs.org/rollup/-/rollup-2.72.1.tgz#861c94790537b10008f0ca0fbc60e631aabdd045" - integrity sha512-NTc5UGy/NWFGpSqF1lFY8z9Adri6uhyMLI6LvPAXdBKoPRFhIIiBUpt+Qg2awixqO3xvzSijjhnb4+QEZwJmxA== +rollup@2.79.1: + version "2.79.1" + resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" + integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== optionalDependencies: fsevents "~2.3.2" @@ -4032,19 +4032,19 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== "semver@2 || 3 || 4 || 5", semver@^5.6.0, semver@^5.7.1: - version "5.7.1" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + version "5.7.2" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== semver@^6.0.0: - version "6.3.0" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + version "6.3.1" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.1.1, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: - version "7.3.5" - resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + version "7.6.0" + resolved "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== dependencies: lru-cache "^6.0.0" @@ -4539,10 +4539,10 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@4.2.2: - version "4.2.2" - resolved "https://registry.npmjs.org/typescript/-/typescript-4.2.2.tgz#1450f020618f872db0ea17317d16d8da8ddb8c4c" - integrity sha512-tbb+NVrLfnsJy3M59lsDgrzWIflR4d4TIUjz+heUnHZwdF7YsrMTKoRERiIvI2lvBG95dfpLxB21WZhys1bgaQ== +typescript@4.7.4: + version "4.7.4" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" + integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== uglify-js@^3.1.4, uglify-js@^3.4.9: version "3.14.2" diff --git a/packages/auth-compat/package.json b/packages/auth-compat/package.json index c3b3cda70ee..adc07c86d33 100644 --- a/packages/auth-compat/package.json +++ b/packages/auth-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth-compat", - "version": "0.5.1", + "version": "0.5.7", "description": "FirebaseAuth compatibility package that uses API style compatible with Firebase@8 and prior versions", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -50,16 +50,16 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/auth": "1.5.1", - "@firebase/auth-types": "0.12.0", - "@firebase/component": "0.6.4", - "@firebase/util": "1.9.3", - "undici": "5.26.5", + "@firebase/auth": "1.7.2", + "@firebase/auth-types": "0.12.1", + "@firebase/component": "0.6.6", + "@firebase/util": "1.9.5", + "undici": "5.28.4", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app-compat": "0.2.25", + "@firebase/app-compat": "0.2.32", "@rollup/plugin-json": "4.1.0", "rollup": "2.79.1", "rollup-plugin-replace": "2.2.0", @@ -70,7 +70,7 @@ "repository": { "directory": "packages/auth-compat", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/auth-interop-types/CHANGELOG.md b/packages/auth-interop-types/CHANGELOG.md index da872fe77ce..8f9f19002fc 100644 --- a/packages/auth-interop-types/CHANGELOG.md +++ b/packages/auth-interop-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/auth-interop-types +## 0.2.2 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.2.1 ### Patch Changes diff --git a/packages/auth-interop-types/package.json b/packages/auth-interop-types/package.json index 41873828f55..d3d89fb1b9b 100644 --- a/packages/auth-interop-types/package.json +++ b/packages/auth-interop-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth-interop-types", - "version": "0.2.1", + "version": "0.2.2", "description": "@firebase/auth interop Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -14,7 +14,7 @@ "repository": { "directory": "packages/auth-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/auth-types/CHANGELOG.md b/packages/auth-types/CHANGELOG.md index 70436276e0e..8e10bb2b060 100644 --- a/packages/auth-types/CHANGELOG.md +++ b/packages/auth-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/auth-types +## 0.12.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.12.0 ### Minor Changes diff --git a/packages/auth-types/package.json b/packages/auth-types/package.json index ee0497983f2..080a3b332e0 100644 --- a/packages/auth-types/package.json +++ b/packages/auth-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth-types", - "version": "0.12.0", + "version": "0.12.1", "description": "@firebase/auth Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -18,7 +18,7 @@ "repository": { "directory": "packages/auth-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/auth/CHANGELOG.md b/packages/auth/CHANGELOG.md index 3843030b21c..faa2faafa8a 100644 --- a/packages/auth/CHANGELOG.md +++ b/packages/auth/CHANGELOG.md @@ -1,5 +1,67 @@ # @firebase/auth +## 1.7.2 + +### Patch Changes + +- [`36b283f3f`](https://github.com/firebase/firebase-js-sdk/commit/36b283f3fc317d0fa7dde47e1048d2ee3690a9a0) [#8191](https://github.com/firebase/firebase-js-sdk/pull/8191) (fixes [#8115](https://github.com/firebase/firebase-js-sdk/issues/8115)) - Emit a module package file with esm2017 auth browser extension builds + +- [`55fef6d62`](https://github.com/firebase/firebase-js-sdk/commit/55fef6d627791f4704194c3913ebeb339a564906) [#7001](https://github.com/firebase/firebase-js-sdk/pull/7001) - Update jszip transient dependency from 3.7.1 to 3.10.1 in auth. + +## 1.7.1 + +### Patch Changes + +- [`fe09d8338`](https://github.com/firebase/firebase-js-sdk/commit/fe09d8338d7d5f7a82d8cd73cf825adbe5551975) [#8138](https://github.com/firebase/firebase-js-sdk/pull/8138) (fixes [#8132](https://github.com/firebase/firebase-js-sdk/issues/8132)) - Update undici version to 5.28.4 due to CVE-2024-30260. + +- [`ad8d5470d`](https://github.com/firebase/firebase-js-sdk/commit/ad8d5470dad9b9ec1bcd939609da4a1c439c8414) [#8134](https://github.com/firebase/firebase-js-sdk/pull/8134) - Updated dependencies. See GitHub PR #8098. + +## 1.7.0 + +### Minor Changes + +- [`ed84efe50`](https://github.com/firebase/firebase-js-sdk/commit/ed84efe50bfc365da8ebfacdd2b17b5cc2a9e596) [#8005](https://github.com/firebase/firebase-js-sdk/pull/8005) - Added the new `FirebaseServerApp` interface to bridge state + data between client and server runtime environments. This interface extends `FirebaseApp`. + +### Patch Changes + +- [`9ca1a4e4f`](https://github.com/firebase/firebase-js-sdk/commit/9ca1a4e4f9f13d56cde93cab6d83a8bc54f83539) [#8076](https://github.com/firebase/firebase-js-sdk/pull/8076) - Additional protection against misuse of the authTokenSyncURL experiment + +- [`c8a2568dd`](https://github.com/firebase/firebase-js-sdk/commit/c8a2568ddd2acd9162a99bce9ff4203fe8d6e0da) [#8097](https://github.com/firebase/firebase-js-sdk/pull/8097) - Updated transitive dependencies based on generated dependabot security reports. For more information see [PR #8088](https://github.com/firebase/firebase-js-sdk/pull/8088/files). + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/component@0.6.6 + - @firebase/logger@0.4.1 + - @firebase/util@1.9.5 + +## 1.6.2 + +### Patch Changes + +- [`6d487d7de`](https://github.com/firebase/firebase-js-sdk/commit/6d487d7dee631498bed1aeccbb45d8f14ae911d1) [#8060](https://github.com/firebase/firebase-js-sdk/pull/8060) - Do not allow double slash at beginning of authTokenSyncURL. (follow-up fix to https://github.com/firebase/firebase-js-sdk/pull/8056) + +- [`245dd26e1`](https://github.com/firebase/firebase-js-sdk/commit/245dd26e19b6c16aca7e1b7e597ed5784c2984ba) [#8056](https://github.com/firebase/firebase-js-sdk/pull/8056) - Fix possible XSS vulnerability through **FIREBASE_DEFAULTS** settings. + +## 1.6.1 + +### Patch Changes + +- [`f3cec28df`](https://github.com/firebase/firebase-js-sdk/commit/f3cec28dfbdfc7f19c8218cf9d26956235d03fb0) [#8044](https://github.com/firebase/firebase-js-sdk/pull/8044) (fixes [#8038](https://github.com/firebase/firebase-js-sdk/issues/8038)) - Bump undici version to 5.28.3 due to security issue. + +## 1.6.0 + +### Minor Changes + +- [`2f7ad0ac4`](https://github.com/firebase/firebase-js-sdk/commit/2f7ad0ac43f5d085604324f6dc3921d9420bfccd) [#8001](https://github.com/firebase/firebase-js-sdk/pull/8001) - Added a Web-Extension package that strips the external JS loading for developers to use when building Chrome Extension app. + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/component@0.6.5 + ## 1.5.1 ### Patch Changes diff --git a/packages/auth/demo/functions/package.json b/packages/auth/demo/functions/package.json index d240de9b37d..275924c8ed2 100644 --- a/packages/auth/demo/functions/package.json +++ b/packages/auth/demo/functions/package.json @@ -9,7 +9,7 @@ "logs": "firebase functions:log" }, "dependencies": { - "firebase-admin": "11.10.1", + "firebase-admin": "11.11.1", "firebase-functions": "3.24.1" }, "private": true, diff --git a/packages/auth/demo/functions/yarn.lock b/packages/auth/demo/functions/yarn.lock index 8383cf43122..db07d180dab 100644 --- a/packages/auth/demo/functions/yarn.lock +++ b/packages/auth/demo/functions/yarn.lock @@ -2,94 +2,91 @@ # yarn lockfile v1 -"@firebase/app-types@0.7.0": - version "0.7.0" - resolved "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.7.0.tgz#c9e16d1b8bed1a991840b8d2a725fb58d0b5899f" - integrity sha512-6fbHQwDv2jp/v6bXhBw2eSRbNBpxHcd1NBF864UksSMVIqIyri9qpJB1Mn6sGZE+bnDsSQBC5j2TbMxYsJQkQg== - -"@firebase/auth-interop-types@0.1.6": - version "0.1.6" - resolved "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.6.tgz#5ce13fc1c527ad36f1bb1322c4492680a6cf4964" - integrity sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g== - -"@firebase/component@0.5.13": - version "0.5.13" - resolved "https://registry.npmjs.org/@firebase/component/-/component-0.5.13.tgz#65a382e83bddd109380c9aa1f280791b1b4567c4" - integrity sha512-hxhJtpD8Ppf/VU2Rlos6KFCEV77TGIGD5bJlkPK1+B/WUe0mC6dTjW7KhZtXTc+qRBp9nFHWcsIORnT8liHP9w== - dependencies: - "@firebase/util" "1.5.2" - tslib "^2.1.0" +"@babel/parser@^7.20.15": + version "7.24.0" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac" + integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg== -"@firebase/database-compat@^0.1.8": - version "0.1.8" - resolved "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.1.8.tgz#ab627f2bdbe94367f515d5bded880c86886bbd28" - integrity sha512-dhXr5CSieBuKNdU96HgeewMQCT9EgOIkfF1GNy+iRrdl7BWLxmlKuvLfK319rmIytSs/vnCzcD9uqyxTeU/A3A== +"@fastify/busboy@^1.2.1": + version "1.2.1" + resolved "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.2.1.tgz#9c6db24a55f8b803b5222753b24fe3aea2ba9ca3" + integrity sha512-7PQA7EH43S0CxcOa9OeAnaeA0oQ+e/DHNPZwSQM9CQHW76jle5+OvLdibRp/Aafs9KXbLhxyjOTkRjWUbQEd3Q== dependencies: - "@firebase/component" "0.5.13" - "@firebase/database" "0.12.8" - "@firebase/database-types" "0.9.7" - "@firebase/logger" "0.3.2" - "@firebase/util" "1.5.2" - tslib "^2.1.0" + text-decoding "^1.0.0" -"@firebase/database-types@0.9.7": - version "0.9.7" - resolved "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.7.tgz#c5ee0ea9bb2703a13c1c47fe880fc577d5ce7f33" - integrity sha512-EFhgL89Fz6DY3kkB8TzdHvdu8XaqqvzcF2DLVOXEnQ3Ms7L755p5EO42LfxXoJqb9jKFvgLpFmKicyJG25WFWw== - dependencies: - "@firebase/app-types" "0.7.0" - "@firebase/util" "1.5.2" +"@firebase/app-types@0.9.0": + version "0.9.0" + resolved "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz#35b5c568341e9e263b29b3d2ba0e9cfc9ec7f01e" + integrity sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q== -"@firebase/database-types@^0.9.7": - version "0.9.8" - resolved "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.8.tgz#5a9bb1d2c492ad635eff5f3cfbe6a0ea6a2463e7" - integrity sha512-bI7bwF5xc0nPi6Oa3JVt6JJdfhVAnEpCwgfTNILR4lYDPtxdxlRXhZzQ5lfqlCj7PR+drKh9RvMu6C24N1q04w== +"@firebase/auth-interop-types@0.2.1": + version "0.2.1" + resolved "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz#78884f24fa539e34a06c03612c75f222fcc33742" + integrity sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg== + +"@firebase/component@0.6.4": + version "0.6.4" + resolved "https://registry.npmjs.org/@firebase/component/-/component-0.6.4.tgz#8981a6818bd730a7554aa5e0516ffc9b1ae3f33d" + integrity sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA== dependencies: - "@firebase/app-types" "0.7.0" - "@firebase/util" "1.6.0" + "@firebase/util" "1.9.3" + tslib "^2.1.0" -"@firebase/database@0.12.8": - version "0.12.8" - resolved "https://registry.npmjs.org/@firebase/database/-/database-0.12.8.tgz#11a1b6752ba0614892af15c71958e00ce16f5824" - integrity sha512-JBQVfFLzfhxlQbl4OU6ov9fdsddkytBQdtSSR49cz48homj38ccltAhK6seum+BI7f28cV2LFHF9672lcN+qxA== +"@firebase/database-compat@^0.3.4": + version "0.3.4" + resolved "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.3.4.tgz#4e57932f7a5ba761cd5ac946ab6b6ab3f660522c" + integrity sha512-kuAW+l+sLMUKBThnvxvUZ+Q1ZrF/vFJ58iUY9kAcbX48U03nVzIF6Tmkf0p3WVQwMqiXguSgtOPIB6ZCeF+5Gg== dependencies: - "@firebase/auth-interop-types" "0.1.6" - "@firebase/component" "0.5.13" - "@firebase/logger" "0.3.2" - "@firebase/util" "1.5.2" - faye-websocket "0.11.4" + "@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" -"@firebase/logger@0.3.2": - version "0.3.2" - resolved "https://registry.npmjs.org/@firebase/logger/-/logger-0.3.2.tgz#5046ffa8295c577846d54b6ca95645a03809800e" - integrity sha512-lzLrcJp9QBWpo40OcOM9B8QEtBw2Fk1zOZQdvv+rWS6gKmhQBCEMc4SMABQfWdjsylBcDfniD1Q+fUX1dcBTXA== +"@firebase/database-types@0.10.4", "@firebase/database-types@^0.10.4": + version "0.10.4" + resolved "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.10.4.tgz#47ba81113512dab637abace61cfb65f63d645ca7" + integrity sha512-dPySn0vJ/89ZeBac70T+2tWWPiJXWbmRygYv0smT5TfE3hDrQ09eKMF3Y+vMlTdrMWq7mUdYW5REWPSGH4kAZQ== dependencies: + "@firebase/app-types" "0.9.0" + "@firebase/util" "1.9.3" + +"@firebase/database@0.14.4": + version "0.14.4" + resolved "https://registry.npmjs.org/@firebase/database/-/database-0.14.4.tgz#9e7435a16a540ddfdeb5d99d45618e6ede179aa6" + integrity sha512-+Ea/IKGwh42jwdjCyzTmeZeLM3oy1h0mFPsTy6OqCWzcu/KFqRAr5Tt1HRCOBlNOdbh84JPZC47WLU18n2VbxQ== + 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" -"@firebase/util@1.5.2": - version "1.5.2" - resolved "https://registry.npmjs.org/@firebase/util/-/util-1.5.2.tgz#bdd2bc11c956a8a6a0fa25fbd752a13e033558bc" - integrity sha512-YvBH2UxFcdWG2HdFnhxZptPl2eVFlpOyTH66iDo13JPEYraWzWToZ5AMTtkyRHVmu7sssUpQlU9igy1KET7TOw== +"@firebase/logger@0.4.0": + version "0.4.0" + resolved "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.0.tgz#15ecc03c452525f9d47318ad9491b81d1810f113" + integrity sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA== dependencies: tslib "^2.1.0" -"@firebase/util@1.6.0": - version "1.6.0" - resolved "https://registry.npmjs.org/@firebase/util/-/util-1.6.0.tgz#31aea6bba3ee98fc83a60eb189cb187243f4ef4b" - integrity sha512-6+hhqb4Zzjoo12xofTDHPkgW3FnN4ydBsjd5X2KuQI268DR3W3Ld64W/gkKPZrKRgUxeNeb+pykfP3qRe7q+vA== +"@firebase/util@1.9.3": + version "1.9.3" + resolved "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz#45458dd5cd02d90e55c656e84adf6f3decf4b7ed" + integrity sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA== dependencies: tslib "^2.1.0" -"@google-cloud/firestore@^4.15.1": - version "4.15.1" - resolved "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-4.15.1.tgz#ed764fc76823ce120e68fe8c27ef1edd0650cd93" - integrity sha512-2PWsCkEF1W02QbghSeRsNdYKN1qavrHBP3m72gPDMHQSYrGULOaTi7fSJquQmAtc4iPVB2/x6h80rdLHTATQtA== +"@google-cloud/firestore@^6.6.0": + version "6.8.0" + resolved "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-6.8.0.tgz#d8c852844c381afaf62592796606c10e178400b5" + integrity sha512-JRpk06SmZXLGz0pNx1x7yU3YhkUXheKgH5hbDZ4kMsdhtfV5qPLJLRI4wv69K0cZorIk+zTMOwptue7hizo0eA== dependencies: fast-deep-equal "^3.1.1" functional-red-black-tree "^1.0.1" - google-gax "^2.24.1" - protobufjs "^6.8.6" + google-gax "^3.5.7" + protobufjs "^7.2.5" "@google-cloud/paginator@^3.0.7": version "3.0.7" @@ -99,70 +96,64 @@ arrify "^2.0.0" extend "^3.0.2" -"@google-cloud/projectify@^2.0.0": - version "2.1.1" - resolved "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.1.1.tgz#ae6af4fee02d78d044ae434699a630f8df0084ef" - integrity sha512-+rssMZHnlh0twl122gXY4/aCrk0G1acBqkHFfYddtsqpYXGxA29nj9V5V9SfC+GyOG00l650f6lG9KL+EpFEWQ== +"@google-cloud/projectify@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz#302b25f55f674854dce65c2532d98919b118a408" + integrity sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA== -"@google-cloud/promisify@^2.0.0": - version "2.0.4" - resolved "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.4.tgz#9d8705ecb2baa41b6b2673f3a8e9b7b7e1abc52a" - integrity sha512-j8yRSSqswWi1QqUGKVEKOG03Q7qOoZP6/h2zN2YO+F5h2+DHU0bSrHCK9Y7lo2DI9fBd8qGAw795sf+3Jva4yA== +"@google-cloud/promisify@^3.0.0": + version "3.0.1" + resolved "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-3.0.1.tgz#8d724fb280f47d1ff99953aee0c1669b25238c2e" + integrity sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA== -"@google-cloud/storage@^5.18.3": - version "5.19.3" - resolved "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.19.3.tgz#0624f57a7ed5a4e3e0e23d5aaab849cb015f903a" - integrity sha512-l+8X0BoA7rg9jyZaS4p2DwMg1Ivju+VAL6PeQZE1u2q52LQ0KemrZmdQWhtrplHYo8UdYtqpbj4A6Fc5fKDZdg== +"@google-cloud/storage@^6.9.5": + version "6.12.0" + resolved "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.12.0.tgz#a5d3093cc075252dca5bd19a3cfda406ad3a9de1" + integrity sha512-78nNAY7iiZ4O/BouWMWTD/oSF2YtYgYB3GZirn0To6eBOugjXVoK+GXgUXOl+HlqbAOyHxAVXOlsj3snfbQ1dw== dependencies: "@google-cloud/paginator" "^3.0.7" - "@google-cloud/projectify" "^2.0.0" - "@google-cloud/promisify" "^2.0.0" + "@google-cloud/projectify" "^3.0.0" + "@google-cloud/promisify" "^3.0.0" abort-controller "^3.0.0" - arrify "^2.0.0" async-retry "^1.3.3" compressible "^2.0.12" - configstore "^5.0.0" - date-and-time "^2.0.0" duplexify "^4.0.0" ent "^2.2.0" extend "^3.0.2" - gaxios "^4.0.0" - get-stream "^6.0.0" - google-auth-library "^7.14.1" - hash-stream-validation "^0.2.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" - pumpify "^2.0.0" - retry-request "^4.2.2" - snakeize "^0.1.0" - stream-events "^1.0.4" - teeny-request "^7.1.3" - xdg-basedir "^4.0.0" - -"@grpc/grpc-js@~1.6.0": - version "1.6.7" - resolved "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.7.tgz#4c4fa998ff719fe859ac19fe977fdef097bb99aa" - integrity sha512-eBM03pu9hd3VqDQG+kHahiG1x80RGkkqqRb1Pchcwqej/KkAH95gAvKs6laqaHCycYaPK+TKuNQnOz9UXYA8qw== - dependencies: - "@grpc/proto-loader" "^0.6.4" + retry-request "^5.0.0" + teeny-request "^8.0.0" + uuid "^8.0.0" + +"@grpc/grpc-js@~1.8.0": + version "1.8.21" + resolved "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.21.tgz#d282b122c71227859bf6c5866f4c40f4a2696513" + integrity sha512-KeyQeZpxeEBSqFVTi3q2K7PiPXmgBfECc4updA1ejCLjYmoAlvvM3ZMp5ztTDUCUQmoY3CpDxvchjO1+rFkoHg== + dependencies: + "@grpc/proto-loader" "^0.7.0" "@types/node" ">=12.12.47" -"@grpc/proto-loader@^0.6.1", "@grpc/proto-loader@^0.6.4": - version "0.6.9" - resolved "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.9.tgz#4014eef366da733f8e04a9ddd7376fe8a58547b7" - integrity sha512-UlcCS8VbsU9d3XTXGiEVFonN7hXk+oMXZtoHHG2oSA1/GcDP1q6OUgs20PzHDGizzyi8ufGSUDlk3O2NyY7leg== +"@grpc/proto-loader@^0.7.0": + version "0.7.10" + resolved "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz#6bf26742b1b54d0a473067743da5d3189d06d720" + integrity sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ== dependencies: - "@types/long" "^4.0.1" lodash.camelcase "^4.3.0" - long "^4.0.0" - protobufjs "^6.10.0" - yargs "^16.2.0" + long "^5.0.0" + protobufjs "^7.2.4" + yargs "^17.7.2" -"@panva/asn1.js@^1.0.0": - version "1.0.0" - resolved "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz#dd55ae7b8129e02049f009408b97c61ccf9032f6" - integrity sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw== +"@jsdoc/salty@^0.2.1": + version "0.2.7" + resolved "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.7.tgz#98ddce519fd95d7bee605a658fabf6e8cbf7556d" + integrity sha512-mh8LbS9d4Jq84KLw8pzho7XC2q2/IJGiJss3xwRoLD1A+EE16SjN4PfaG4jRCzKegTFLlN0Zd8SdUPE6XdoPFg== + dependencies: + lodash "^4.17.21" "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" @@ -242,14 +233,6 @@ resolved "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== -"@types/express-jwt@0.0.42": - version "0.0.42" - resolved "https://registry.npmjs.org/@types/express-jwt/-/express-jwt-0.0.42.tgz#4f04e1fadf9d18725950dc041808a4a4adf7f5ae" - integrity sha512-WszgUddvM1t5dPpJ3LhWNH8kfNN8GPIBrAGxgIYXVCEGx6Bx4A036aAuf/r5WH9DIEdlmp7gHOYvSM6U87B0ag== - dependencies: - "@types/express" "*" - "@types/express-unless" "*" - "@types/express-serve-static-core@*": version "4.17.24" resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz#ea41f93bf7e0d59cd5a76665068ed6aab6815c07" @@ -259,31 +242,15 @@ "@types/qs" "*" "@types/range-parser" "*" -"@types/express-serve-static-core@^4.17.18": - version "4.17.28" - resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" - integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== +"@types/express-serve-static-core@^4.17.33": + version "4.17.43" + resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz#10d8444be560cb789c4735aea5eac6e5af45df54" + integrity sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg== dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" - -"@types/express-unless@*": - version "0.5.3" - resolved "https://registry.npmjs.org/@types/express-unless/-/express-unless-0.5.3.tgz#271f8603617445568ed0d6efe25a7d2f338544c1" - integrity sha512-TyPLQaF6w8UlWdv4gj8i46B+INBVzURBNRahCozCSXfsK2VTlL1wNyTlMKw817VHygBtlcl5jfnPadlydr06Yw== - dependencies: - "@types/express" "*" - -"@types/express@*": - version "4.17.13" - resolved "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" - integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.18" - "@types/qs" "*" - "@types/serve-static" "*" + "@types/send" "*" "@types/express@4.17.3": version "4.17.3" @@ -294,16 +261,64 @@ "@types/express-serve-static-core" "*" "@types/serve-static" "*" -"@types/long@^4.0.0", "@types/long@^4.0.1": +"@types/express@^4.17.17": + version "4.17.21" + resolved "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/glob@*": + version "8.1.0" + resolved "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc" + integrity sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w== + dependencies: + "@types/minimatch" "^5.1.2" + "@types/node" "*" + +"@types/jsonwebtoken@^9.0.2": + version "9.0.6" + resolved "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz#d1af3544d99ad992fb6681bbe60676e06b032bd3" + integrity sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw== + dependencies: + "@types/node" "*" + +"@types/linkify-it@*": + version "3.0.5" + resolved "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz#1e78a3ac2428e6d7e6c05c1665c242023a4601d8" + integrity sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw== + +"@types/long@^4.0.0": version "4.0.1" resolved "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9" integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== +"@types/markdown-it@^12.2.3": + version "12.2.3" + resolved "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz#0d6f6e5e413f8daaa26522904597be3d6cd93b51" + integrity sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ== + dependencies: + "@types/linkify-it" "*" + "@types/mdurl" "*" + +"@types/mdurl@*": + version "1.0.5" + resolved "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz#3e0d2db570e9fb6ccb2dc8fde0be1d79ac810d39" + integrity sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA== + "@types/mime@^1": version "1.3.2" resolved "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== +"@types/minimatch@^5.1.2": + version "5.1.2" + resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" + integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== + "@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0": version "16.9.6" resolved "https://registry.npmjs.org/@types/node/-/node-16.9.6.tgz#040a64d7faf9e5d9e940357125f0963012e66f04" @@ -319,6 +334,22 @@ resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== +"@types/rimraf@^3.0.2": + version "3.0.2" + resolved "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz#a63d175b331748e5220ad48c901d7bbf1f44eef8" + integrity sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ== + dependencies: + "@types/glob" "*" + "@types/node" "*" + +"@types/send@*": + version "0.17.4" + resolved "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + "@types/serve-static@*": version "1.13.10" resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" @@ -342,6 +373,16 @@ accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.9.0: + version "8.11.3" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== + agent-base@6: version "6.0.2" resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -354,13 +395,18 @@ ansi-regex@^5.0.1: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^4.0.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -378,6 +424,11 @@ async-retry@^1.3.3: dependencies: retry "0.13.1" +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + base64-js@^1.3.0: version "1.5.1" resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -388,6 +439,11 @@ bignumber.js@^9.0.0: resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== +bluebird@^3.7.2: + version "3.7.2" + resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + body-parser@1.19.0: version "1.19.0" resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" @@ -404,6 +460,13 @@ body-parser@1.19.0: raw-body "2.4.0" type-is "~1.6.17" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" @@ -414,13 +477,28 @@ bytes@3.1.0: resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== +catharsis@^0.9.0: + version "0.9.0" + resolved "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz#40382a168be0e6da308c277d3a2b3eb40c7d2121" + integrity sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A== + dependencies: + lodash "^4.17.15" + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: string-width "^4.2.0" - strip-ansi "^6.0.0" + strip-ansi "^6.0.1" wrap-ansi "^7.0.0" color-convert@^2.0.1: @@ -442,18 +520,6 @@ compressible@^2.0.12: dependencies: mime-db ">= 1.43.0 < 2" -configstore@^5.0.0: - version "5.0.1" - resolved "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" - integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== - 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" - content-disposition@0.5.3: version "0.5.3" resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -484,16 +550,6 @@ cors@^2.8.5: object-assign "^4" vary "^1" -crypto-random-string@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" - integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== - -date-and-time@^2.0.0: - version "2.3.1" - resolved "https://registry.npmjs.org/date-and-time/-/date-and-time-2.3.1.tgz#006675ec4943a0a5f85810e3a3fd6aa96f6130c9" - integrity sha512-OaIRmSJXifwEN21rMVVDs0Kz8uhJ3wWPYd86atkRiqN54liaMQYEbbrgjZQea75YXOBWL4ZFb3rG/waenw1TEg== - debug@2.6.9: version "2.6.9" resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -515,6 +571,11 @@ debug@^4.3.4: dependencies: ms "2.1.2" +deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + depd@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -525,21 +586,7 @@ destroy@~1.0.4: resolved "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= -dicer@^0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872" - integrity sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA== - dependencies: - streamsearch "0.1.2" - -dot-prop@^5.2.0: - version "5.3.0" - resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" - integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== - dependencies: - is-obj "^2.0.0" - -duplexify@^4.0.0, duplexify@^4.1.1: +duplexify@^4.0.0: version "4.1.2" resolved "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0" integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw== @@ -571,7 +618,7 @@ encodeurl@~1.0.2: resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -end-of-stream@^1.1.0, end-of-stream@^1.4.1: +end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -583,6 +630,11 @@ ent@^2.2.0: resolved "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= +entities@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" + integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== + escalade@^3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -593,6 +645,57 @@ escape-html@~1.0.3: resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escodegen@^1.13.0: + version "1.14.3" + resolved "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" + integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== + dependencies: + esprima "^4.0.1" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +eslint-visitor-keys@^3.4.1: + version "3.4.3" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +espree@^9.0.0: + version "9.6.1" + resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esprima@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +estraverse@^4.2.0: + version "4.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0: + version "5.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + etag@~1.8.1: version "1.8.1" resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" @@ -649,11 +752,23 @@ fast-deep-equal@^3.1.1: resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz#ec02ac8e01ab8a319af182dae2681213cfe9ce53" integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig== +fast-xml-parser@^4.2.2: + version "4.3.5" + resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.5.tgz#e2f2a2ae8377e9c3dc321b151e58f420ca7e5ccc" + integrity sha512-sWvP1Pl8H03B8oFJpFR3HE31HUfwtX7Rlf9BNsvdpujD4n7WMhfmu8h9wOV2u+c1k0ZilTADhPqypzx2J690ZQ== + dependencies: + strnum "^1.0.5" + faye-websocket@0.11.4: version "0.11.4" resolved "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" @@ -674,27 +789,27 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -firebase-admin@10.2.0: - version "10.2.0" - resolved "https://registry.npmjs.org/firebase-admin/-/firebase-admin-10.2.0.tgz#e5a97d35819b5872e3e29384b48f67dab59ede04" - integrity sha512-6ehn5J9UEFgi4+naqYvozmGpnZae3cJLdwSkSsDc8/Y0eTBjVMFdf9N2ft7N81UNHA0N5DknOyXhlsdAdyBLCA== +firebase-admin@11.10.1: + version "11.10.1" + resolved "https://registry.npmjs.org/firebase-admin/-/firebase-admin-11.10.1.tgz#5f0f83a44627e89938d350c5e4bbac76596c963e" + integrity sha512-atv1E6GbuvcvWaD3eHwrjeP5dAVs+EaHEJhu9CThMzPY6In8QYDiUR6tq5SwGl4SdA/GcAU0nhwWc/FSJsAzfQ== dependencies: - "@firebase/database-compat" "^0.1.8" - "@firebase/database-types" "^0.9.7" + "@fastify/busboy" "^1.2.1" + "@firebase/database-compat" "^0.3.4" + "@firebase/database-types" "^0.10.4" "@types/node" ">=12.12.47" - dicer "^0.3.0" - jsonwebtoken "^8.5.1" - jwks-rsa "^2.0.2" + jsonwebtoken "^9.0.0" + jwks-rsa "^3.0.1" node-forge "^1.3.1" - uuid "^8.3.2" + uuid "^9.0.0" optionalDependencies: - "@google-cloud/firestore" "^4.15.1" - "@google-cloud/storage" "^5.18.3" + "@google-cloud/firestore" "^6.6.0" + "@google-cloud/storage" "^6.9.5" -firebase-functions@3.21.0: - version "3.21.0" - resolved "https://registry.npmjs.org/firebase-functions/-/firebase-functions-3.21.0.tgz#46b4c771781891929408bd4424959fe552d6cd6c" - integrity sha512-Xl0EFV05+RSB9hJHlo12LguoRqAmpSXmBnpI0MANeNj07dGW0QCWPHtaAewxYEzRS3RfSCL8WH12rjvo0PPKGw== +firebase-functions@3.24.1: + version "3.24.1" + resolved "https://registry.npmjs.org/firebase-functions/-/firebase-functions-3.24.1.tgz#50d13274c4ae96b2308a67e9fc76f1a74cff690d" + integrity sha512-GYhoyOV0864HFMU1h/JNBXYNmDk2MlbvU7VO/5qliHX6u/6vhSjTJjlyCG4leDEI8ew8IvmkIC5QquQ1U8hAuA== dependencies: "@types/cors" "^2.8.5" "@types/express" "4.17.3" @@ -713,28 +828,32 @@ fresh@0.5.2: resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gaxios@^4.0.0: - version "4.3.3" - resolved "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz#d44bdefe52d34b6435cc41214fdb160b64abfc22" - integrity sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA== +gaxios@^5.0.0, gaxios@^5.0.1: + version "5.1.3" + resolved "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz#f7fa92da0fe197c846441e5ead2573d4979e9013" + integrity sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA== 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" + node-fetch "^2.6.9" -gcp-metadata@^4.2.0: - version "4.3.1" - resolved "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz#fb205fe6a90fef2fd9c85e6ba06e5559ee1eefa9" - integrity sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A== +gcp-metadata@^5.3.0: + version "5.3.0" + resolved "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz#6f45eb473d0cb47d15001476b48b663744d25408" + integrity sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w== dependencies: - gaxios "^4.0.0" + gaxios "^5.0.0" json-bigint "^1.0.0" get-caller-file@^2.0.5: @@ -742,70 +861,78 @@ get-caller-file@^2.0.5: resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== +glob@^8.0.0: + version "8.1.0" + resolved "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" -google-auth-library@^7.14.0, google-auth-library@^7.14.1: - version "7.14.1" - resolved "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz#e3483034162f24cc71b95c8a55a210008826213c" - integrity sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA== +google-auth-library@^8.0.1, google-auth-library@^8.0.2: + version "8.9.0" + resolved "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.9.0.tgz#15a271eb2ec35d43b81deb72211bd61b1ef14dd0" + integrity sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg== 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" + gaxios "^5.0.0" + gcp-metadata "^5.3.0" + gtoken "^6.1.0" jws "^4.0.0" lru-cache "^6.0.0" -google-gax@^2.24.1: - version "2.30.2" - resolved "https://registry.npmjs.org/google-gax/-/google-gax-2.30.2.tgz#ba16940bad5a116099547a5966fdf83f6c026356" - integrity sha512-BCNCT26kb0iC52zj2SosyOZMhI5sVfXuul1h0Aw5uT9nGAbmS5eOvQ49ft53ft6XotDj11sUSDV6XESEiQqCqg== +google-gax@^3.5.7: + version "3.6.1" + resolved "https://registry.npmjs.org/google-gax/-/google-gax-3.6.1.tgz#02c78fc496f5adf86f2ca9145545f4b6575f6118" + integrity sha512-g/lcUjGcB6DSw2HxgEmCDOrI/CByOwqRvsuUvNalHUK2iPPPlmAIpbMbl62u0YufGMr8zgE3JL7th6dCb1Ry+w== dependencies: - "@grpc/grpc-js" "~1.6.0" - "@grpc/proto-loader" "^0.6.1" + "@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 "^7.14.0" + 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 "^0.1.8" - protobufjs "6.11.2" - retry-request "^4.0.0" + proto3-json-serializer "^1.0.0" + protobufjs "7.2.4" + protobufjs-cli "1.1.1" + retry-request "^5.0.0" -google-p12-pem@^3.1.3: - version "3.1.4" - resolved "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz#123f7b40da204de4ed1fbf2fd5be12c047fc8b3b" - integrity sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg== +google-p12-pem@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-4.0.1.tgz#82841798253c65b7dc2a4e5fe9df141db670172a" + integrity sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ== dependencies: node-forge "^1.3.1" -graceful-fs@^4.1.2: - version "4.2.8" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== +graceful-fs@^4.1.9: + version "4.2.11" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -gtoken@^5.0.4: - version "5.3.2" - resolved "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz#deb7dc876abe002178e0515e383382ea9446d58f" - integrity sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ== +gtoken@^6.1.0: + version "6.1.2" + resolved "https://registry.npmjs.org/gtoken/-/gtoken-6.1.2.tgz#aeb7bdb019ff4c3ba3ac100bbe7b6e74dce0e8bc" + integrity sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ== dependencies: - gaxios "^4.0.0" - google-p12-pem "^3.1.3" + gaxios "^5.0.1" + google-p12-pem "^4.0.0" jws "^4.0.0" -hash-stream-validation@^0.2.2: - version "0.2.4" - resolved "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz#ee68b41bf822f7f44db1142ec28ba9ee7ccb7512" - integrity sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ== +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== http-errors@1.7.2: version "1.7.2" @@ -858,21 +985,24 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== inherits@2.0.3: version "2.0.3" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -inherits@2.0.4, inherits@^2.0.3: - version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" @@ -883,11 +1013,6 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - is-stream-ended@^0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda" @@ -898,17 +1023,38 @@ is-stream@^2.0.0: resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== -is-typedarray@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +jose@^4.14.6: + version "4.15.5" + resolved "https://registry.npmjs.org/jose/-/jose-4.15.5.tgz#6475d0f467ecd3c630a1b5dadd2735a7288df706" + integrity sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg== -jose@^2.0.5: - version "2.0.5" - resolved "https://registry.npmjs.org/jose/-/jose-2.0.5.tgz#29746a18d9fff7dcf9d5d2a6f62cb0c7cd27abd3" - integrity sha512-BAiDNeDKTMgk4tvD0BbxJ8xHEHBZgpeRZ1zGPPsitSyMgjoMWiLGYAE7H7NpP5h0lPppQajQs871E8NHUrzVPA== +js2xmlparser@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz#2a1fdf01e90585ef2ae872a01bc169c6a8d5e60a" + integrity sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA== dependencies: - "@panva/asn1.js" "^1.0.0" + xmlcreate "^2.0.4" + +jsdoc@^4.0.0: + version "4.0.2" + resolved "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz#a1273beba964cf433ddf7a70c23fd02c3c60296e" + integrity sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg== + 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" json-bigint@^1.0.0: version "1.0.0" @@ -917,10 +1063,10 @@ json-bigint@^1.0.0: dependencies: bignumber.js "^9.0.0" -jsonwebtoken@^8.5.1: - version "8.5.1" - resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" - integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== +jsonwebtoken@^9.0.0: + version "9.0.2" + resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" + integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== dependencies: jws "^3.2.2" lodash.includes "^4.3.0" @@ -931,7 +1077,7 @@ jsonwebtoken@^8.5.1: lodash.isstring "^4.0.1" lodash.once "^4.0.0" ms "^2.1.1" - semver "^5.6.0" + semver "^7.5.4" jwa@^1.4.1: version "1.4.1" @@ -951,16 +1097,17 @@ jwa@^2.0.0: ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" -jwks-rsa@^2.0.2: - version "2.1.0" - resolved "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.1.0.tgz#00e4c5eecc40ba41de199b71ab7e489807a1727f" - integrity sha512-GKOSDBWWBCiQTzawei6mEdRQvji5gecj8F9JwMt0ZOPnBPSmTjo5CKFvvbhE7jGPkU159Cpi0+OTLuABFcNOQQ== +jwks-rsa@^3.0.1: + version "3.1.0" + resolved "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.1.0.tgz#50406f23e38c9b2682cd437f824d7d61aa983171" + integrity sha512-v7nqlfezb9YfHHzYII3ef2a2j1XnGeSE/bK3WfumaYCqONAIstJbrEGapz4kadScZzEt7zYCN7bucj8C0Mv/Rg== dependencies: - "@types/express-jwt" "0.0.42" + "@types/express" "^4.17.17" + "@types/jsonwebtoken" "^9.0.2" debug "^4.3.4" - jose "^2.0.5" + jose "^4.14.6" limiter "^1.1.5" - lru-memoizer "^2.1.4" + lru-memoizer "^2.2.0" jws@^3.2.2: version "3.2.2" @@ -978,11 +1125,33 @@ jws@^4.0.0: jwa "^2.0.0" safe-buffer "^5.0.1" +klaw@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz#b11bec9cf2492f06756d6e809ab73a2910259146" + integrity sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g== + dependencies: + graceful-fs "^4.1.9" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + limiter@^1.1.5: version "1.1.5" resolved "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz#8f92a25b3b16c6131293a0cc834b4a838a2aa7c2" integrity sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA== +linkify-it@^3.0.1: + version "3.0.3" + resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e" + integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ== + dependencies: + uc.micro "^1.0.1" + lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" @@ -1028,15 +1197,15 @@ lodash.once@^4.0.0: resolved "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= -lodash@^4.17.14: +lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -long@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" - integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== +long@^5.0.0: + version "5.2.3" + resolved "https://registry.npmjs.org/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" + integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== lru-cache@^6.0.0: version "6.0.0" @@ -1053,20 +1222,39 @@ lru-cache@~4.0.0: pseudomap "^1.0.1" yallist "^2.0.0" -lru-memoizer@^2.1.4: - version "2.1.4" - resolved "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.1.4.tgz#b864d92b557f00b1eeb322156a0409cb06dafac6" - integrity sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ== +lru-memoizer@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.2.0.tgz#b9d90c91637b4b1a423ef76f3156566691293df8" + integrity sha512-QfOZ6jNkxCcM/BkIPnFsqDhtrazLRsghi9mBwFAzol5GCvj4EkFT899Za3+QwikCg5sRX8JstioBDwOxEyzaNw== dependencies: lodash.clonedeep "^4.5.0" lru-cache "~4.0.0" -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== +markdown-it-anchor@^8.4.1: + version "8.6.7" + resolved "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz#ee6926daf3ad1ed5e4e3968b1740eef1c6399634" + integrity sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA== + +markdown-it@^12.3.2: + version "12.3.2" + resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90" + integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg== dependencies: - semver "^6.0.0" + argparse "^2.0.1" + entities "~2.1.0" + linkify-it "^3.0.1" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +marked@^4.0.10: + version "4.3.0" + resolved "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== media-typer@0.3.0: version "0.3.0" @@ -1110,6 +1298,23 @@ mime@^3.0.0: resolved "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0: + version "1.2.8" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + ms@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -1142,6 +1347,13 @@ node-fetch@^2.6.1, node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" +node-fetch@^2.6.9: + version "2.7.0" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-forge@^1.3.1: version "1.3.1" resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -1164,13 +1376,25 @@ on-finished@~2.3.0: dependencies: ee-first "1.1.1" -once@^1.3.1, once@^1.4.0: +once@^1.3.0, once@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + 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" + p-limit@^3.0.1: version "3.1.0" resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" @@ -1188,17 +1412,38 @@ path-to-regexp@0.1.7: resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= -proto3-json-serializer@^0.1.8: - version "0.1.8" - resolved "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-0.1.8.tgz#f80f9afc1efe5ed9a9856bbbd17dc7cabd7ce9a3" - integrity sha512-ACilkB6s1U1gWnl5jtICpnDai4VCxmI9GFxuEaYdxtDG2oVI3sVFIUsvUZcQbJgtPM6p+zqKbjTKQZp6Y4FpQw== +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== + +proto3-json-serializer@^1.0.0: + version "1.1.1" + resolved "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-1.1.1.tgz#1b5703152b6ce811c5cdcc6468032caf53521331" + integrity sha512-AwAuY4g9nxx0u52DnSMkqqgyLHaW/XaPLtaAo3y/ZCfeaQB/g4YDH4kb8Wc/mWzWvu0YjOznVnfn373MVZZrgw== dependencies: - protobufjs "^6.11.2" + protobufjs "^7.0.0" -protobufjs@6.11.2, protobufjs@^6.10.0, protobufjs@^6.11.2, protobufjs@^6.8.6: - version "6.11.2" - resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz#de39fabd4ed32beaa08e9bb1e30d08544c1edf8b" - integrity sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw== +protobufjs-cli@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.1.tgz#f531201b1c8c7772066aa822bf9a08318b24a704" + integrity sha512-VPWMgIcRNyQwWUv8OLPyGQ/0lQY/QTQAVN5fh+XzfDwsVw1FZ2L3DM/bcBf8WPiRz2tNpaov9lPZfNcmNo6LXA== + 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" + +protobufjs@7.2.4: + version "7.2.4" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz#3fc1ec0cdc89dd91aef9ba6037ba07408485c3ae" + integrity sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -1210,9 +1455,26 @@ protobufjs@6.11.2, protobufjs@^6.10.0, protobufjs@^6.11.2, protobufjs@^6.8.6: "@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" + long "^5.0.0" + +protobufjs@^7.0.0, protobufjs@^7.2.4, protobufjs@^7.2.5: + version "7.2.6" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz#4a0ccd79eb292717aacf07530a07e0ed20278215" + integrity sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw== + 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" proxy-addr@~2.0.5: version "2.0.7" @@ -1227,23 +1489,6 @@ pseudomap@^1.0.1: resolved "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pumpify@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz#abfc7b5a621307c728b551decbbefb51f0e4aa1e" - integrity sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw== - dependencies: - duplexify "^4.1.1" - inherits "^2.0.3" - pump "^3.0.0" - qs@6.7.0: version "6.7.0" resolved "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" @@ -1278,10 +1523,17 @@ require-directory@^2.1.1: resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= -retry-request@^4.0.0, retry-request@^4.2.2: - version "4.2.2" - resolved "https://registry.npmjs.org/retry-request/-/retry-request-4.2.2.tgz#b7d82210b6d2651ed249ba3497f07ea602f1a903" - integrity sha512-xA93uxUD/rogV7BV59agW/JHPGXeREMWiZc9jhcwY4YdZ7QOtC7qbomYg0n4wyk2lJhggjvKvhNX8wln/Aldhg== +requizzle@^0.2.3: + version "0.2.4" + resolved "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz#319eb658b28c370f0c20f968fa8ceab98c13d27c" + integrity sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw== + dependencies: + lodash "^4.17.21" + +retry-request@^5.0.0: + version "5.0.2" + resolved "https://registry.npmjs.org/retry-request/-/retry-request-5.0.2.tgz#143d85f90c755af407fcc46b7166a4ba520e44da" + integrity sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ== dependencies: debug "^4.1.1" extend "^3.0.2" @@ -1306,15 +1558,12 @@ safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@~5.2.0: resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -semver@^5.6.0: - version "5.7.1" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0: - version "6.3.0" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.1.2, semver@^7.5.4: + version "7.6.0" + resolved "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" send@0.17.1: version "0.17.1" @@ -1350,22 +1599,17 @@ setprototypeof@1.1.1: resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== -signal-exit@^3.0.2: - version "3.0.4" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.4.tgz#366a4684d175b9cab2081e3681fda3747b6c51d7" - integrity sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q== - -snakeize@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz#10c088d8b58eb076b3229bb5a04e232ce126422d" - integrity sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0= +source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== "statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= -stream-events@^1.0.4, stream-events@^1.0.5: +stream-events@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5" integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== @@ -1377,12 +1621,7 @@ stream-shift@^1.0.0: resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== -streamsearch@0.1.2: - version "0.1.2" - resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" - integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= - -string-width@^4.1.0, string-width@^4.2.0: +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -1405,21 +1644,48 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-json-comments@^3.1.0: + version "3.1.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + stubs@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" integrity sha1-6NK6H6nJBXAwPAMLaQD31fiavls= -teeny-request@^7.1.3: +supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.npmjs.org/teeny-request/-/teeny-request-7.2.0.tgz#41347ece068f08d741e7b86df38a4498208b2633" - integrity sha512-SyY0pek1zWsi0LRVAALem+avzMLc33MKW/JLLakdP4s9+D7+jHcy5x6P+h94g2QNZsAqQNfX5lsbd3WSeJXrrw== + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +teeny-request@^8.0.0: + version "8.0.3" + resolved "https://registry.npmjs.org/teeny-request/-/teeny-request-8.0.3.tgz#5cb9c471ef5e59f2fca8280dc3c5909595e6ca24" + integrity sha512-jJZpA5He2y52yUhA7pyAGZlgQpcB+xLjcN0eUFxr9c8hP/H7uOXbBNVo/O0C/xVfJLJs680jvkFgVJEEvk9+ww== dependencies: http-proxy-agent "^5.0.0" https-proxy-agent "^5.0.0" node-fetch "^2.6.1" stream-events "^1.0.5" - uuid "^8.0.0" + uuid "^9.0.0" + +text-decoding@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz#38a5692d23b5c2b12942d6e245599cb58b1bc52f" + integrity sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA== + +tmp@^0.2.1: + version "0.2.3" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" + integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== toidentifier@1.0.0: version "1.0.0" @@ -1436,6 +1702,13 @@ tslib@^2.1.0: resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== + dependencies: + prelude-ls "~1.1.2" + type-is@~1.6.17, type-is@~1.6.18: version "1.6.18" resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -1444,19 +1717,20 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== -unique-string@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" - integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== - dependencies: - crypto-random-string "^2.0.0" +uglify-js@^3.7.7: + version "3.17.4" + resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" + integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== + +underscore@~1.13.2: + version "1.13.6" + resolved "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" + integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" @@ -1473,11 +1747,16 @@ utils-merge@1.0.1: resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= -uuid@^8.0.0, uuid@^8.3.2: +uuid@^8.0.0: version "8.3.2" resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9.0.0: + version "9.0.1" + resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -1510,6 +1789,11 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" +word-wrap@~1.2.3: + version "1.2.5" + resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -1524,20 +1808,10 @@ wrappy@1: resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write-file-atomic@^3.0.0: - version "3.0.3" - resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -xdg-basedir@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" - integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== +xmlcreate@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz#0c5ab0f99cdd02a81065fa9cd8f8ae87624889be" + integrity sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg== y18n@^5.0.5: version "5.0.8" @@ -1554,23 +1828,23 @@ yallist@^4.0.0: resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@^20.2.2: - version "20.2.9" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^16.2.0: - version "16.2.0" - resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: - cliui "^7.0.2" + cliui "^8.0.1" escalade "^3.1.1" get-caller-file "^2.0.5" require-directory "^2.1.1" - string-width "^4.2.0" + string-width "^4.2.3" y18n "^5.0.5" - yargs-parser "^20.2.2" + yargs-parser "^21.1.1" yocto-queue@^0.1.0: version "0.1.0" diff --git a/packages/auth/demo/package.json b/packages/auth/demo/package.json index 47798106098..15ea2f48463 100644 --- a/packages/auth/demo/package.json +++ b/packages/auth/demo/package.json @@ -17,10 +17,10 @@ "dev": "rollup -c -w" }, "dependencies": { - "@firebase/app": "0.7.24", + "@firebase/app": "*", "@firebase/auth": "file:..", - "@firebase/logger": "0.3.2", - "@firebase/util": "1.6.0", + "@firebase/logger": "*", + "@firebase/util": "*", "tslib": "^2.1.0" }, "license": "Apache-2.0", @@ -38,7 +38,7 @@ "repository": { "directory": "packages/auth/demo", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/auth/index.web-extension.ts b/packages/auth/index.web-extension.ts new file mode 100644 index 00000000000..d7296e9c839 --- /dev/null +++ b/packages/auth/index.web-extension.ts @@ -0,0 +1,68 @@ +/** + * @license + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Core functionality shared by all clients +export * from './src'; + +import { ClientPlatform } from './src/core/util/version'; + +import { indexedDBLocalPersistence } from './src/platform_browser/persistence/indexed_db'; + +import { + TotpMultiFactorGenerator, + TotpSecret +} from './src/mfa/assertions/totp'; +import { FirebaseApp, getApp, _getProvider } from '@firebase/app'; +import { Auth, connectAuthEmulator, initializeAuth } from './index.shared'; +import { getDefaultEmulatorHost } from '@firebase/util'; +import { registerAuth } from './src/core/auth/register'; + +/** + * Returns the Auth instance associated with the provided {@link @firebase/app#FirebaseApp}. + * If no instance exists, initializes an Auth instance with platform-specific default dependencies. + * + * @param app - The Firebase App. + * + * @public + */ +function getAuth(app: FirebaseApp = getApp()): Auth { + const provider = _getProvider(app, 'auth'); + + if (provider.isInitialized()) { + return provider.getImmediate(); + } + + const auth = initializeAuth(app, { + persistence: [indexedDBLocalPersistence] + }); + + const authEmulatorHost = getDefaultEmulatorHost('auth'); + if (authEmulatorHost) { + connectAuthEmulator(auth, `http://${authEmulatorHost}`); + } + + return auth; +} + +registerAuth(ClientPlatform.WEB_EXTENSION); + +export { + indexedDBLocalPersistence, + TotpMultiFactorGenerator, + TotpSecret, + getAuth +}; diff --git a/packages/auth/karma.conf.js b/packages/auth/karma.conf.js index 6845f0bd91d..198b079a15b 100644 --- a/packages/auth/karma.conf.js +++ b/packages/auth/karma.conf.js @@ -65,7 +65,8 @@ function getTestFiles(argv) { 'src/**/*.test.ts', 'test/helpers/**/*.test.ts', 'test/integration/flows/anonymous.test.ts', - 'test/integration/flows/email.test.ts' + 'test/integration/flows/email.test.ts', + 'test/integration/flows/firebaseserverapp.test.ts' ]; } } diff --git a/packages/auth/package.json b/packages/auth/package.json index e1c23b6f485..38765e72fb6 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/auth", - "version": "1.5.1", + "version": "1.7.2", "description": "The Firebase Authenticaton component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/node/index.js", @@ -8,6 +8,7 @@ "browser": "dist/esm2017/index.js", "module": "dist/esm2017/index.js", "cordova": "dist/cordova/index.js", + "web-extension": "dist/web-extension-esm2017/index.js", "webworker": "dist/index.webworker.esm5.js", "esm5": "dist/esm5/index.js", "exports": { @@ -41,6 +42,12 @@ "types": "./dist/cordova/index.cordova.d.ts", "default": "./dist/cordova/index.js" }, + "./web-extension": { + "types:": "./dist/web-extension-esm2017/index.web-extension.d.ts", + "import": "./dist/web-extension-esm2017/index.js", + "require": "./dist/web-extension-cjs/index.js", + "default": "./dist/web-extension-esm2017/index.js" + }, "./internal": { "types": "./dist/internal/index.d.ts", "node": { @@ -61,6 +68,12 @@ "require": "./dist/browser-cjs/internal.js", "import": "./dist/esm2017/internal.js" }, + "web-extension": { + "types:": "./dist/web-extension-cjs/internal/index.d.ts", + "import": "./dist/web-extension-esm2017/internal.js", + "require": "./dist/web-extension-cjs/internal.js", + "default": "./dist/web-extension-esm2017/internal.js" + }, "default": "./dist/esm2017/internal.js" }, "./package.json": "./package.json" @@ -68,7 +81,8 @@ "files": [ "dist", "cordova/package.json", - "internal/package.json" + "internal/package.json", + "web-extension/package.json" ], "scripts": { "lint": "eslint -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'", @@ -112,19 +126,19 @@ } }, "dependencies": { - "@firebase/component": "0.6.4", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.3", - "undici": "5.26.5", + "@firebase/component": "0.6.6", + "@firebase/logger": "0.4.1", + "@firebase/util": "1.9.5", + "undici": "5.28.4", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.9.25", + "@firebase/app": "0.10.2", "@rollup/plugin-json": "4.1.0", "@rollup/plugin-strip": "2.1.0", - "@types/express": "4.17.17", - "chromedriver": "114.0.2", + "@types/express": "4.17.21", + "chromedriver": "119.0.1", "rollup": "2.79.1", "rollup-plugin-sourcemaps": "0.6.3", "rollup-plugin-typescript2": "0.31.2", @@ -135,7 +149,7 @@ "repository": { "directory": "packages/auth", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/auth/rollup.config.js b/packages/auth/rollup.config.js index 01e358a9aff..46d3ee0380d 100644 --- a/packages/auth/rollup.config.js +++ b/packages/auth/rollup.config.js @@ -112,6 +112,38 @@ const browserBuilds = [ } ]; +const browserWebExtensionBuilds = [ + { + input: { + index: 'index.web-extension.ts', + internal: 'internal/index.ts' + }, + output: { + dir: 'dist/web-extension-esm2017', + format: 'es', + sourcemap: true + }, + plugins: [ + ...es2017BuildPlugins, + replace(generateBuildTargetReplaceConfig('esm', 2017)), + emitModulePackageFile() + ], + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + }, + { + input: { + index: 'index.web-extension.ts', + internal: 'internal/index.ts' + }, + output: [{ dir: 'dist/web-extension-cjs', format: 'cjs', sourcemap: true }], + plugins: [ + ...es2017BuildPlugins, + replace(generateBuildTargetReplaceConfig('cjs', 2017)) + ], + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + } +]; + const nodeBuilds = [ { input: { @@ -198,6 +230,7 @@ const webWorkerBuild = { export default [ ...browserBuilds, + ...browserWebExtensionBuilds, ...nodeBuilds, cordovaBuild, rnBuild, diff --git a/packages/auth/scripts/run_node_tests.ts b/packages/auth/scripts/run_node_tests.ts index 2bfc593d8fd..ce913612f64 100644 --- a/packages/auth/scripts/run_node_tests.ts +++ b/packages/auth/scripts/run_node_tests.ts @@ -48,7 +48,9 @@ let testConfig = [ ]; if (argv.integration) { - testConfig = ['test/integration/flows/{email,anonymous}.test.ts']; + testConfig = [ + 'test/integration/flows/{email,anonymous,firebaseserverapp}.test.ts' + ]; if (argv.local) { testConfig.push('test/integration/flows/*.local.test.ts'); } diff --git a/packages/auth/src/core/auth/auth_impl.ts b/packages/auth/src/core/auth/auth_impl.ts index cd75276e006..eb7e2a322c8 100644 --- a/packages/auth/src/core/auth/auth_impl.ts +++ b/packages/auth/src/core/auth/auth_impl.ts @@ -15,7 +15,11 @@ * limitations under the License. */ -import { _FirebaseService, FirebaseApp } from '@firebase/app'; +import { + _isFirebaseServerApp, + _FirebaseService, + FirebaseApp +} from '@firebase/app'; import { Provider } from '@firebase/component'; import { AppCheckInternalComponentName } from '@firebase/app-check-interop-types'; import { @@ -58,7 +62,10 @@ import { PersistenceUserManager } from '../persistence/persistence_user_manager'; import { _reloadWithoutSaving } from '../user/reload'; -import { _assert } from '../util/assert'; +import { + _assert, + _serverAppCurrentUserOperationNotSupportedError +} from '../util/assert'; import { _getInstance } from '../util/instantiator'; import { _getUserLanguage } from '../util/navigator'; import { _getClientVersion } from '../util/version'; @@ -74,6 +81,8 @@ import { _logWarn } from '../util/log'; import { _getPasswordPolicy } from '../../api/password_policy/get_password_policy'; import { PasswordPolicyInternal } from '../../model/password_policy'; import { PasswordPolicyImpl } from './password_policy_impl'; +import { getAccountInfo } from '../../api/account_management/account'; +import { UserImpl } from '../user/user_impl'; interface AsyncAction { (): Promise; @@ -168,6 +177,7 @@ export class AuthImpl implements AuthInternal, _FirebaseService { } await this.initializeCurrentUser(popupRedirectResolver); + this.lastNotifiedUid = this.currentUser?.uid || null; if (this._deleted) { @@ -210,9 +220,47 @@ export class AuthImpl implements AuthInternal, _FirebaseService { await this._updateCurrentUser(user, /* skipBeforeStateCallbacks */ true); } + private async initializeCurrentUserFromIdToken( + idToken: string + ): Promise { + try { + const response = await getAccountInfo(this, { idToken }); + const user = await UserImpl._fromGetAccountInfoResponse( + this, + response, + idToken + ); + await this.directlySetCurrentUser(user); + } catch (err) { + console.warn( + 'FirebaseServerApp could not login user with provided authIdToken: ', + err + ); + await this.directlySetCurrentUser(null); + } + } + private async initializeCurrentUser( popupRedirectResolver?: PopupRedirectResolver ): Promise { + if (_isFirebaseServerApp(this.app)) { + const idToken = this.app.settings.authIdToken; + if (idToken) { + // Start the auth operation in the next tick to allow a moment for the customer's app to + // attach an emulator, if desired. + return new Promise(resolve => { + setTimeout(() => + this.initializeCurrentUserFromIdToken(idToken).then( + resolve, + resolve + ) + ); + }); + } else { + return this.directlySetCurrentUser(null); + } + } + // First check to see if we have a pending redirect event. const previouslyStoredUser = (await this.assertedPersistence.getCurrentUser()) as UserInternal | null; @@ -346,6 +394,11 @@ export class AuthImpl implements AuthInternal, _FirebaseService { } async updateCurrentUser(userExtern: User | null): Promise { + if (_isFirebaseServerApp(this.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(this) + ); + } // The public updateCurrentUser method needs to make a copy of the user, // and also check that the project matches const user = userExtern @@ -387,6 +440,11 @@ export class AuthImpl implements AuthInternal, _FirebaseService { } async signOut(): Promise { + if (_isFirebaseServerApp(this.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(this) + ); + } // Run first, to block _setRedirectUser() if any callbacks fail. await this.beforeStateQueue.runMiddleware(null); // Clear the redirect user when signOut is called @@ -400,6 +458,11 @@ export class AuthImpl implements AuthInternal, _FirebaseService { } setPersistence(persistence: Persistence): Promise { + if (_isFirebaseServerApp(this.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(this) + ); + } return this.queue(async () => { await this.assertedPersistence.setPersistence(_getInstance(persistence)); }); diff --git a/packages/auth/src/core/auth/emulator.test.ts b/packages/auth/src/core/auth/emulator.test.ts index 8015aecee18..71a30883218 100644 --- a/packages/auth/src/core/auth/emulator.test.ts +++ b/packages/auth/src/core/auth/emulator.test.ts @@ -45,7 +45,7 @@ describe('core/auth/emulator', () => { fetch.setUp(); normalEndpoint = mockEndpoint(Endpoint.DELETE_ACCOUNT, {}); emulatorEndpoint = fetch.mock( - `http://localhost:2020/${endpointUrl(Endpoint.DELETE_ACCOUNT).replace( + `http://127.0.0.1:2020/${endpointUrl(Endpoint.DELETE_ACCOUNT).replace( /^.*:\/\//, '' )}`, @@ -70,46 +70,46 @@ describe('core/auth/emulator', () => { context('connectAuthEmulator', () => { it('fails if a network request has already been made', async () => { await user.delete(); - expect(() => connectAuthEmulator(auth, 'http://localhost:2020')).to.throw( + expect(() => connectAuthEmulator(auth, 'http://127.0.0.1:2020')).to.throw( FirebaseError, 'auth/emulator-config-failed' ); }); it('updates the endpoint appropriately', async () => { - connectAuthEmulator(auth, 'http://localhost:2020'); + connectAuthEmulator(auth, 'http://127.0.0.1:2020'); await user.delete(); expect(normalEndpoint.calls.length).to.eq(0); expect(emulatorEndpoint.calls.length).to.eq(1); }); it('updates the endpoint appropriately with trailing slash', async () => { - connectAuthEmulator(auth, 'http://localhost:2020/'); + connectAuthEmulator(auth, 'http://127.0.0.1:2020/'); await user.delete(); expect(normalEndpoint.calls.length).to.eq(0); expect(emulatorEndpoint.calls.length).to.eq(1); }); it('checks the scheme properly', () => { - expect(() => connectAuthEmulator(auth, 'http://localhost:2020')).not.to + expect(() => connectAuthEmulator(auth, 'http://127.0.0.1:2020')).not.to .throw; delete auth.config.emulator; - expect(() => connectAuthEmulator(auth, 'https://localhost:2020')).not.to + expect(() => connectAuthEmulator(auth, 'https://127.0.0.1:2020')).not.to .throw; delete auth.config.emulator; - expect(() => connectAuthEmulator(auth, 'ssh://localhost:2020')).to.throw( + expect(() => connectAuthEmulator(auth, 'ssh://127.0.0.1:2020')).to.throw( FirebaseError, 'auth/invalid-emulator-scheme' ); delete auth.config.emulator; - expect(() => connectAuthEmulator(auth, 'localhost:2020')).to.throw( + expect(() => connectAuthEmulator(auth, '127.0.0.1:2020')).to.throw( FirebaseError, 'auth/invalid-emulator-scheme' ); }); it('attaches a banner to the DOM', () => { - connectAuthEmulator(auth, 'http://localhost:2020'); + connectAuthEmulator(auth, 'http://127.0.0.1:2020'); if (typeof document !== 'undefined') { const el = document.querySelector('.firebase-emulator-warning')!; expect(el).not.to.be.null; @@ -122,7 +122,7 @@ describe('core/auth/emulator', () => { it('logs out a warning to the console', () => { sinon.stub(console, 'info'); - connectAuthEmulator(auth, 'http://localhost:2020'); + connectAuthEmulator(auth, 'http://127.0.0.1:2020'); expect(console.info).to.have.been.calledWith( 'WARNING: You are using the Auth Emulator,' + ' which is intended for local testing only. Do not use with' + @@ -132,7 +132,7 @@ describe('core/auth/emulator', () => { it('skips console info and has no banner if warnings disabled', () => { sinon.stub(console, 'info'); - connectAuthEmulator(auth, 'http://localhost:2020', { + connectAuthEmulator(auth, 'http://127.0.0.1:2020', { disableWarnings: true }); expect(console.info).not.to.have.been.called; @@ -142,10 +142,10 @@ describe('core/auth/emulator', () => { }); it('sets emulatorConfig on the Auth object', async () => { - connectAuthEmulator(auth, 'http://localhost:2020'); + connectAuthEmulator(auth, 'http://127.0.0.1:2020'); expect(auth.emulatorConfig).to.eql({ protocol: 'http', - host: 'localhost', + host: '127.0.0.1', port: 2020, options: { disableWarnings: false } }); diff --git a/packages/auth/src/core/auth/register.ts b/packages/auth/src/core/auth/register.ts index c203d682d00..4b891618d3a 100644 --- a/packages/auth/src/core/auth/register.ts +++ b/packages/auth/src/core/auth/register.ts @@ -49,6 +49,8 @@ function getVersionForPlatform( return 'webworker'; case ClientPlatform.CORDOVA: return 'cordova'; + case ClientPlatform.WEB_EXTENSION: + return 'web-extension'; default: return undefined; } diff --git a/packages/auth/src/core/index.ts b/packages/auth/src/core/index.ts index 506d7623f25..43b1adb4bb9 100644 --- a/packages/auth/src/core/index.ts +++ b/packages/auth/src/core/index.ts @@ -46,7 +46,8 @@ export { * remembered or not. It also makes it easier to never persist the `Auth` state for applications * that are shared by other users or have sensitive data. * - * This method does not work in a Node.js environment. + * This method does not work in a Node.js environment or with {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. * * @example * ```javascript @@ -223,6 +224,9 @@ export function useDeviceLanguage(auth: Auth): void { * The operation fails with an error if the user to be updated belongs to a different Firebase * project. * + * This method is not supported by {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * * @param auth - The {@link Auth} instance. * @param user - The new {@link User}. * @@ -237,6 +241,10 @@ export function updateCurrentUser( /** * Signs out the current user. * + * @remarks + * This method is not supported by {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * * @param auth - The {@link Auth} instance. * * @public diff --git a/packages/auth/src/core/providers/google.ts b/packages/auth/src/core/providers/google.ts index 764ac9d2601..ddf605e8239 100644 --- a/packages/auth/src/core/providers/google.ts +++ b/packages/auth/src/core/providers/google.ts @@ -26,7 +26,7 @@ import { BaseOAuthProvider } from './oauth'; import { ProviderId, SignInMethod } from '../../model/enums'; /** - * Provider for generating an an {@link OAuthCredential} for {@link ProviderId}.GOOGLE. + * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.GOOGLE. * * @example * ```javascript diff --git a/packages/auth/src/core/strategies/anonymous.ts b/packages/auth/src/core/strategies/anonymous.ts index cd2a40f8240..ee537fa8eb9 100644 --- a/packages/auth/src/core/strategies/anonymous.ts +++ b/packages/auth/src/core/strategies/anonymous.ts @@ -21,6 +21,8 @@ import { UserInternal } from '../../model/user'; import { UserCredentialImpl } from '../user/user_credential_impl'; import { _castAuth } from '../auth/auth_impl'; import { OperationType } from '../../model/enums'; +import { _isFirebaseServerApp } from '@firebase/app'; +import { _serverAppCurrentUserOperationNotSupportedError } from '../../core/util/assert'; /** * Asynchronously signs in as an anonymous user. @@ -29,11 +31,19 @@ import { OperationType } from '../../model/enums'; * If there is already an anonymous user signed in, that user will be returned; otherwise, a * new anonymous user identity will be created and returned. * + * This method is not supported by {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * * @param auth - The {@link Auth} instance. * * @public */ export async function signInAnonymously(auth: Auth): Promise { + if (_isFirebaseServerApp(auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(auth) + ); + } const authInternal = _castAuth(auth); await authInternal._initializationPromise; if (authInternal.currentUser?.isAnonymous) { diff --git a/packages/auth/src/core/strategies/credential.ts b/packages/auth/src/core/strategies/credential.ts index 00aa919f047..476cf888095 100644 --- a/packages/auth/src/core/strategies/credential.ts +++ b/packages/auth/src/core/strategies/credential.ts @@ -27,12 +27,19 @@ import { UserCredentialImpl } from '../user/user_credential_impl'; import { _castAuth } from '../auth/auth_impl'; import { getModularInstance } from '@firebase/util'; import { OperationType } from '../../model/enums'; +import { _isFirebaseServerApp } from '@firebase/app'; +import { _serverAppCurrentUserOperationNotSupportedError } from '../../core/util/assert'; export async function _signInWithCredential( auth: AuthInternal, credential: AuthCredential, bypassAuthState = false ): Promise { + if (_isFirebaseServerApp(auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(auth) + ); + } const operationType = OperationType.SIGN_IN; const response = await _processCredentialSavingMfaContextIfNecessary( auth, @@ -57,6 +64,9 @@ export async function _signInWithCredential( * @remarks * An {@link AuthProvider} can be used to generate the credential. * + * This method is not supported by {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * * @param auth - The {@link Auth} instance. * @param credential - The auth credential. * @@ -99,6 +109,9 @@ export async function linkWithCredential( * attempts. This method can be used to recover from a `CREDENTIAL_TOO_OLD_LOGIN_AGAIN` error * or a `TOKEN_EXPIRED` error. * + * This method is not supported on any {@link User} signed in by {@link Auth} instances + * created with a {@link @firebase/app#FirebaseServerApp}. + * * @param user - The user. * @param credential - The auth credential. * diff --git a/packages/auth/src/core/strategies/custom_token.ts b/packages/auth/src/core/strategies/custom_token.ts index 6d1e1b36fe0..83c66d5edd6 100644 --- a/packages/auth/src/core/strategies/custom_token.ts +++ b/packages/auth/src/core/strategies/custom_token.ts @@ -22,7 +22,8 @@ import { IdTokenResponse } from '../../model/id_token'; import { UserCredentialImpl } from '../user/user_credential_impl'; import { _castAuth } from '../auth/auth_impl'; import { OperationType } from '../../model/enums'; - +import { _isFirebaseServerApp } from '@firebase/app'; +import { _serverAppCurrentUserOperationNotSupportedError } from '../../core/util/assert'; /** * Asynchronously signs in using a custom token. * @@ -34,6 +35,9 @@ import { OperationType } from '../../model/enums'; * * Fails with an error if the token is invalid, expired, or not accepted by the Firebase Auth service. * + * This method is not supported by {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * * @param auth - The {@link Auth} instance. * @param customToken - The custom token to sign in with. * @@ -43,6 +47,11 @@ export async function signInWithCustomToken( auth: Auth, customToken: string ): Promise { + if (_isFirebaseServerApp(auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(auth) + ); + } const authInternal = _castAuth(auth); const response: IdTokenResponse = await getIdTokenResponse(authInternal, { token: customToken, diff --git a/packages/auth/src/core/strategies/email.ts b/packages/auth/src/core/strategies/email.ts index 13fefda640d..5e872e3e1c7 100644 --- a/packages/auth/src/core/strategies/email.ts +++ b/packages/auth/src/core/strategies/email.ts @@ -34,8 +34,9 @@ import { getModularInstance } from '@firebase/util'; /** * Gets the list of possible sign in methods for the given email address. This method returns an - * empty list when [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled, irrespective of the number of - * authentication methods available for the given email. + * empty list when + * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection} + * is enabled, irrespective of the number of authentication methods available for the given email. * * @remarks * This is useful to differentiate methods of sign-in for the same provider, eg. @@ -47,7 +48,8 @@ import { getModularInstance } from '@firebase/util'; * @param email - The user's email address. * * Deprecated. Migrating off of this method is recommended as a security best-practice. - * Learn more in the Identity Platform documentation for [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection). + * Learn more in the Identity Platform documentation for + * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection}. * @public */ export async function fetchSignInMethodsForEmail( diff --git a/packages/auth/src/core/strategies/email_and_password.ts b/packages/auth/src/core/strategies/email_and_password.ts index 86855dfa8b2..f98ef683a92 100644 --- a/packages/auth/src/core/strategies/email_and_password.ts +++ b/packages/auth/src/core/strategies/email_and_password.ts @@ -29,7 +29,10 @@ import { signUp, SignUpRequest } from '../../api/authentication/sign_up'; import { MultiFactorInfoImpl } from '../../mfa/mfa_info'; import { EmailAuthProvider } from '../providers/email'; import { UserCredentialImpl } from '../user/user_credential_impl'; -import { _assert } from '../util/assert'; +import { + _assert, + _serverAppCurrentUserOperationNotSupportedError +} from '../util/assert'; import { _setActionCodeSettingsOnRequest } from './action_code_settings'; import { signInWithCredential } from './credential'; import { _castAuth } from '../auth/auth_impl'; @@ -39,6 +42,7 @@ import { OperationType } from '../../model/enums'; import { handleRecaptchaFlow } from '../../platform_browser/recaptcha/recaptcha_enterprise_verifier'; import { IdTokenResponse } from '../../model/id_token'; import { RecaptchaActionName, RecaptchaClientType } from '../../api'; +import { _isFirebaseServerApp } from '@firebase/app'; /** * Updates the password policy cached in the {@link Auth} instance if a policy is already @@ -63,7 +67,8 @@ async function recachePasswordPolicy(auth: Auth): Promise { /** * Sends a password reset email to the given email address. This method does not throw an error when * there's no user account with the given email address and - * [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled. + * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection} + * is enabled. * * @remarks * To complete the password reset, call {@link confirmPasswordReset} with the code supplied in @@ -253,6 +258,9 @@ export async function verifyPasswordResetCode( * * User account creation can fail if the account already exists or the password is invalid. * + * This method is not supported on {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * * Note: The email address acts as a unique identifier for the user and enables an email-based * password reset. This function will create a new user account and set the initial user password. * @@ -267,6 +275,11 @@ export async function createUserWithEmailAndPassword( email: string, password: string ): Promise { + if (_isFirebaseServerApp(auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(auth) + ); + } const authInternal = _castAuth(auth); const request: SignUpRequest = { returnSecureToken: true, @@ -304,14 +317,19 @@ export async function createUserWithEmailAndPassword( * Asynchronously signs in using an email and password. * * @remarks - * Fails with an error if the email address and password do not match. - * When [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled, - * this method fails with "auth/invalid-credential" in case of an invalid email/password. + * Fails with an error if the email address and password do not match. When + * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection} + * is enabled, this method fails with "auth/invalid-credential" in case of an invalid + * email/password. + * + * This method is not supported on {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. * * Note: The user's password is NOT the password used to access the user's email account. The * email address serves as a unique identifier for the user, and the password is used to access * the user's account in your Firebase project. See also: {@link createUserWithEmailAndPassword}. * + * * @param auth - The {@link Auth} instance. * @param email - The users email address. * @param password - The users password. @@ -323,6 +341,11 @@ export function signInWithEmailAndPassword( email: string, password: string ): Promise { + if (_isFirebaseServerApp(auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(auth) + ); + } return signInWithCredential( getModularInstance(auth), EmailAuthProvider.credential(email, password) diff --git a/packages/auth/src/core/strategies/email_link.ts b/packages/auth/src/core/strategies/email_link.ts index 55f95226656..351583a6bb5 100644 --- a/packages/auth/src/core/strategies/email_link.ts +++ b/packages/auth/src/core/strategies/email_link.ts @@ -34,6 +34,8 @@ import { getModularInstance } from '@firebase/util'; import { _castAuth } from '../auth/auth_impl'; import { handleRecaptchaFlow } from '../../platform_browser/recaptcha/recaptcha_enterprise_verifier'; import { RecaptchaActionName, RecaptchaClientType } from '../../api'; +import { _isFirebaseServerApp } from '@firebase/app'; +import { _serverAppCurrentUserOperationNotSupportedError } from '../../core/util/assert'; /** * Sends a sign-in email link to the user with the specified email. @@ -131,6 +133,9 @@ export function isSignInWithEmailLink(auth: Auth, emailLink: string): boolean { * * Fails with an error if the email address is invalid or OTP in email link expires. * + * This method is not supported by {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * * Note: Confirm the link is a sign-in email link before calling this method firebase.auth.Auth.isSignInWithEmailLink. * * @example @@ -154,6 +159,7 @@ export function isSignInWithEmailLink(auth: Auth, emailLink: string): boolean { * } * ``` * + * * @param auth - The {@link Auth} instance. * @param email - The user's email address. * @param emailLink - The link sent to the user's email address. @@ -165,6 +171,11 @@ export async function signInWithEmailLink( email: string, emailLink?: string ): Promise { + if (_isFirebaseServerApp(auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(auth) + ); + } const authModular = getModularInstance(auth); const credential = EmailAuthProvider.credentialWithLink( email, diff --git a/packages/auth/src/core/user/account_info.ts b/packages/auth/src/core/user/account_info.ts index 3f061630435..b06c97b9a0f 100644 --- a/packages/auth/src/core/user/account_info.ts +++ b/packages/auth/src/core/user/account_info.ts @@ -26,6 +26,8 @@ import { UserInternal } from '../../model/user'; import { _logoutIfInvalidated } from './invalidation'; import { getModularInstance } from '@firebase/util'; import { ProviderId } from '../../model/enums'; +import { _isFirebaseServerApp } from '@firebase/app'; +import { _serverAppCurrentUserOperationNotSupportedError } from '../../core/util/assert'; /** * Updates a user's profile data. @@ -81,6 +83,9 @@ export async function updateProfile( * An email will be sent to the original email address (if it was set) that allows to revoke the * email address change, in order to protect them from account hijacking. * + * This method is not supported on any {@link User} signed in by {@link Auth} instances + * created with a {@link @firebase/app#FirebaseServerApp}. + * * Important: this is a security sensitive operation that requires the user to have recently signed * in. If this requirement isn't met, ask the user to authenticate again and then call * {@link reauthenticateWithCredential}. @@ -88,17 +93,21 @@ export async function updateProfile( * @param user - The user. * @param newEmail - The new email address. * - * Throws "auth/operation-not-allowed" error when [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled. + * Throws "auth/operation-not-allowed" error when + * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection} + * is enabled. * Deprecated - Use {@link verifyBeforeUpdateEmail} instead. * * @public */ export function updateEmail(user: User, newEmail: string): Promise { - return updateEmailOrPassword( - getModularInstance(user) as UserInternal, - newEmail, - null - ); + const userInternal = getModularInstance(user) as UserInternal; + if (_isFirebaseServerApp(userInternal.auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(userInternal.auth) + ); + } + return updateEmailOrPassword(userInternal, newEmail, null); } /** diff --git a/packages/auth/src/core/user/reauthenticate.ts b/packages/auth/src/core/user/reauthenticate.ts index a88b9479b51..7e888c2c1d7 100644 --- a/packages/auth/src/core/user/reauthenticate.ts +++ b/packages/auth/src/core/user/reauthenticate.ts @@ -25,6 +25,8 @@ import { _assert, _fail } from '../util/assert'; import { _parseToken } from './id_token_result'; import { _logoutIfInvalidated } from './invalidation'; import { UserCredentialImpl } from './user_credential_impl'; +import { _isFirebaseServerApp } from '@firebase/app'; +import { _serverAppCurrentUserOperationNotSupportedError } from '../../core/util/assert'; export async function _reauthenticate( user: UserInternal, @@ -32,6 +34,11 @@ export async function _reauthenticate( bypassAuthState = false ): Promise { const { auth } = user; + if (_isFirebaseServerApp(auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(auth) + ); + } const operationType = OperationType.REAUTHENTICATE; try { diff --git a/packages/auth/src/core/user/reload.ts b/packages/auth/src/core/user/reload.ts index fc0a33b937a..ac9a1683e2d 100644 --- a/packages/auth/src/core/user/reload.ts +++ b/packages/auth/src/core/user/reload.ts @@ -102,7 +102,7 @@ function mergeProviderData( return [...deduped, ...newData]; } -function extractProviderData(providers: ProviderUserInfo[]): UserInfo[] { +export function extractProviderData(providers: ProviderUserInfo[]): UserInfo[] { return providers.map(({ providerId, ...provider }) => { return { providerId, diff --git a/packages/auth/src/core/user/token_manager.test.ts b/packages/auth/src/core/user/token_manager.test.ts index e1648d4eb32..b2e1609692f 100644 --- a/packages/auth/src/core/user/token_manager.test.ts +++ b/packages/auth/src/core/user/token_manager.test.ts @@ -144,8 +144,35 @@ describe('core/user/token_manager', () => { }); }); - it('returns null if the refresh token is missing', async () => { - expect(await stsTokenManager.getToken(auth)).to.be.null; + it('returns non-null if the refresh token is missing but token still valid', async () => { + Object.assign(stsTokenManager, { + accessToken: 'token', + expirationTime: now + 100_000 + }); + const tokens = await stsTokenManager.getToken(auth, false); + expect(tokens).to.eql('token'); + }); + + it('throws an error if the refresh token is missing and force refresh is true', async () => { + Object.assign(stsTokenManager, { + accessToken: 'token', + expirationTime: now + 100_000 + }); + await expect(stsTokenManager.getToken(auth, true)).to.be.rejectedWith( + FirebaseError, + "Firebase: The user's credential is no longer valid. The user must sign in again. (auth/user-token-expired)" + ); + }); + + it('throws an error if the refresh token is missing and token is no longer valid', async () => { + Object.assign(stsTokenManager, { + accessToken: 'old-access-token', + expirationTime: now - 1 + }); + await expect(stsTokenManager.getToken(auth)).to.be.rejectedWith( + FirebaseError, + "Firebase: The user's credential is no longer valid. The user must sign in again. (auth/user-token-expired)" + ); }); it('throws an error if expired but refresh token is missing', async () => { diff --git a/packages/auth/src/core/user/token_manager.ts b/packages/auth/src/core/user/token_manager.ts index 5f56f88afb6..14969005d89 100644 --- a/packages/auth/src/core/user/token_manager.ts +++ b/packages/auth/src/core/user/token_manager.ts @@ -73,20 +73,22 @@ export class StsTokenManager { ); } + updateFromIdToken(idToken: string): void { + _assert(idToken.length !== 0, AuthErrorCode.INTERNAL_ERROR); + const expiresIn = _tokenExpiresIn(idToken); + this.updateTokensAndExpiration(idToken, null, expiresIn); + } + async getToken( auth: AuthInternal, forceRefresh = false ): Promise { - _assert( - !this.accessToken || this.refreshToken, - auth, - AuthErrorCode.TOKEN_EXPIRED - ); - if (!forceRefresh && this.accessToken && !this.isExpired) { return this.accessToken; } + _assert(this.refreshToken, auth, AuthErrorCode.TOKEN_EXPIRED); + if (this.refreshToken) { await this.refresh(auth, this.refreshToken!); return this.accessToken; @@ -113,7 +115,7 @@ export class StsTokenManager { private updateTokensAndExpiration( accessToken: string, - refreshToken: string, + refreshToken: string | null, expiresInSec: number ): void { this.refreshToken = refreshToken || null; diff --git a/packages/auth/src/core/user/user_impl.ts b/packages/auth/src/core/user/user_impl.ts index 44192cc4617..aeb031ab855 100644 --- a/packages/auth/src/core/user/user_impl.ts +++ b/packages/auth/src/core/user/user_impl.ts @@ -15,11 +15,11 @@ * limitations under the License. */ -import { IdTokenResult } from '../../model/public_types'; +import { IdTokenResult, UserInfo } from '../../model/public_types'; import { NextFn } from '@firebase/util'; - import { APIUserInfo, + GetAccountInfoResponse, deleteAccount } from '../../api/account_management/account'; import { FinalizeMfaResponse } from '../../api/authentication/mfa'; @@ -32,14 +32,18 @@ import { } from '../../model/user'; import { AuthErrorCode } from '../errors'; import { PersistedBlob } from '../persistence'; -import { _assert } from '../util/assert'; +import { + _assert, + _serverAppCurrentUserOperationNotSupportedError +} from '../util/assert'; import { getIdTokenResult } from './id_token_result'; import { _logoutIfInvalidated } from './invalidation'; import { ProactiveRefresh } from './proactive_refresh'; -import { _reloadWithoutSaving, reload } from './reload'; +import { extractProviderData, _reloadWithoutSaving, reload } from './reload'; import { StsTokenManager } from './token_manager'; import { UserMetadata } from './user_metadata'; import { ProviderId } from '../../model/enums'; +import { _isFirebaseServerApp } from '@firebase/app'; function assertStringOrUndefined( assertion: unknown, @@ -200,6 +204,11 @@ export class UserImpl implements UserInternal { } async delete(): Promise { + if (_isFirebaseServerApp(this.auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(this.auth) + ); + } const idToken = await this.getIdToken(); await _logoutIfInvalidated(this, deleteAccount(this.auth, { idToken })); this.stsTokenManager.clearRefreshToken(); @@ -333,4 +342,59 @@ export class UserImpl implements UserInternal { await _reloadWithoutSaving(user); return user; } + + /** + * Initialize a User from an idToken server response + * @param auth + * @param idTokenResponse + */ + static async _fromGetAccountInfoResponse( + auth: AuthInternal, + response: GetAccountInfoResponse, + idToken: string + ): Promise { + const coreAccount = response.users[0]; + _assert(coreAccount.localId !== undefined, AuthErrorCode.INTERNAL_ERROR); + + const providerData: UserInfo[] = + coreAccount.providerUserInfo !== undefined + ? extractProviderData(coreAccount.providerUserInfo) + : []; + + const isAnonymous = + !(coreAccount.email && coreAccount.passwordHash) && !providerData?.length; + + const stsTokenManager = new StsTokenManager(); + stsTokenManager.updateFromIdToken(idToken); + + // Initialize the Firebase Auth user. + const user = new UserImpl({ + uid: coreAccount.localId, + auth, + stsTokenManager, + isAnonymous + }); + + // update the user with data from the GetAccountInfo response. + const updates: Partial = { + uid: coreAccount.localId, + displayName: coreAccount.displayName || null, + photoURL: coreAccount.photoUrl || null, + email: coreAccount.email || null, + emailVerified: coreAccount.emailVerified || false, + phoneNumber: coreAccount.phoneNumber || null, + tenantId: coreAccount.tenantId || null, + providerData, + metadata: new UserMetadata( + coreAccount.createdAt, + coreAccount.lastLoginAt + ), + isAnonymous: + !(coreAccount.email && coreAccount.passwordHash) && + !providerData?.length + }; + + Object.assign(user, updates); + return user; + } } diff --git a/packages/auth/src/core/util/assert.ts b/packages/auth/src/core/util/assert.ts index adb391b033a..51dff0793e2 100644 --- a/packages/auth/src/core/util/assert.ts +++ b/packages/auth/src/core/util/assert.ts @@ -102,6 +102,16 @@ export function _errorWithCustomMessage( }); } +export function _serverAppCurrentUserOperationNotSupportedError( + auth: Auth +): FirebaseError { + return _errorWithCustomMessage( + auth, + AuthErrorCode.OPERATION_NOT_SUPPORTED, + 'Operations that alter the current user are not supported in conjunction with FirebaseServerApp' + ); +} + export function _assertInstanceOf( auth: Auth, object: object, diff --git a/packages/auth/src/core/util/emulator.test.ts b/packages/auth/src/core/util/emulator.test.ts index 65337681d5b..17a916917b1 100644 --- a/packages/auth/src/core/util/emulator.test.ts +++ b/packages/auth/src/core/util/emulator.test.ts @@ -23,23 +23,23 @@ import { _emulatorUrl } from './emulator'; describe('core/util/emulator', () => { const config: ConfigInternal = { emulator: { - url: 'http://localhost:4000/' + url: 'http://127.0.0.1:4000/' } } as ConfigInternal; it('builds the proper URL with no path', () => { - expect(_emulatorUrl(config)).to.eq('http://localhost:4000/'); + expect(_emulatorUrl(config)).to.eq('http://127.0.0.1:4000/'); }); it('builds the proper URL with a path', () => { expect(_emulatorUrl(config, '/test/path')).to.eq( - 'http://localhost:4000/test/path' + 'http://127.0.0.1:4000/test/path' ); }); it('builds the proper URL with a path missing separator', () => { expect(_emulatorUrl(config, 'test/path')).to.eq( - 'http://localhost:4000/test/path' + 'http://127.0.0.1:4000/test/path' ); }); }); diff --git a/packages/auth/src/core/util/version.test.ts b/packages/auth/src/core/util/version.test.ts index 86ab624f22d..80cfc41b378 100644 --- a/packages/auth/src/core/util/version.test.ts +++ b/packages/auth/src/core/util/version.test.ts @@ -56,5 +56,13 @@ describe('core/util/_getClientVersion', () => { ); }); }); + + context('Web Extension', () => { + it('should set the correct version', () => { + expect(_getClientVersion(ClientPlatform.WEB_EXTENSION)).to.eq( + `WebExtension/JsCore/${SDK_VERSION}/FirebaseCore-web` + ); + }); + }); } }); diff --git a/packages/auth/src/core/util/version.ts b/packages/auth/src/core/util/version.ts index dae126296d6..777b4eadc6d 100644 --- a/packages/auth/src/core/util/version.ts +++ b/packages/auth/src/core/util/version.ts @@ -31,7 +31,8 @@ export const enum ClientPlatform { NODE = 'Node', REACT_NATIVE = 'ReactNative', CORDOVA = 'Cordova', - WORKER = 'Worker' + WORKER = 'Worker', + WEB_EXTENSION = 'WebExtension' } /* diff --git a/packages/auth/src/model/public_types.ts b/packages/auth/src/model/public_types.ts index 0390ba5e30d..07e56a6b9aa 100644 --- a/packages/auth/src/model/public_types.ts +++ b/packages/auth/src/model/public_types.ts @@ -70,7 +70,7 @@ export interface Config { /** * Interface representing reCAPTCHA parameters. * - * See the [reCAPTCHA docs](https://developers.google.com/recaptcha/docs/display#render_param) + * See the {@link https://developers.google.com/recaptcha/docs/display#render_param | reCAPTCHA docs} * for the list of accepted parameters. All parameters are accepted except for `sitekey`: Firebase Auth * provisions a reCAPTCHA for each project and will configure the site key upon rendering. * @@ -322,6 +322,10 @@ export interface Auth { useDeviceLanguage(): void; /** * Signs out the current user. This does not automatically revoke the user's ID token. + * + * @remarks + * This method is not supported by {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. */ signOut(): Promise; } @@ -1004,6 +1008,9 @@ export interface User extends UserInfo { * Important: this is a security-sensitive operation that requires the user to have recently * signed in. If this requirement isn't met, ask the user to authenticate again and then call * one of the reauthentication methods like {@link reauthenticateWithCredential}. + * + * This method is not supported on any {@link User} signed in by {@link Auth} instances + * created with a {@link @firebase/app#FirebaseServerApp}. */ delete(): Promise; /** diff --git a/packages/auth/src/platform_browser/iframe/gapi.ts b/packages/auth/src/platform_browser/iframe/gapi.ts index a76cf886d34..7d9633043fe 100644 --- a/packages/auth/src/platform_browser/iframe/gapi.ts +++ b/packages/auth/src/platform_browser/iframe/gapi.ts @@ -104,7 +104,7 @@ function loadGapi(auth: AuthInternal): Promise { }; // Load GApi loader. return js - ._loadJS(`https://apis.google.com/js/api.js?onload=${cbName}`) + ._loadJS(`${js._gapiScriptUrl()}?onload=${cbName}`) .catch(e => reject(e)); } }).catch(error => { diff --git a/packages/auth/src/platform_browser/index.ts b/packages/auth/src/platform_browser/index.ts index 9bfe4e3b01a..f94525bfeb7 100644 --- a/packages/auth/src/platform_browser/index.ts +++ b/packages/auth/src/platform_browser/index.ts @@ -31,6 +31,9 @@ import { indexedDBLocalPersistence } from './persistence/indexed_db'; import { browserPopupRedirectResolver } from './popup_redirect'; import { Auth, User } from '../model/public_types'; import { getDefaultEmulatorHost, getExperimentalSetting } from '@firebase/util'; +import { _setExternalJSProvider } from './load_js'; +import { _createError } from '../core/util/assert'; +import { AuthErrorCode } from '../core/errors'; const DEFAULT_ID_TOKEN_MAX_AGE = 5 * 60; const authIdTokenMaxAge = @@ -86,13 +89,22 @@ export function getAuth(app: FirebaseApp = getApp()): Auth { ] }); - const authTokenSyncUrl = getExperimentalSetting('authTokenSyncURL'); - if (authTokenSyncUrl) { - const mintCookie = mintCookieFactory(authTokenSyncUrl); - beforeAuthStateChanged(auth, mintCookie, () => - mintCookie(auth.currentUser) - ); - onIdTokenChanged(auth, user => mintCookie(user)); + const authTokenSyncPath = getExperimentalSetting('authTokenSyncURL'); + // Only do the Cookie exchange in a secure context + if ( + authTokenSyncPath && + typeof isSecureContext === 'boolean' && + isSecureContext + ) { + // Don't allow urls (XSS possibility), only paths on the same domain + const authTokenSyncUrl = new URL(authTokenSyncPath, location.origin); + if (location.origin === authTokenSyncUrl.origin) { + const mintCookie = mintCookieFactory(authTokenSyncUrl.toString()); + beforeAuthStateChanged(auth, mintCookie, () => + mintCookie(auth.currentUser) + ); + onIdTokenChanged(auth, user => mintCookie(user)); + } } const authEmulatorHost = getDefaultEmulatorHost('auth'); @@ -103,4 +115,32 @@ export function getAuth(app: FirebaseApp = getApp()): Auth { return auth; } +function getScriptParentElement(): HTMLDocument | HTMLHeadElement { + return document.getElementsByTagName('head')?.[0] ?? document; +} + +_setExternalJSProvider({ + loadJS(url: string): Promise { + // TODO: consider adding timeout support & cancellation + return new Promise((resolve, reject) => { + const el = document.createElement('script'); + el.setAttribute('src', url); + el.onload = resolve; + el.onerror = e => { + const error = _createError(AuthErrorCode.INTERNAL_ERROR); + error.customData = e as unknown as Record; + reject(error); + }; + el.type = 'text/javascript'; + el.charset = 'UTF-8'; + getScriptParentElement().appendChild(el); + }); + }, + + gapiScript: 'https://apis.google.com/js/api.js', + recaptchaV2Script: 'https://www.google.com/recaptcha/api.js', + recaptchaEnterpriseScript: + 'https://www.google.com/recaptcha/enterprise.js?render=' +}); + registerAuth(ClientPlatform.BROWSER); diff --git a/packages/auth/src/platform_browser/load_js.test.ts b/packages/auth/src/platform_browser/load_js.test.ts index df6e994f614..972fb292065 100644 --- a/packages/auth/src/platform_browser/load_js.test.ts +++ b/packages/auth/src/platform_browser/load_js.test.ts @@ -19,7 +19,13 @@ import { expect, use } from 'chai'; import * as sinon from 'sinon'; import sinonChai from 'sinon-chai'; -import { _generateCallbackName, _loadJS } from './load_js'; +import { + _generateCallbackName, + _loadJS, + _setExternalJSProvider +} from './load_js'; +import { _createError } from '../core/util/assert'; +import { AuthErrorCode } from '../core/errors'; use(sinonChai); @@ -34,6 +40,25 @@ describe('platform-browser/load_js', () => { describe('_loadJS', () => { it('sets the appropriate properties', () => { + _setExternalJSProvider({ + loadJS(url: string): Promise { + return new Promise((resolve, reject) => { + const el = document.createElement('script'); + el.setAttribute('src', url); + el.onload = resolve; + el.onerror = e => { + const error = _createError(AuthErrorCode.INTERNAL_ERROR); + error.customData = e as unknown as Record; + reject(error); + }; + el.type = 'text/javascript'; + el.charset = 'UTF-8'; + }); + }, + gapiScript: 'https://gapiScript', + recaptchaV2Script: 'https://recaptchaV2Script', + recaptchaEnterpriseScript: 'https://recaptchaEnterpriseScript' + }); const el = document.createElement('script'); sinon.stub(el); // Prevent actually setting the src attribute sinon.stub(document, 'createElement').returns(el); diff --git a/packages/auth/src/platform_browser/load_js.ts b/packages/auth/src/platform_browser/load_js.ts index 229442b0b51..b7eb0ce4690 100644 --- a/packages/auth/src/platform_browser/load_js.ts +++ b/packages/auth/src/platform_browser/load_js.ts @@ -15,28 +15,41 @@ * limitations under the License. */ -import { AuthErrorCode } from '../core/errors'; -import { _createError } from '../core/util/assert'; +interface ExternalJSProvider { + loadJS(url: string): Promise; + recaptchaV2Script: string; + recaptchaEnterpriseScript: string; + gapiScript: string; +} + +let externalJSProvider: ExternalJSProvider = { + async loadJS() { + throw new Error('Unable to load external scripts'); + }, + + recaptchaV2Script: '', + recaptchaEnterpriseScript: '', + gapiScript: '' +}; -function getScriptParentElement(): HTMLDocument | HTMLHeadElement { - return document.getElementsByTagName('head')?.[0] ?? document; +export function _setExternalJSProvider(p: ExternalJSProvider): void { + externalJSProvider = p; } export function _loadJS(url: string): Promise { - // TODO: consider adding timeout support & cancellation - return new Promise((resolve, reject) => { - const el = document.createElement('script'); - el.setAttribute('src', url); - el.onload = resolve; - el.onerror = e => { - const error = _createError(AuthErrorCode.INTERNAL_ERROR); - error.customData = e as unknown as Record; - reject(error); - }; - el.type = 'text/javascript'; - el.charset = 'UTF-8'; - getScriptParentElement().appendChild(el); - }); + return externalJSProvider.loadJS(url); +} + +export function _recaptchaV2ScriptUrl(): string { + return externalJSProvider.recaptchaV2Script; +} + +export function _recaptchaEnterpriseScriptUrl(): string { + return externalJSProvider.recaptchaEnterpriseScript; +} + +export function _gapiScriptUrl(): string { + return externalJSProvider.gapiScript; } export function _generateCallbackName(prefix: string): string { diff --git a/packages/auth/src/platform_browser/recaptcha/recaptcha_enterprise_verifier.ts b/packages/auth/src/platform_browser/recaptcha/recaptcha_enterprise_verifier.ts index 8d188032e36..cccd737defc 100644 --- a/packages/auth/src/platform_browser/recaptcha/recaptcha_enterprise_verifier.ts +++ b/packages/auth/src/platform_browser/recaptcha/recaptcha_enterprise_verifier.ts @@ -31,9 +31,6 @@ import { _castAuth } from '../../core/auth/auth_impl'; import * as jsHelpers from '../load_js'; import { AuthErrorCode } from '../../core/errors'; -const RECAPTCHA_ENTERPRISE_URL = - 'https://www.google.com/recaptcha/enterprise.js?render='; - export const RECAPTCHA_ENTERPRISE_VERIFIER_TYPE = 'recaptcha-enterprise'; export const FAKE_TOKEN = 'NO_RECAPTCHA'; @@ -134,8 +131,12 @@ export class RecaptchaEnterpriseVerifier { ); return; } + let url = jsHelpers._recaptchaEnterpriseScriptUrl(); + if (url.length !== 0) { + url += siteKey; + } jsHelpers - ._loadJS(RECAPTCHA_ENTERPRISE_URL + siteKey) + ._loadJS(url) .then(() => { retrieveRecaptchaToken(siteKey, resolve, reject); }) diff --git a/packages/auth/src/platform_browser/recaptcha/recaptcha_loader.ts b/packages/auth/src/platform_browser/recaptcha/recaptcha_loader.ts index 2b945464cea..f510436223f 100644 --- a/packages/auth/src/platform_browser/recaptcha/recaptcha_loader.ts +++ b/packages/auth/src/platform_browser/recaptcha/recaptcha_loader.ts @@ -30,7 +30,6 @@ import { MockReCaptcha } from './recaptcha_mock'; // to be kept around export const _JSLOAD_CALLBACK = jsHelpers._generateCallbackName('rcb'); const NETWORK_TIMEOUT_DELAY = new Delay(30000, 60000); -const RECAPTCHA_BASE = 'https://www.google.com/recaptcha/api.js?'; /** * We need to mark this interface as internal explicitly to exclude it in the public typings, because @@ -91,7 +90,7 @@ export class ReCaptchaLoaderImpl implements ReCaptchaLoader { resolve(recaptcha); }; - const url = `${RECAPTCHA_BASE}?${querystring({ + const url = `${jsHelpers._recaptchaV2ScriptUrl()}?${querystring({ onload: _JSLOAD_CALLBACK, render: 'explicit', hl diff --git a/packages/auth/src/platform_browser/strategies/phone.ts b/packages/auth/src/platform_browser/strategies/phone.ts index 745385c2db9..9e0c34d7058 100644 --- a/packages/auth/src/platform_browser/strategies/phone.ts +++ b/packages/auth/src/platform_browser/strategies/phone.ts @@ -31,7 +31,10 @@ import { ApplicationVerifierInternal } from '../../model/application_verifier'; import { PhoneAuthCredential } from '../../core/credentials/phone'; import { AuthErrorCode } from '../../core/errors'; import { _assertLinkedStatus, _link } from '../../core/user/link_unlink'; -import { _assert } from '../../core/util/assert'; +import { + _assert, + _serverAppCurrentUserOperationNotSupportedError +} from '../../core/util/assert'; import { AuthInternal } from '../../model/auth'; import { linkWithCredential, @@ -47,6 +50,7 @@ import { RECAPTCHA_VERIFIER_TYPE } from '../recaptcha/recaptcha_verifier'; import { _castAuth } from '../../core/auth/auth_impl'; import { getModularInstance } from '@firebase/util'; import { ProviderId } from '../../model/enums'; +import { _isFirebaseServerApp } from '@firebase/app'; interface OnConfirmationCallback { (credential: PhoneAuthCredential): Promise; @@ -82,7 +86,8 @@ class ConfirmationResultImpl implements ConfirmationResult { * {@link RecaptchaVerifier} (like React Native), but you need to use a * third-party {@link ApplicationVerifier} implementation. * - * This method does not work in a Node.js environment. + * This method does not work in a Node.js environment or with {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. * * @example * ```javascript @@ -104,6 +109,11 @@ export async function signInWithPhoneNumber( phoneNumber: string, appVerifier: ApplicationVerifier ): Promise { + if (_isFirebaseServerApp(auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(auth) + ); + } const authInternal = _castAuth(auth); const verificationId = await _verifyPhoneNumber( authInternal, @@ -150,7 +160,8 @@ export async function linkWithPhoneNumber( * @remarks * Use before operations such as {@link updatePassword} that require tokens from recent sign-in attempts. * - * This method does not work in a Node.js environment. + * This method does not work in a Node.js environment or on any {@link User} signed in by + * {@link Auth} instances created with a {@link @firebase/app#FirebaseServerApp}. * * @param user - The user. * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101). @@ -164,6 +175,11 @@ export async function reauthenticateWithPhoneNumber( appVerifier: ApplicationVerifier ): Promise { const userInternal = getModularInstance(user) as UserInternal; + if (_isFirebaseServerApp(userInternal.auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(userInternal.auth) + ); + } const verificationId = await _verifyPhoneNumber( userInternal.auth, phoneNumber, @@ -259,7 +275,8 @@ export async function _verifyPhoneNumber( * Updates the user's phone number. * * @remarks - * This method does not work in a Node.js environment. + * This method does not work in a Node.js environment or on any {@link User} signed in by + * {@link Auth} instances created with a {@link @firebase/app#FirebaseServerApp}. * * @example * ``` @@ -281,5 +298,11 @@ export async function updatePhoneNumber( user: User, credential: PhoneAuthCredential ): Promise { - await _link(getModularInstance(user) as UserInternal, credential); + const userInternal = getModularInstance(user) as UserInternal; + if (_isFirebaseServerApp(userInternal.auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(userInternal.auth) + ); + } + await _link(userInternal, credential); } diff --git a/packages/auth/src/platform_browser/strategies/popup.ts b/packages/auth/src/platform_browser/strategies/popup.ts index e47e03cd3f7..12ba128aca9 100644 --- a/packages/auth/src/platform_browser/strategies/popup.ts +++ b/packages/auth/src/platform_browser/strategies/popup.ts @@ -44,6 +44,7 @@ import { AuthPopup } from '../util/popup'; import { AbstractPopupRedirectOperation } from '../../core/strategies/abstract_popup_redirect_operation'; import { FederatedAuthProvider } from '../../core/providers/federated'; import { getModularInstance } from '@firebase/util'; +import { _isFirebaseServerApp } from '@firebase/app'; /* * The event timeout is the same on mobile and desktop, no need for Delay. Set this to 8s since @@ -63,7 +64,8 @@ export const _POLL_WINDOW_CLOSE_TIMEOUT = new Delay(2000, 10000); * If succeeds, returns the signed in user along with the provider's credential. If sign in was * unsuccessful, returns an error object containing additional information about the error. * - * This method does not work in a Node.js environment. + * This method does not work in a Node.js environment or with {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. * * @example * ```javascript @@ -91,6 +93,11 @@ export async function signInWithPopup( provider: AuthProvider, resolver?: PopupRedirectResolver ): Promise { + if (_isFirebaseServerApp(auth.app)) { + return Promise.reject( + _createError(auth, AuthErrorCode.OPERATION_NOT_SUPPORTED) + ); + } const authInternal = _castAuth(auth); _assertInstanceOf(auth, provider, FederatedAuthProvider); const resolverInternal = _withDefaultResolver(authInternal, resolver); @@ -111,7 +118,8 @@ export async function signInWithPopup( * If the reauthentication is successful, the returned result will contain the user and the * provider's credential. * - * This method does not work in a Node.js environment. + * This method does not work in a Node.js environment or on any {@link User} signed in by + * {@link Auth} instances created with a {@link @firebase/app#FirebaseServerApp}. * * @example * ```javascript @@ -136,6 +144,11 @@ export async function reauthenticateWithPopup( resolver?: PopupRedirectResolver ): Promise { const userInternal = getModularInstance(user) as UserInternal; + if (_isFirebaseServerApp(userInternal.auth.app)) { + return Promise.reject( + _createError(userInternal.auth, AuthErrorCode.OPERATION_NOT_SUPPORTED) + ); + } _assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider); const resolverInternal = _withDefaultResolver(userInternal.auth, resolver); const action = new PopupOperation( diff --git a/packages/auth/src/platform_browser/strategies/redirect.ts b/packages/auth/src/platform_browser/strategies/redirect.ts index 8586ea589d2..1084fab1b6f 100644 --- a/packages/auth/src/platform_browser/strategies/redirect.ts +++ b/packages/auth/src/platform_browser/strategies/redirect.ts @@ -25,7 +25,10 @@ import { import { _castAuth } from '../../core/auth/auth_impl'; import { _assertLinkedStatus } from '../../core/user/link_unlink'; -import { _assertInstanceOf } from '../../core/util/assert'; +import { + _assertInstanceOf, + _serverAppCurrentUserOperationNotSupportedError +} from '../../core/util/assert'; import { _generateEventId } from '../../core/util/event_id'; import { AuthEventType } from '../../model/popup_redirect'; import { UserInternal } from '../../model/user'; @@ -36,6 +39,7 @@ import { } from '../../core/strategies/redirect'; import { FederatedAuthProvider } from '../../core/providers/federated'; import { getModularInstance } from '@firebase/util'; +import { _isFirebaseServerApp } from '@firebase/app'; /** * Authenticates a Firebase client using a full-page redirect flow. @@ -45,7 +49,8 @@ import { getModularInstance } from '@firebase/util'; * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices * | best practices} when using {@link signInWithRedirect}. * - * This method does not work in a Node.js environment. + * This method does not work in a Node.js environment or with {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. * * @example * ```javascript @@ -93,6 +98,11 @@ export async function _signInWithRedirect( provider: AuthProvider, resolver?: PopupRedirectResolver ): Promise { + if (_isFirebaseServerApp(auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(auth) + ); + } const authInternal = _castAuth(auth); _assertInstanceOf(auth, provider, FederatedAuthProvider); // Wait for auth initialization to complete, this will process pending redirects and clear the @@ -116,7 +126,8 @@ export async function _signInWithRedirect( * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices * | best practices} when using {@link reauthenticateWithRedirect}. * - * This method does not work in a Node.js environment. + * This method does not work in a Node.js environment or with {@link Auth} instances + * created with a {@link @firebase/app#FirebaseServerApp}. * * @example * ```javascript @@ -161,6 +172,11 @@ export async function _reauthenticateWithRedirect( ): Promise { const userInternal = getModularInstance(user) as UserInternal; _assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider); + if (_isFirebaseServerApp(userInternal.auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(userInternal.auth) + ); + } // Wait for auth initialization to complete, this will process pending redirects and clear the // PENDING_REDIRECT_KEY in persistence. This should be completed before starting a new // redirect and creating a PENDING_REDIRECT_KEY entry. @@ -185,7 +201,8 @@ export async function _reauthenticateWithRedirect( * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices * | best practices} when using {@link linkWithRedirect}. * - * This method does not work in a Node.js environment. + * This method does not work in a Node.js environment or with {@link Auth} instances + * created with a {@link @firebase/app#FirebaseServerApp}. * * @example * ```javascript @@ -247,7 +264,8 @@ export async function _linkWithRedirect( * If sign-in succeeded, returns the signed in user. If sign-in was unsuccessful, fails with an * error. If no redirect operation was called, returns `null`. * - * This method does not work in a Node.js environment. + * This method does not work in a Node.js environment or with {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. * * @example * ```javascript @@ -293,6 +311,11 @@ export async function _getRedirectResult( resolverExtern?: PopupRedirectResolver, bypassAuthState = false ): Promise { + if (_isFirebaseServerApp(auth.app)) { + return Promise.reject( + _serverAppCurrentUserOperationNotSupportedError(auth) + ); + } const authInternal = _castAuth(auth); const resolver = _withDefaultResolver(authInternal, resolverExtern); const action = new RedirectAction(authInternal, resolver, bypassAuthState); diff --git a/packages/auth/test/helpers/integration/helpers.ts b/packages/auth/test/helpers/integration/helpers.ts index 9825a8f4ba0..540c926dd99 100644 --- a/packages/auth/test/helpers/integration/helpers.ts +++ b/packages/auth/test/helpers/integration/helpers.ts @@ -16,7 +16,7 @@ */ import * as sinon from 'sinon'; -import { deleteApp, initializeApp } from '@firebase/app'; +import { FirebaseServerApp, deleteApp, initializeApp } from '@firebase/app'; import { Auth, User } from '@firebase/auth'; import { getAuth, connectAuthEmulator } from '../../../'; // Use browser OR node dist entrypoint depending on test env. @@ -80,6 +80,29 @@ export function getTestInstance(requireEmulator = false): Auth { return auth; } +export function getTestInstanceForServerApp( + serverApp: FirebaseServerApp +): Auth { + const auth = getAuth(serverApp) as IntegrationTestAuth; + auth.settings.appVerificationDisabledForTesting = true; + const emulatorUrl = getEmulatorUrl(); + + if (emulatorUrl) { + connectAuthEmulator(auth, emulatorUrl, { disableWarnings: true }); + } + + // Don't track created users on the created Auth instance like we do for Auth objects created in + // getTestInstance(...) above. FirebaseServerApp testing re-uses users created by the Auth + // instances returned by getTestInstance, so those Auth cleanup routines will suffice. + auth.cleanUp = async () => { + // If we're in an emulated environment, the emulator will clean up for us. + //if (emulatorUrl) { + // await resetEmulator(); + //} + }; + return auth; +} + export async function cleanUpTestInstance(auth: Auth): Promise { await auth.signOut(); await (auth as IntegrationTestAuth).cleanUp(); diff --git a/packages/auth/test/helpers/timeout_stub.ts b/packages/auth/test/helpers/timeout_stub.ts index d38c46cb28c..2d14519d1c8 100644 --- a/packages/auth/test/helpers/timeout_stub.ts +++ b/packages/auth/test/helpers/timeout_stub.ts @@ -36,7 +36,11 @@ export function stubTimeouts(ids?: number[]): TimerMap { let idCounter = 0; sinon.stub(window, 'setTimeout').callsFake((cb: () => void, duration) => { - callbacks[duration] = cb; + if (duration !== undefined) { + callbacks[duration] = cb; + } else { + callbacks[0] = cb; + } // For some bizarre reason setTimeout always get shoehorned into NodeJS.Timeout, // which is flat-wrong. This is the easiest way to fix it. // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/auth/test/integration/flows/firebaseserverapp.test.ts b/packages/auth/test/integration/flows/firebaseserverapp.test.ts new file mode 100644 index 00000000000..917430089c4 --- /dev/null +++ b/packages/auth/test/integration/flows/firebaseserverapp.test.ts @@ -0,0 +1,528 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect, use } from 'chai'; +import chaiAsPromised from 'chai-as-promised'; + +// eslint-disable-next-line import/no-extraneous-dependencies +import { + Auth, + createUserWithEmailAndPassword, + EmailAuthProvider, + getAdditionalUserInfo, + getRedirectResult, + GoogleAuthProvider, + onAuthStateChanged, + OperationType, + reauthenticateWithCredential, + signInAnonymously, + signInWithCredential, + signInWithCustomToken, + signInWithEmailAndPassword, + signInWithEmailLink, + signInWithRedirect, + signOut, + updateCurrentUser, + updateEmail, + updateProfile +} from '@firebase/auth'; +import { isBrowser, FirebaseError } from '@firebase/util'; +import { initializeServerApp, deleteApp } from '@firebase/app'; + +import { + cleanUpTestInstance, + getTestInstance, + getTestInstanceForServerApp, + randomEmail +} from '../../helpers/integration/helpers'; + +import { getAppConfig } from '../../helpers/integration/settings'; + +use(chaiAsPromised); + +const signInWaitDuration = 200; + +describe('Integration test: Auth FirebaseServerApp tests', () => { + let auth: Auth; + + beforeEach(() => { + auth = getTestInstance(); + }); + + afterEach(async () => { + await cleanUpTestInstance(auth); + }); + + it('signs in with anonymous user', async () => { + if (isBrowser()) { + return; + } + const userCred = await signInAnonymously(auth); + expect(auth.currentUser).to.eq(userCred.user); + expect(userCred.operationType).to.eq(OperationType.SIGN_IN); + const user = userCred.user; + expect(user).to.equal(auth.currentUser); + expect(user.isAnonymous).to.be.true; + expect(user.uid).to.be.a('string'); + expect(user.emailVerified).to.be.false; + expect(user.providerData.length).to.equal(0); + + const authIdToken = await user.getIdToken(); + const firebaseServerAppSettings = { authIdToken }; + + const serverApp = initializeServerApp(auth.app, firebaseServerAppSettings); + const serverAppAuth = getTestInstanceForServerApp(serverApp); + + console.log('auth.emulatorConfig ', auth.emulatorConfig); + console.log('serverAuth.emulatorConfig ', serverAppAuth.emulatorConfig); + + let numberServerLogins = 0; + onAuthStateChanged(serverAppAuth, serverAuthUser => { + if (serverAuthUser) { + numberServerLogins++; + + // Note, the serverAuthUser does not fully equal the standard Auth user + // since the serverAuthUser does not have a refresh token. + expect(user.uid).to.be.equal(serverAuthUser.uid); + expect(user.isAnonymous).to.be.equal(serverAuthUser.isAnonymous); + expect(user.emailVerified).to.be.equal(serverAuthUser.emailVerified); + expect(user.providerData.length).to.eq( + serverAuthUser.providerData.length + ); + } + }); + + await new Promise(resolve => { + setTimeout(resolve, signInWaitDuration); + }); + + expect(numberServerLogins).to.equal(1); + + await deleteApp(serverApp); + }); + + it('getToken operations fullfilled or rejected', async () => { + if (isBrowser()) { + return; + } + const userCred = await signInAnonymously(auth); + expect(auth.currentUser).to.eq(userCred.user); + expect(userCred.operationType).to.eq(OperationType.SIGN_IN); + const user = userCred.user; + expect(user).to.equal(auth.currentUser); + expect(user.isAnonymous).to.be.true; + expect(user.uid).to.be.a('string'); + + const authIdToken = await user.getIdToken(); + const firebaseServerAppSettings = { authIdToken }; + + const serverApp = initializeServerApp( + getAppConfig(), + firebaseServerAppSettings + ); + const serverAppAuth = getTestInstanceForServerApp(serverApp); + let numberServerLogins = 0; + onAuthStateChanged(serverAppAuth, serverAuthUser => { + if (serverAuthUser) { + numberServerLogins++; + expect(user.uid).to.be.equal(serverAuthUser.uid); + expect(serverAppAuth).to.not.be.null; + expect(serverAuthUser.getIdToken); + if (serverAppAuth) { + expect(serverAppAuth.currentUser).to.equal(serverAuthUser); + } + } + }); + + await new Promise(resolve => { + setTimeout(resolve, signInWaitDuration); + }); + + expect(numberServerLogins).to.equal(1); + expect(serverAppAuth.currentUser).to.not.be.null; + if (serverAppAuth.currentUser) { + const idToken = await serverAppAuth.currentUser.getIdToken( + /*forceRefresh=*/ false + ); + expect(idToken).to.not.be.null; + await expect(serverAppAuth.currentUser.getIdToken(/*forceRefresh=*/ true)) + .to.be.rejected; + } + + await deleteApp(serverApp); + }); + + it('invalid token does not sign in user', async () => { + if (isBrowser()) { + return; + } + const authIdToken = '{ invalid token }'; + const firebaseServerAppSettings = { authIdToken }; + + const serverApp = initializeServerApp( + getAppConfig(), + firebaseServerAppSettings + ); + const serverAppAuth = getTestInstanceForServerApp(serverApp); + expect(serverAppAuth.currentUser).to.be.null; + + let numberServerLogins = 0; + onAuthStateChanged(serverAppAuth, serverAuthUser => { + if (serverAuthUser) { + numberServerLogins++; + } + }); + + await new Promise(resolve => { + setTimeout(resolve, signInWaitDuration); + }); + + expect(numberServerLogins).to.equal(0); + expect(serverAppAuth.currentUser).to.be.null; + + await deleteApp(serverApp); + }); + + it('signs in with email crednetial user', async () => { + if (isBrowser()) { + return; + } + const email = randomEmail(); + const password = 'password'; + const userCred = await createUserWithEmailAndPassword( + auth, + email, + password + ); + const user = userCred.user; + expect(auth.currentUser).to.eq(userCred.user); + expect(userCred.operationType).to.eq(OperationType.SIGN_IN); + + const additionalUserInfo = getAdditionalUserInfo(userCred)!; + expect(additionalUserInfo.isNewUser).to.be.true; + expect(additionalUserInfo.providerId).to.eq('password'); + expect(user.isAnonymous).to.be.false; + expect(user.email).to.equal(email); + + const authIdToken = await user.getIdToken(); + const firebaseServerAppSettings = { authIdToken }; + + const serverApp = initializeServerApp( + getAppConfig(), + firebaseServerAppSettings + ); + const serverAppAuth = getTestInstanceForServerApp(serverApp); + let numberServerLogins = 0; + onAuthStateChanged(serverAppAuth, serverAuthUser => { + if (serverAuthUser) { + numberServerLogins++; + expect(serverAppAuth).to.not.be.null; + if (serverAppAuth) { + expect(serverAppAuth.currentUser).to.equal(serverAuthUser); + } + expect(user.uid).to.be.equal(serverAuthUser.uid); + expect(serverAuthUser.refreshToken).to.be.empty; + expect(user.isAnonymous).to.be.equal(serverAuthUser.isAnonymous); + expect(user.emailVerified).to.be.equal(serverAuthUser.emailVerified); + expect(user.providerData.length).to.eq( + serverAuthUser.providerData.length + ); + expect(user.email).to.equal(serverAuthUser.email); + } + }); + + await new Promise(resolve => { + setTimeout(resolve, signInWaitDuration); + }); + + expect(numberServerLogins).to.equal(1); + + await deleteApp(serverApp); + }); + + it('can reload user', async () => { + if (isBrowser()) { + return; + } + const userCred = await signInAnonymously(auth); + expect(auth.currentUser).to.eq(userCred.user); + + const user = userCred.user; + expect(user).to.equal(auth.currentUser); + expect(user.uid).to.be.a('string'); + + const authIdToken = await user.getIdToken(); + const firebaseServerAppSettings = { authIdToken }; + + const serverApp = initializeServerApp( + getAppConfig(), + firebaseServerAppSettings + ); + const serverAppAuth = getTestInstanceForServerApp(serverApp); + let numberServerLogins = 0; + onAuthStateChanged(serverAppAuth, serverAuthUser => { + if (serverAuthUser) { + numberServerLogins++; + expect(user.uid).to.be.equal(serverAuthUser.uid); + expect(serverAppAuth).to.not.be.null; + if (serverAppAuth) { + expect(serverAppAuth.currentUser).to.equal(serverAuthUser); + } + } + }); + + await new Promise(resolve => { + setTimeout(resolve, signInWaitDuration); + }); + + expect(serverAppAuth.currentUser).to.not.be.null; + if (serverAppAuth.currentUser) { + await serverAppAuth.currentUser.reload(); + } + expect(numberServerLogins).to.equal(1); + + await deleteApp(serverApp); + }); + + it('can update server based user profile', async () => { + if (isBrowser()) { + return; + } + const userCred = await signInAnonymously(auth); + expect(auth.currentUser).to.eq(userCred.user); + + const user = userCred.user; + expect(user).to.equal(auth.currentUser); + expect(user.uid).to.be.a('string'); + expect(user.displayName).to.be.null; + + const authIdToken = await user.getIdToken(); + const firebaseServerAppSettings = { authIdToken }; + + const serverApp = initializeServerApp( + getAppConfig(), + firebaseServerAppSettings + ); + const serverAppAuth = getTestInstanceForServerApp(serverApp); + let numberServerLogins = 0; + const newDisplayName = 'newName'; + onAuthStateChanged(serverAppAuth, serverAuthUser => { + if (serverAuthUser) { + numberServerLogins++; + expect(serverAppAuth).to.not.be.null; + if (serverAppAuth) { + expect(serverAppAuth.currentUser).to.equal(serverAuthUser); + } + expect(user.uid).to.be.equal(serverAuthUser.uid); + expect(user.displayName).to.be.null; + void updateProfile(serverAuthUser, { + displayName: newDisplayName + }); + } + }); + + await new Promise(resolve => { + setTimeout(resolve, signInWaitDuration); + }); + + expect(serverAppAuth.currentUser).to.not.be.null; + + if (serverAppAuth.currentUser) { + await serverAppAuth.currentUser.reload(); + } + + expect(numberServerLogins).to.equal(1); + expect(serverAppAuth).to.not.be.null; + if (serverAppAuth) { + expect(serverAppAuth.currentUser).to.not.be.null; + expect(serverAppAuth.currentUser?.displayName).to.not.be.null; + expect(serverAppAuth.currentUser?.displayName).to.equal(newDisplayName); + } + + await deleteApp(serverApp); + }); + + it('can sign out of main auth and still use server auth', async () => { + if (isBrowser()) { + return; + } + const userCred = await signInAnonymously(auth); + expect(auth.currentUser).to.eq(userCred.user); + + const user = userCred.user; + expect(user).to.equal(auth.currentUser); + expect(user.uid).to.be.a('string'); + expect(user.displayName).to.be.null; + + const authIdToken = await user.getIdToken(); + const firebaseServerAppSettings = { authIdToken }; + + const serverApp = initializeServerApp( + getAppConfig(), + firebaseServerAppSettings + ); + const serverAppAuth = getTestInstanceForServerApp(serverApp); + let numberServerLogins = 0; + onAuthStateChanged(serverAppAuth, serverAuthUser => { + if (serverAuthUser) { + numberServerLogins++; + expect(serverAppAuth).to.not.be.null; + expect(user.uid).to.be.equal(serverAuthUser.uid); + expect(user.displayName).to.be.null; + if (serverAppAuth) { + expect(serverAppAuth.currentUser).to.equal(serverAuthUser); + } + } + }); + + await signOut(auth); + await new Promise(resolve => { + setTimeout(resolve, signInWaitDuration); + }); + + expect(serverAppAuth.currentUser).to.not.be.null; + + if (serverAppAuth.currentUser) { + await serverAppAuth.currentUser.reload(); + } + + expect(numberServerLogins).to.equal(1); + expect(serverAppAuth).to.not.be.null; + if (serverAppAuth) { + expect(serverAppAuth.currentUser).to.not.be.null; + } + + await deleteApp(serverApp); + }); + + it('auth operations fail correctly on FirebaseServerApp instances', async () => { + if (isBrowser()) { + return; + } + const userCred = await signInAnonymously(auth); + expect(auth.currentUser).to.eq(userCred.user); + + const user = userCred.user; + expect(user).to.equal(auth.currentUser); + expect(user.uid).to.be.a('string'); + + const authIdToken = await user.getIdToken(); + const firebaseServerAppSettings = { authIdToken }; + + const serverApp = initializeServerApp( + getAppConfig(), + firebaseServerAppSettings + ); + + const serverAppAuth = getTestInstanceForServerApp(serverApp); + await new Promise(resolve => { + setTimeout(resolve, signInWaitDuration); + }); + + expect(serverAppAuth.currentUser).to.not.be.null; + const email = randomEmail(); + const password = 'password'; + + // Auth tests: + await expect( + createUserWithEmailAndPassword(serverAppAuth, email, password) + ).to.be.rejectedWith( + FirebaseError, + 'operation-not-supported-in-this-environment' + ); + await expect( + signInWithRedirect(serverAppAuth, new GoogleAuthProvider()) + ).to.be.rejectedWith( + FirebaseError, + 'operation-not-supported-in-this-environment' + ); + await expect(getRedirectResult(serverAppAuth)).to.be.rejectedWith( + FirebaseError, + 'operation-not-supported-in-this-environment' + ); + await expect(signInAnonymously(serverAppAuth)).to.be.rejectedWith( + FirebaseError, + 'operation-not-supported-in-this-environment' + ); + + const credential = EmailAuthProvider.credential(email, password); + await expect( + signInWithCredential(serverAppAuth, credential) + ).to.be.rejectedWith( + FirebaseError, + 'operation-not-supported-in-this-environment' + ); + + await expect( + signInWithCustomToken(serverAppAuth, 'custom token') + ).to.be.rejectedWith( + FirebaseError, + 'operation-not-supported-in-this-environment' + ); + await expect( + signInWithEmailAndPassword(serverAppAuth, email, password) + ).to.be.rejectedWith( + FirebaseError, + 'operation-not-supported-in-this-environment' + ); + await expect( + signInWithEmailLink(serverAppAuth, email, 'email link') + ).to.be.rejectedWith( + FirebaseError, + 'operation-not-supported-in-this-environment' + ); + await expect( + updateCurrentUser(serverAppAuth, serverAppAuth.currentUser) + ).to.be.rejectedWith( + FirebaseError, + 'operation-not-supported-in-this-environment' + ); + await expect( + updateCurrentUser(serverAppAuth, serverAppAuth.currentUser) + ).to.be.rejectedWith( + FirebaseError, + 'operation-not-supported-in-this-environment' + ); + await expect(signOut(serverAppAuth)).to.be.rejectedWith( + FirebaseError, + 'operation-not-supported-in-this-environment' + ); + + if (serverAppAuth.currentUser !== null) { + await expect( + reauthenticateWithCredential(serverAppAuth.currentUser, credential) + ).to.be.rejectedWith( + FirebaseError, + 'operation-not-supported-in-this-environment' + ); + + await expect(serverAppAuth.currentUser.delete()).to.be.rejectedWith( + FirebaseError, + 'operation-not-supported-in-this-environment' + ); + + await expect( + updateEmail(serverAppAuth.currentUser, email) + ).to.be.rejectedWith( + FirebaseError, + 'operation-not-supported-in-this-environment' + ); + } + + await deleteApp(serverApp); + }); +}); diff --git a/packages/auth/web-extension/package.json b/packages/auth/web-extension/package.json new file mode 100644 index 00000000000..1a46dcf1f90 --- /dev/null +++ b/packages/auth/web-extension/package.json @@ -0,0 +1,8 @@ +{ + "name": "@firebase/auth/web-extension", + "description": "A Chrome-Manifest-v3-specific build of the Firebase Auth JS SDK", + "main": "../dist/web-extension-cjs/index.js", + "browser": "../dist/web-extension-esm2017/index.js", + "module": "../dist/web-extension-esm2017/index.js", + "typings": "../dist/web-extension-esm2017/index.web-extension.d.ts" +} \ No newline at end of file diff --git a/packages/component/CHANGELOG.md b/packages/component/CHANGELOG.md index f0f702571bf..02b0bb97bb6 100644 --- a/packages/component/CHANGELOG.md +++ b/packages/component/CHANGELOG.md @@ -1,5 +1,21 @@ # @firebase/component +## 0.6.6 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/util@1.9.5 + +## 0.6.5 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + ## 0.6.4 ### Patch Changes diff --git a/packages/component/package.json b/packages/component/package.json index 055d6b81bc6..9227abf217c 100644 --- a/packages/component/package.json +++ b/packages/component/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/component", - "version": "0.6.4", + "version": "0.6.6", "description": "Firebase Component Platform", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -32,7 +32,7 @@ "test:node": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' nyc --reporter lcovonly -- mocha src/**/*.test.ts --config ../../config/mocharc.node.js" }, "dependencies": { - "@firebase/util": "1.9.3", + "@firebase/util": "1.9.5", "tslib": "^2.1.0" }, "license": "Apache-2.0", @@ -44,7 +44,7 @@ "repository": { "directory": "packages/component", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/database-compat/CHANGELOG.md b/packages/database-compat/CHANGELOG.md index 40f4868ed5b..ae3aab2ebec 100644 --- a/packages/database-compat/CHANGELOG.md +++ b/packages/database-compat/CHANGELOG.md @@ -1,5 +1,28 @@ # @firebase/database-compat +## 1.0.4 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/database-types@1.0.2 + - @firebase/component@0.6.6 + - @firebase/database@1.0.4 + - @firebase/logger@0.4.1 + - @firebase/util@1.9.5 + +## 1.0.3 + +### Patch Changes + +- Updated dependencies [[`046ac8a39`](https://github.com/firebase/firebase-js-sdk/commit/046ac8a39b483e127a4bbe11a5390a3e6018f2a7), [`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/database@1.0.3 + - @firebase/util@1.9.4 + - @firebase/component@0.6.5 + - @firebase/database-types@1.0.1 + ## 1.0.2 ### Patch Changes diff --git a/packages/database-compat/package.json b/packages/database-compat/package.json index f22066bc400..b691c521954 100644 --- a/packages/database-compat/package.json +++ b/packages/database-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/database-compat", - "version": "1.0.2", + "version": "1.0.4", "description": "The Realtime Database component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.js", @@ -50,21 +50,21 @@ "add-compat-overloads": "ts-node-script ../../scripts/build/create-overloads.ts -i ../database/dist/public.d.ts -o dist/database-compat/src/index.d.ts -a -r Database:types.FirebaseDatabase -r Query:types.Query -r DatabaseReference:types.Reference -r FirebaseApp:FirebaseAppCompat --moduleToEnhance @firebase/database" }, "dependencies": { - "@firebase/database": "1.0.2", - "@firebase/database-types": "1.0.0", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.3", - "@firebase/component": "0.6.4", + "@firebase/database": "1.0.4", + "@firebase/database-types": "1.0.2", + "@firebase/logger": "0.4.1", + "@firebase/util": "1.9.5", + "@firebase/component": "0.6.6", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.2.25", + "@firebase/app-compat": "0.2.32", "typescript": "4.7.4" }, "repository": { "directory": "packages/database-compat", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/database-types/CHANGELOG.md b/packages/database-types/CHANGELOG.md index dc3b3551af8..72f56760f01 100644 --- a/packages/database-types/CHANGELOG.md +++ b/packages/database-types/CHANGELOG.md @@ -1,5 +1,22 @@ # @firebase/database-types +## 1.0.2 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/app-types@0.9.1 + - @firebase/util@1.9.5 + +## 1.0.1 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + ## 1.0.0 ### Major Changes diff --git a/packages/database-types/package.json b/packages/database-types/package.json index 327648ccd2d..bfcff25343f 100644 --- a/packages/database-types/package.json +++ b/packages/database-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/database-types", - "version": "1.0.0", + "version": "1.0.2", "description": "@firebase/database Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -12,13 +12,13 @@ "index.d.ts" ], "dependencies": { - "@firebase/app-types": "0.9.0", - "@firebase/util": "1.9.3" + "@firebase/app-types": "0.9.1", + "@firebase/util": "1.9.5" }, "repository": { "directory": "packages/database-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/database/CHANGELOG.md b/packages/database/CHANGELOG.md index 03d1621390f..10333284ffe 100644 --- a/packages/database/CHANGELOG.md +++ b/packages/database/CHANGELOG.md @@ -1,5 +1,28 @@ # Unreleased +## 1.0.4 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/app-check-interop-types@0.3.1 + - @firebase/auth-interop-types@0.2.2 + - @firebase/component@0.6.6 + - @firebase/logger@0.4.1 + - @firebase/util@1.9.5 + +## 1.0.3 + +### Patch Changes + +- [`046ac8a39`](https://github.com/firebase/firebase-js-sdk/commit/046ac8a39b483e127a4bbe11a5390a3e6018f2a7) [#7973](https://github.com/firebase/firebase-js-sdk/pull/7973) (fixes [#7835](https://github.com/firebase/firebase-js-sdk/issues/7835)) - Fixed issue where queryConstraint.type was undefined + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/component@0.6.5 + ## 1.0.2 ### Patch Changes diff --git a/packages/database/package.json b/packages/database/package.json index 256e0c6e588..0c308cd0728 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/database", - "version": "1.0.2", + "version": "1.0.4", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -49,16 +49,16 @@ "license": "Apache-2.0", "peerDependencies": {}, "dependencies": { - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.3", - "@firebase/component": "0.6.4", - "@firebase/app-check-interop-types": "0.3.0", - "@firebase/auth-interop-types": "0.2.1", + "@firebase/logger": "0.4.1", + "@firebase/util": "1.9.5", + "@firebase/component": "0.6.6", + "@firebase/app-check-interop-types": "0.3.1", + "@firebase/auth-interop-types": "0.2.2", "faye-websocket": "0.11.4", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.9.25", + "@firebase/app": "0.10.2", "rollup": "2.79.1", "rollup-plugin-typescript2": "0.31.2", "typescript": "4.7.4" @@ -66,7 +66,7 @@ "repository": { "directory": "packages/database", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/database/src/api/Reference_impl.ts b/packages/database/src/api/Reference_impl.ts index 531c5d794da..7870bf93e53 100644 --- a/packages/database/src/api/Reference_impl.ts +++ b/packages/database/src/api/Reference_impl.ts @@ -1683,7 +1683,7 @@ export abstract class QueryConstraint { } class QueryEndAtConstraint extends QueryConstraint { - readonly type: 'endAt'; + readonly type = 'endAt'; constructor( private readonly _value: number | string | boolean | null, @@ -1748,7 +1748,7 @@ export function endAt( } class QueryEndBeforeConstraint extends QueryConstraint { - readonly type: 'endBefore'; + readonly type = 'endBefore'; constructor( private readonly _value: number | string | boolean | null, @@ -1809,7 +1809,7 @@ export function endBefore( } class QueryStartAtConstraint extends QueryConstraint { - readonly type: 'startAt'; + readonly type = 'startAt'; constructor( private readonly _value: number | string | boolean | null, @@ -1873,7 +1873,7 @@ export function startAt( } class QueryStartAfterConstraint extends QueryConstraint { - readonly type: 'startAfter'; + readonly type = 'startAfter'; constructor( private readonly _value: number | string | boolean | null, @@ -1933,7 +1933,7 @@ export function startAfter( } class QueryLimitToFirstConstraint extends QueryConstraint { - readonly type: 'limitToFirst'; + readonly type = 'limitToFirst'; constructor(private readonly _limit: number) { super(); @@ -1981,7 +1981,7 @@ export function limitToFirst(limit: number): QueryConstraint { } class QueryLimitToLastConstraint extends QueryConstraint { - readonly type: 'limitToLast'; + readonly type = 'limitToLast'; constructor(private readonly _limit: number) { super(); @@ -2030,7 +2030,7 @@ export function limitToLast(limit: number): QueryConstraint { } class QueryOrderByChildConstraint extends QueryConstraint { - readonly type: 'orderByChild'; + readonly type = 'orderByChild'; constructor(private readonly _path: string) { super(); @@ -2093,7 +2093,7 @@ export function orderByChild(path: string): QueryConstraint { } class QueryOrderByKeyConstraint extends QueryConstraint { - readonly type: 'orderByKey'; + readonly type = 'orderByKey'; _apply(query: QueryImpl): QueryImpl { validateNoPreviousOrderByCall(query, 'orderByKey'); @@ -2121,7 +2121,7 @@ export function orderByKey(): QueryConstraint { } class QueryOrderByPriorityConstraint extends QueryConstraint { - readonly type: 'orderByPriority'; + readonly type = 'orderByPriority'; _apply(query: QueryImpl): QueryImpl { validateNoPreviousOrderByCall(query, 'orderByPriority'); @@ -2149,7 +2149,7 @@ export function orderByPriority(): QueryConstraint { } class QueryOrderByValueConstraint extends QueryConstraint { - readonly type: 'orderByValue'; + readonly type = 'orderByValue'; _apply(query: QueryImpl): QueryImpl { validateNoPreviousOrderByCall(query, 'orderByValue'); @@ -2178,7 +2178,7 @@ export function orderByValue(): QueryConstraint { } class QueryEqualToValueConstraint extends QueryConstraint { - readonly type: 'equalTo'; + readonly type = 'equalTo'; constructor( private readonly _value: number | string | boolean | null, diff --git a/packages/database/test/queryconstraint.test.ts b/packages/database/test/queryconstraint.test.ts new file mode 100644 index 00000000000..964c9fdb4de --- /dev/null +++ b/packages/database/test/queryconstraint.test.ts @@ -0,0 +1,60 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'chai'; + +import { + endAt, + endBefore, + equalTo, + limitToFirst, + limitToLast, + orderByChild, + orderByKey, + orderByPriority, + orderByValue, + startAfter, + startAt +} from '../src'; + +import { createTestApp } from './exp/integration.test'; + +describe('Query Constraints', () => { + let defaultApp; + + beforeEach(() => { + defaultApp = createTestApp(); + }); + it('query constraint types are exposed', () => { + const queryConstraintTypes = [ + { qc: endAt(0), name: 'endAt' }, + { qc: endBefore(0), name: 'endBefore' }, + { qc: startAt(0), name: 'startAt' }, + { qc: startAfter(0), name: 'startAfter' }, + { qc: limitToFirst(1), name: 'limitToFirst' }, + { qc: limitToLast(1), name: 'limitToLast' }, + { qc: orderByChild('a'), name: 'orderByChild' }, + { qc: orderByKey(), name: 'orderByKey' }, + { qc: orderByPriority(), name: 'orderByPriority' }, + { qc: orderByValue(), name: 'orderByValue' }, + { qc: equalTo(''), name: 'equalTo' } + ]; + queryConstraintTypes.forEach(({ qc, name }) => { + expect(qc.type).to.equal(name); + }); + }); +}); diff --git a/packages/firebase/CHANGELOG.md b/packages/firebase/CHANGELOG.md index 1170e4f5e9f..ea04d82c2b4 100644 --- a/packages/firebase/CHANGELOG.md +++ b/packages/firebase/CHANGELOG.md @@ -1,5 +1,165 @@ # firebase +## 10.11.1 + +### Patch Changes + +- [`224419457`](https://github.com/firebase/firebase-js-sdk/commit/224419457c3fd2e5813166dbd7d6d9a03322143c) [#8145](https://github.com/firebase/firebase-js-sdk/pull/8145) - Prevent spurious "Backend didn't respond within 10 seconds" errors when network is indeed responding, just slowly. + +- [`84f9ff008`](https://github.com/firebase/firebase-js-sdk/commit/84f9ff0085993159c3513cb859852a5c79145b1b) [#8178](https://github.com/firebase/firebase-js-sdk/pull/8178) - Reduce code bundle size by 6.5 kB in applications that only use memory persistence (the default persistence mode). This bundle size regression was accidentally introduced in v10.7.2. + +- Updated dependencies [[`224419457`](https://github.com/firebase/firebase-js-sdk/commit/224419457c3fd2e5813166dbd7d6d9a03322143c), [`bd12e83cd`](https://github.com/firebase/firebase-js-sdk/commit/bd12e83cd1f0a10774dfb7e6ff7d4b0555a29a81), [`e1a7764cf`](https://github.com/firebase/firebase-js-sdk/commit/e1a7764cf36d246bb021d084e498604fe37e84aa), [`36b283f3f`](https://github.com/firebase/firebase-js-sdk/commit/36b283f3fc317d0fa7dde47e1048d2ee3690a9a0), [`84f9ff008`](https://github.com/firebase/firebase-js-sdk/commit/84f9ff0085993159c3513cb859852a5c79145b1b), [`55fef6d62`](https://github.com/firebase/firebase-js-sdk/commit/55fef6d627791f4704194c3913ebeb339a564906)]: + - @firebase/app@0.10.2 + - @firebase/firestore@4.6.1 + - @firebase/auth@1.7.2 + - @firebase/auth-compat@0.5.7 + - @firebase/app-compat@0.2.32 + - @firebase/firestore-compat@0.3.30 + +## 10.11.0 + +### Minor Changes + +- [`666dddae0`](https://github.com/firebase/firebase-js-sdk/commit/666dddae0b050204c59f70e74010fd92a6b54187) [#7999](https://github.com/firebase/firebase-js-sdk/pull/7999) - Enable queries with range & inequality filters on multiple fields. + +### Patch Changes + +- Updated dependencies [[`fe09d8338`](https://github.com/firebase/firebase-js-sdk/commit/fe09d8338d7d5f7a82d8cd73cf825adbe5551975), [`f1a57d00d`](https://github.com/firebase/firebase-js-sdk/commit/f1a57d00d05c202ca676f22ed89ad636e8a708c6), [`c6ecac8ac`](https://github.com/firebase/firebase-js-sdk/commit/c6ecac8ac7110622d178d9450446318a4d0c474e), [`a6fa54417`](https://github.com/firebase/firebase-js-sdk/commit/a6fa544173aeeee9d4f35e1ebd36fe2c2f461d19), [`666dddae0`](https://github.com/firebase/firebase-js-sdk/commit/666dddae0b050204c59f70e74010fd92a6b54187), [`6d31930b3`](https://github.com/firebase/firebase-js-sdk/commit/6d31930b3abe1588ae81a5c14b59cd386fddc718), [`ad8d5470d`](https://github.com/firebase/firebase-js-sdk/commit/ad8d5470dad9b9ec1bcd939609da4a1c439c8414)]: + - @firebase/auth-compat@0.5.6 + - @firebase/firestore@4.6.0 + - @firebase/functions@0.11.4 + - @firebase/storage@0.12.4 + - @firebase/auth@1.7.1 + - @firebase/messaging@0.12.8 + - @firebase/app@0.10.1 + - @firebase/storage-compat@0.3.7 + - @firebase/firestore-compat@0.3.29 + - @firebase/functions-compat@0.3.10 + - @firebase/messaging-compat@0.2.8 + - @firebase/app-compat@0.2.31 + +## 10.10.0 + +### Minor Changes + +- [`ed84efe50`](https://github.com/firebase/firebase-js-sdk/commit/ed84efe50bfc365da8ebfacdd2b17b5cc2a9e596) [#8005](https://github.com/firebase/firebase-js-sdk/pull/8005) - Added the new `FirebaseServerApp` interface to bridge state + data between client and server runtime environments. This interface extends `FirebaseApp`. + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`ed84efe50`](https://github.com/firebase/firebase-js-sdk/commit/ed84efe50bfc365da8ebfacdd2b17b5cc2a9e596), [`9ca1a4e4f`](https://github.com/firebase/firebase-js-sdk/commit/9ca1a4e4f9f13d56cde93cab6d83a8bc54f83539), [`c8a2568dd`](https://github.com/firebase/firebase-js-sdk/commit/c8a2568ddd2acd9162a99bce9ff4203fe8d6e0da), [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/auth@1.7.0 + - @firebase/app@0.10.0 + - @firebase/installations-compat@0.2.6 + - @firebase/remote-config-compat@0.2.6 + - @firebase/performance-compat@0.2.6 + - @firebase/analytics-compat@0.2.8 + - @firebase/app-check-compat@0.3.10 + - @firebase/firestore-compat@0.3.28 + - @firebase/functions-compat@0.3.9 + - @firebase/messaging-compat@0.2.7 + - @firebase/database-compat@1.0.4 + - @firebase/storage-compat@0.3.6 + - @firebase/installations@0.6.6 + - @firebase/remote-config@0.4.6 + - @firebase/auth-compat@0.5.5 + - @firebase/performance@0.6.6 + - @firebase/app-compat@0.2.30 + - @firebase/analytics@0.10.2 + - @firebase/app-check@0.8.3 + - @firebase/app-types@0.9.1 + - @firebase/firestore@4.5.1 + - @firebase/functions@0.11.3 + - @firebase/messaging@0.12.7 + - @firebase/database@1.0.4 + - @firebase/storage@0.12.3 + - @firebase/util@1.9.5 + +## 10.9.0 + +### Minor Changes + +- [`ce88e71e7`](https://github.com/firebase/firebase-js-sdk/commit/ce88e71e738ac7bb2cd5d63e4e314e2de82f72ef) [#7982](https://github.com/firebase/firebase-js-sdk/pull/7982) - Enable snapshot listener option to retrieve data from local cache only. + +### Patch Changes + +- [`2b22838aa`](https://github.com/firebase/firebase-js-sdk/commit/2b22838aa2c7ccec480b26c9702bbb98a0778250) [#8059](https://github.com/firebase/firebase-js-sdk/pull/8059) - Fix glob pattern to work with Node 20 and its NPM version. + +- Updated dependencies [[`6d487d7de`](https://github.com/firebase/firebase-js-sdk/commit/6d487d7dee631498bed1aeccbb45d8f14ae911d1), [`ce88e71e7`](https://github.com/firebase/firebase-js-sdk/commit/ce88e71e738ac7bb2cd5d63e4e314e2de82f72ef), [`245dd26e1`](https://github.com/firebase/firebase-js-sdk/commit/245dd26e19b6c16aca7e1b7e597ed5784c2984ba)]: + - @firebase/auth@1.6.2 + - @firebase/app@0.9.29 + - @firebase/firestore@4.5.0 + - @firebase/auth-compat@0.5.4 + - @firebase/app-compat@0.2.29 + - @firebase/firestore-compat@0.3.27 + +## 10.8.1 + +### Patch Changes + +- Updated dependencies [[`f3cec28df`](https://github.com/firebase/firebase-js-sdk/commit/f3cec28dfbdfc7f19c8218cf9d26956235d03fb0)]: + - @firebase/app@0.9.28 + - @firebase/auth-compat@0.5.3 + - @firebase/firestore@4.4.3 + - @firebase/functions@0.11.2 + - @firebase/storage@0.12.2 + - @firebase/auth@1.6.1 + - @firebase/app-compat@0.2.28 + - @firebase/storage-compat@0.3.5 + - @firebase/firestore-compat@0.3.26 + - @firebase/functions-compat@0.3.8 + +## 10.8.0 + +### Minor Changes + +- [`2f7ad0ac4`](https://github.com/firebase/firebase-js-sdk/commit/2f7ad0ac43f5d085604324f6dc3921d9420bfccd) [#8001](https://github.com/firebase/firebase-js-sdk/pull/8001) - Added a Web-Extension package that strips the external JS loading for developers to use when building Chrome Extension app. + +### Patch Changes + +- Updated dependencies [[`046ac8a39`](https://github.com/firebase/firebase-js-sdk/commit/046ac8a39b483e127a4bbe11a5390a3e6018f2a7), [`3f8cbcd18`](https://github.com/firebase/firebase-js-sdk/commit/3f8cbcd18f47fcae8c0d8060fd8c245c025784c0), [`bf59c0aed`](https://github.com/firebase/firebase-js-sdk/commit/bf59c0aedefabae9bff4d777e1591fe496259293), [`2f7ad0ac4`](https://github.com/firebase/firebase-js-sdk/commit/2f7ad0ac43f5d085604324f6dc3921d9420bfccd), [`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/database@1.0.3 + - @firebase/app@0.9.27 + - @firebase/analytics@0.10.1 + - @firebase/auth@1.6.0 + - @firebase/util@1.9.4 + - @firebase/database-compat@1.0.3 + - @firebase/app-check@0.8.2 + - @firebase/app-compat@0.2.27 + - @firebase/firestore@4.4.2 + - @firebase/functions@0.11.1 + - @firebase/installations@0.6.5 + - @firebase/messaging@0.12.6 + - @firebase/performance@0.6.5 + - @firebase/remote-config@0.4.5 + - @firebase/storage@0.12.1 + - @firebase/analytics-compat@0.2.7 + - @firebase/auth-compat@0.5.2 + - @firebase/app-check-compat@0.3.9 + - @firebase/firestore-compat@0.3.25 + - @firebase/functions-compat@0.3.7 + - @firebase/installations-compat@0.2.5 + - @firebase/messaging-compat@0.2.6 + - @firebase/performance-compat@0.2.5 + - @firebase/remote-config-compat@0.2.5 + - @firebase/storage-compat@0.3.4 + +## 10.7.2 + +### Patch Changes + +- [`d7ace80d4`](https://github.com/firebase/firebase-js-sdk/commit/d7ace80d44ec870c3117cfed04ae6a1988c03c8e) [#7929](https://github.com/firebase/firebase-js-sdk/pull/7929) - Tweak the automatic index creation parameters to use more optimal values for the platform/browser detected at runtime. + +- [`a476c4692`](https://github.com/firebase/firebase-js-sdk/commit/a476c4692dd1c1affbbd3139290dac54257dc5d2) [#7861](https://github.com/firebase/firebase-js-sdk/pull/7861) (fixes [#7706](https://github.com/firebase/firebase-js-sdk/issues/7706)) - Update the `isEqual` function for arrayUnion, arrayRemove and increment. + +- Updated dependencies [[`7481098d4`](https://github.com/firebase/firebase-js-sdk/commit/7481098d47d14acce901fa4c065ceff0cbf07d3d), [`16728cf3c`](https://github.com/firebase/firebase-js-sdk/commit/16728cf3c6b4e358dc3d12f80623e5966f104c31), [`f4788453e`](https://github.com/firebase/firebase-js-sdk/commit/f4788453eb989d30495ddc7a3832e13c6d11b34e), [`d7ace80d4`](https://github.com/firebase/firebase-js-sdk/commit/d7ace80d44ec870c3117cfed04ae6a1988c03c8e), [`a476c4692`](https://github.com/firebase/firebase-js-sdk/commit/a476c4692dd1c1affbbd3139290dac54257dc5d2)]: + - @firebase/firestore@4.4.1 + - @firebase/app@0.9.26 + - @firebase/firestore-compat@0.3.24 + - @firebase/app-compat@0.2.26 + ## 10.7.1 ### Patch Changes diff --git a/packages/firebase/auth/web-extension/index.ts b/packages/firebase/auth/web-extension/index.ts new file mode 100644 index 00000000000..52c9bee35eb --- /dev/null +++ b/packages/firebase/auth/web-extension/index.ts @@ -0,0 +1,18 @@ +/** + * @license + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from '@firebase/auth/web-extension'; diff --git a/packages/firebase/auth/web-extension/package.json b/packages/firebase/auth/web-extension/package.json new file mode 100644 index 00000000000..6ff8f79531e --- /dev/null +++ b/packages/firebase/auth/web-extension/package.json @@ -0,0 +1,7 @@ +{ + "name": "firebase/auth/web-extension", + "main": "dist/index.cjs.js", + "browser": "dist/esm/index.esm.js", + "module": "dist/esm/index.esm.js", + "typings": "dist/auth/web-extension/index.d.ts" +} \ No newline at end of file diff --git a/packages/firebase/compat/index.d.ts b/packages/firebase/compat/index.d.ts index 3b58814f73b..4b2bc1e8a47 100644 --- a/packages/firebase/compat/index.d.ts +++ b/packages/firebase/compat/index.d.ts @@ -4959,7 +4959,7 @@ declare namespace firebase.analytics { * automatically associates this logged event with this Firebase web * app instance on this device. * See - * {@link https://developers.google.com/analytics/devguides/collection/ga4/page-view + * {@link https://developers.google.com/analytics/devguides/collection/ga4/views * | Page views}. */ logEvent( diff --git a/packages/firebase/package.json b/packages/firebase/package.json index cca5faf64c3..c1aa6405871 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -1,6 +1,6 @@ { "name": "firebase", - "version": "10.7.1", + "version": "10.11.1", "description": "Firebase JavaScript library for web and Node.js", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -16,7 +16,7 @@ "remote-config" ], "files": [ - "**/dist/", + "**/dist/**/*", "**/package.json", "/firebase*.js", "/firebase*.map", @@ -83,6 +83,18 @@ }, "default": "./auth/cordova/dist/esm/index.esm.js" }, + "./auth/web-extension": { + "types": "./auth/web-extension/dist/auth/web-extension/index.d.ts", + "node": { + "require": "./auth/web-extension/dist/index.cjs.js", + "import": "./auth/web-extension/dist/index.mjs" + }, + "browser": { + "require": "./auth/web-extension/dist/index.cjs.js", + "import": "./auth/web-extension/dist/esm/index.esm.js" + }, + "default": "./auth/web-extension/dist/esm/index.esm.js" + }, "./database": { "types": "./database/dist/database/index.d.ts", "node": { @@ -203,6 +215,18 @@ }, "default": "./storage/dist/esm/index.esm.js" }, + "./vertexai-preview": { + "types": "./vertexai-preview/dist/vertexai-preview/index.d.ts", + "node": { + "require": "./vertexai-preview/dist/index.cjs.js", + "import": "./vertexai-preview/dist/index.mjs" + }, + "browser": { + "require": "./vertexai-preview/dist/index.cjs.js", + "import": "./vertexai-preview/dist/esm/index.esm.js" + }, + "default": "./vertexai-preview/dist/esm/index.esm.js" + }, "./compat/analytics": { "types": "./compat/analytics/dist/compat/analytics/index.d.ts", "node": { @@ -351,7 +375,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "scripts": { "build": "rollup -c && gulp cdn-type-module-path && yarn build:compat", @@ -362,32 +386,33 @@ "test:ci": "echo 'No test suite for firebase wrapper'" }, "dependencies": { - "@firebase/app": "0.9.25", - "@firebase/app-compat": "0.2.25", - "@firebase/app-types": "0.9.0", - "@firebase/auth": "1.5.1", - "@firebase/auth-compat": "0.5.1", - "@firebase/database": "1.0.2", - "@firebase/database-compat": "1.0.2", - "@firebase/firestore": "4.4.0", - "@firebase/firestore-compat": "0.3.23", - "@firebase/functions": "0.11.0", - "@firebase/functions-compat": "0.3.6", - "@firebase/installations": "0.6.4", - "@firebase/installations-compat": "0.2.4", - "@firebase/messaging": "0.12.5", - "@firebase/messaging-compat": "0.2.5", - "@firebase/storage": "0.12.0", - "@firebase/storage-compat": "0.3.3", - "@firebase/performance": "0.6.4", - "@firebase/performance-compat": "0.2.4", - "@firebase/remote-config": "0.4.4", - "@firebase/remote-config-compat": "0.2.4", - "@firebase/analytics": "0.10.0", - "@firebase/analytics-compat": "0.2.6", - "@firebase/app-check": "0.8.1", - "@firebase/app-check-compat": "0.3.8", - "@firebase/util": "1.9.3" + "@firebase/app": "0.10.2", + "@firebase/app-compat": "0.2.32", + "@firebase/app-types": "0.9.1", + "@firebase/auth": "1.7.2", + "@firebase/auth-compat": "0.5.7", + "@firebase/database": "1.0.4", + "@firebase/database-compat": "1.0.4", + "@firebase/firestore": "4.6.1", + "@firebase/firestore-compat": "0.3.30", + "@firebase/functions": "0.11.4", + "@firebase/functions-compat": "0.3.10", + "@firebase/installations": "0.6.6", + "@firebase/installations-compat": "0.2.6", + "@firebase/messaging": "0.12.8", + "@firebase/messaging-compat": "0.2.8", + "@firebase/storage": "0.12.4", + "@firebase/storage-compat": "0.3.7", + "@firebase/performance": "0.6.6", + "@firebase/performance-compat": "0.2.6", + "@firebase/remote-config": "0.4.6", + "@firebase/remote-config-compat": "0.2.6", + "@firebase/analytics": "0.10.2", + "@firebase/analytics-compat": "0.2.8", + "@firebase/app-check": "0.8.3", + "@firebase/app-check-compat": "0.3.10", + "@firebase/util": "1.9.5", + "@firebase/vertexai-preview": "0.0.0" }, "devDependencies": { "rollup": "2.79.1", @@ -409,6 +434,7 @@ "app-check", "auth", "auth/cordova", + "auth/web-extension", "functions", "firestore", "firestore/lite", @@ -418,7 +444,8 @@ "remote-config", "messaging", "messaging/sw", - "database" + "database", + "vertexai-preview" ], "typings": "empty.d.ts" } diff --git a/packages/webchannel-wrapper/externs/module.js b/packages/firebase/vertexai-preview/index.ts similarity index 88% rename from packages/webchannel-wrapper/externs/module.js rename to packages/firebase/vertexai-preview/index.ts index 37e045fc23a..20d7697c1e0 100644 --- a/packages/webchannel-wrapper/externs/module.js +++ b/packages/firebase/vertexai-preview/index.ts @@ -1,6 +1,6 @@ /** * @license - * Copyright 2020 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,5 +15,4 @@ * limitations under the License. */ -/** @type {!Object} */ -const module = {}; +export * from '@firebase/vertexai-preview'; diff --git a/packages/firebase/vertexai-preview/package.json b/packages/firebase/vertexai-preview/package.json new file mode 100644 index 00000000000..9dfe8f0c3fa --- /dev/null +++ b/packages/firebase/vertexai-preview/package.json @@ -0,0 +1,7 @@ +{ + "name": "firebase/vertexai-preview", + "main": "dist/index.cjs.js", + "browser": "dist/esm/index.esm.js", + "module": "dist/esm/index.esm.js", + "typings": "dist/vertexai-preview/index.d.ts" +} \ No newline at end of file diff --git a/packages/firestore-compat/CHANGELOG.md b/packages/firestore-compat/CHANGELOG.md index e5d259d4978..d00ebe9ac42 100644 --- a/packages/firestore-compat/CHANGELOG.md +++ b/packages/firestore-compat/CHANGELOG.md @@ -1,5 +1,61 @@ # @firebase/firestore-compat +## 0.3.30 + +### Patch Changes + +- Updated dependencies [[`224419457`](https://github.com/firebase/firebase-js-sdk/commit/224419457c3fd2e5813166dbd7d6d9a03322143c), [`bd12e83cd`](https://github.com/firebase/firebase-js-sdk/commit/bd12e83cd1f0a10774dfb7e6ff7d4b0555a29a81), [`e1a7764cf`](https://github.com/firebase/firebase-js-sdk/commit/e1a7764cf36d246bb021d084e498604fe37e84aa), [`84f9ff008`](https://github.com/firebase/firebase-js-sdk/commit/84f9ff0085993159c3513cb859852a5c79145b1b)]: + - @firebase/firestore@4.6.1 + +## 0.3.29 + +### Patch Changes + +- Updated dependencies [[`fe09d8338`](https://github.com/firebase/firebase-js-sdk/commit/fe09d8338d7d5f7a82d8cd73cf825adbe5551975), [`c6ecac8ac`](https://github.com/firebase/firebase-js-sdk/commit/c6ecac8ac7110622d178d9450446318a4d0c474e), [`a6fa54417`](https://github.com/firebase/firebase-js-sdk/commit/a6fa544173aeeee9d4f35e1ebd36fe2c2f461d19), [`666dddae0`](https://github.com/firebase/firebase-js-sdk/commit/666dddae0b050204c59f70e74010fd92a6b54187), [`ad8d5470d`](https://github.com/firebase/firebase-js-sdk/commit/ad8d5470dad9b9ec1bcd939609da4a1c439c8414)]: + - @firebase/firestore@4.6.0 + +## 0.3.28 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/firestore-types@3.0.1 + - @firebase/component@0.6.6 + - @firebase/firestore@4.5.1 + - @firebase/util@1.9.5 + +## 0.3.27 + +### Patch Changes + +- Updated dependencies [[`ce88e71e7`](https://github.com/firebase/firebase-js-sdk/commit/ce88e71e738ac7bb2cd5d63e4e314e2de82f72ef)]: + - @firebase/firestore@4.5.0 + +## 0.3.26 + +### Patch Changes + +- Updated dependencies [[`f3cec28df`](https://github.com/firebase/firebase-js-sdk/commit/f3cec28dfbdfc7f19c8218cf9d26956235d03fb0)]: + - @firebase/firestore@4.4.3 + +## 0.3.25 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/firestore@4.4.2 + - @firebase/component@0.6.5 + +## 0.3.24 + +### Patch Changes + +- Updated dependencies [[`7481098d4`](https://github.com/firebase/firebase-js-sdk/commit/7481098d47d14acce901fa4c065ceff0cbf07d3d), [`f4788453e`](https://github.com/firebase/firebase-js-sdk/commit/f4788453eb989d30495ddc7a3832e13c6d11b34e), [`d7ace80d4`](https://github.com/firebase/firebase-js-sdk/commit/d7ace80d44ec870c3117cfed04ae6a1988c03c8e), [`a476c4692`](https://github.com/firebase/firebase-js-sdk/commit/a476c4692dd1c1affbbd3139290dac54257dc5d2)]: + - @firebase/firestore@4.4.1 + ## 0.3.23 ### Patch Changes diff --git a/packages/firestore-compat/package.json b/packages/firestore-compat/package.json index 4636e12560b..0077798d106 100644 --- a/packages/firestore-compat/package.json +++ b/packages/firestore-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore-compat", - "version": "0.3.23", + "version": "0.3.30", "description": "The Cloud Firestore component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -47,14 +47,14 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/component": "0.6.4", - "@firebase/firestore": "4.4.0", - "@firebase/util": "1.9.3", - "@firebase/firestore-types": "3.0.0", + "@firebase/component": "0.6.6", + "@firebase/firestore": "4.6.1", + "@firebase/util": "1.9.5", + "@firebase/firestore-types": "3.0.1", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.2.25", + "@firebase/app-compat": "0.2.32", "@types/eslint": "7.29.0", "rollup": "2.79.1", "rollup-plugin-sourcemaps": "0.6.3", @@ -69,7 +69,7 @@ "repository": { "directory": "packages/firestore-compat", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/firestore-types/CHANGELOG.md b/packages/firestore-types/CHANGELOG.md index fe8e9da15ae..8949674fefb 100644 --- a/packages/firestore-types/CHANGELOG.md +++ b/packages/firestore-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/firestore-types +## 3.0.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 3.0.0 ### Major Changes diff --git a/packages/firestore-types/package.json b/packages/firestore-types/package.json index 7528c7c9a6d..4978f23a115 100644 --- a/packages/firestore-types/package.json +++ b/packages/firestore-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore-types", - "version": "3.0.0", + "version": "3.0.1", "description": "@firebase/firestore Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -18,7 +18,7 @@ "repository": { "directory": "packages/firestore-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/firestore/CHANGELOG.md b/packages/firestore/CHANGELOG.md index 3df00bbf5f8..27b7774c721 100644 --- a/packages/firestore/CHANGELOG.md +++ b/packages/firestore/CHANGELOG.md @@ -1,5 +1,77 @@ # @firebase/firestore +## 4.6.1 + +### Patch Changes + +- [`224419457`](https://github.com/firebase/firebase-js-sdk/commit/224419457c3fd2e5813166dbd7d6d9a03322143c) [#8145](https://github.com/firebase/firebase-js-sdk/pull/8145) - Prevent spurious "Backend didn't respond within 10 seconds" errors when network is indeed responding, just slowly. + +- [`bd12e83cd`](https://github.com/firebase/firebase-js-sdk/commit/bd12e83cd1f0a10774dfb7e6ff7d4b0555a29a81) [#8150](https://github.com/firebase/firebase-js-sdk/pull/8150) - Updated protobufjs transitive dependency in Firetore. + +- [`e1a7764cf`](https://github.com/firebase/firebase-js-sdk/commit/e1a7764cf36d246bb021d084e498604fe37e84aa) [#8197](https://github.com/firebase/firebase-js-sdk/pull/8197) - Go back using xmlhttprequest for bidi-streams, as fetch streams seem to be having connection issue. + +- [`84f9ff008`](https://github.com/firebase/firebase-js-sdk/commit/84f9ff0085993159c3513cb859852a5c79145b1b) [#8178](https://github.com/firebase/firebase-js-sdk/pull/8178) - Reduce code bundle size by 6.5 kB in applications that only use memory persistence (the default persistence mode). This bundle size regression was accidentally introduced in v10.7.2. + +## 4.6.0 + +### Minor Changes + +- [`666dddae0`](https://github.com/firebase/firebase-js-sdk/commit/666dddae0b050204c59f70e74010fd92a6b54187) [#7999](https://github.com/firebase/firebase-js-sdk/pull/7999) - Enable queries with range & inequality filters on multiple fields. + +### Patch Changes + +- [`fe09d8338`](https://github.com/firebase/firebase-js-sdk/commit/fe09d8338d7d5f7a82d8cd73cf825adbe5551975) [#8138](https://github.com/firebase/firebase-js-sdk/pull/8138) (fixes [#8132](https://github.com/firebase/firebase-js-sdk/issues/8132)) - Update undici version to 5.28.4 due to CVE-2024-30260. + +- [`c6ecac8ac`](https://github.com/firebase/firebase-js-sdk/commit/c6ecac8ac7110622d178d9450446318a4d0c474e) [#8090](https://github.com/firebase/firebase-js-sdk/pull/8090) (fixes [#8031](https://github.com/firebase/firebase-js-sdk/issues/8031)) - Fixed the CSI issue where indexing on timestamp fields leads to incorrect query results. + +- [`a6fa54417`](https://github.com/firebase/firebase-js-sdk/commit/a6fa544173aeeee9d4f35e1ebd36fe2c2f461d19) [#8142](https://github.com/firebase/firebase-js-sdk/pull/8142) - Fix internal assertion due to Buffer value not evaluating to instanceof Uint8Array, encountered when testing with jsdom. + +- [`ad8d5470d`](https://github.com/firebase/firebase-js-sdk/commit/ad8d5470dad9b9ec1bcd939609da4a1c439c8414) [#8134](https://github.com/firebase/firebase-js-sdk/pull/8134) - Updated dependencies. See GitHub PR #8098. + +## 4.5.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/webchannel-wrapper@0.10.6 + - @firebase/component@0.6.6 + - @firebase/logger@0.4.1 + - @firebase/util@1.9.5 + +## 4.5.0 + +### Minor Changes + +- [`ce88e71e7`](https://github.com/firebase/firebase-js-sdk/commit/ce88e71e738ac7bb2cd5d63e4e314e2de82f72ef) [#7982](https://github.com/firebase/firebase-js-sdk/pull/7982) - Enable snapshot listener option to retrieve data from local cache only. + +## 4.4.3 + +### Patch Changes + +- [`f3cec28df`](https://github.com/firebase/firebase-js-sdk/commit/f3cec28dfbdfc7f19c8218cf9d26956235d03fb0) [#8044](https://github.com/firebase/firebase-js-sdk/pull/8044) (fixes [#8038](https://github.com/firebase/firebase-js-sdk/issues/8038)) - Bump undici version to 5.28.3 due to security issue. + +## 4.4.2 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/component@0.6.5 + +## 4.4.1 + +### Patch Changes + +- [`7481098d4`](https://github.com/firebase/firebase-js-sdk/commit/7481098d47d14acce901fa4c065ceff0cbf07d3d) [#7847](https://github.com/firebase/firebase-js-sdk/pull/7847) (fixes [#7747](https://github.com/firebase/firebase-js-sdk/issues/7747)) - Fixed leak of grpc-js resources on terminate. + +- [`f4788453e`](https://github.com/firebase/firebase-js-sdk/commit/f4788453eb989d30495ddc7a3832e13c6d11b34e) [#7402](https://github.com/firebase/firebase-js-sdk/pull/7402) - Support special characters in query paths sent to `getCountFromServer(...)`, `getCount(...)` (lite API), and `getDocs(...)` (lite API). + +- [`d7ace80d4`](https://github.com/firebase/firebase-js-sdk/commit/d7ace80d44ec870c3117cfed04ae6a1988c03c8e) [#7929](https://github.com/firebase/firebase-js-sdk/pull/7929) - Tweak the automatic index creation parameters to use more optimal values for the platform/browser detected at runtime. + +- [`a476c4692`](https://github.com/firebase/firebase-js-sdk/commit/a476c4692dd1c1affbbd3139290dac54257dc5d2) [#7861](https://github.com/firebase/firebase-js-sdk/pull/7861) (fixes [#7706](https://github.com/firebase/firebase-js-sdk/issues/7706)) - Update the `isEqual` function for arrayUnion, arrayRemove and increment. + ## 4.4.0 ### Minor Changes diff --git a/packages/firestore/externs.json b/packages/firestore/externs.json index a1746227316..f7fbbabeb14 100644 --- a/packages/firestore/externs.json +++ b/packages/firestore/externs.json @@ -24,7 +24,8 @@ "packages/component/dist/src/provider.d.ts", "packages/component/dist/src/component_container.d.ts", "packages/logger/dist/src/logger.d.ts", - "packages/webchannel-wrapper/src/index.d.ts", + "packages/webchannel-wrapper/dist/bloom-blob/bloom_blob_types.d.ts", + "packages/webchannel-wrapper/dist/webchannel-blob/webchannel_blob_types.d.ts", "packages/util/dist/src/crypt.d.ts", "packages/util/dist/src/defaults.d.ts", "packages/util/dist/src/emulator.d.ts", diff --git a/packages/firestore/firestore_composite_index_config.tf b/packages/firestore/firestore_composite_index_config.tf index 217dbb70294..495c6ef1467 100644 --- a/packages/firestore/firestore_composite_index_config.tf +++ b/packages/firestore/firestore_composite_index_config.tf @@ -115,6 +115,36 @@ locals { }, ] index9 = [ + { + field_path = "testId" + order = "ASCENDING" + }, + { + field_path = "a" + order = "ASCENDING" + }, + + { + field_path = "b" + order = "ASCENDING" + }, + ] + index10 = [ + { + field_path = "testId" + order = "ASCENDING" + }, + { + field_path = "b" + order = "DESCENDING" + }, + + { + field_path = "a" + order = "DESCENDING" + }, + ] + index11 = [ { field_path = "testId" order = "ASCENDING" @@ -128,7 +158,7 @@ locals { order = "ASCENDING" }, ] - index10 = [ + index12 = [ { field_path = "testId" order = "ASCENDING" @@ -146,7 +176,7 @@ locals { order = "ASCENDING" }, ] - index11 = [ + index13 = [ { field_path = "rating" array_config = "CONTAINS" @@ -164,5 +194,218 @@ locals { order = "ASCENDING" }, ] + index14 = [ + { + field_path = "testId" + order = "ASCENDING" + }, + { + field_path = "key" + order = "ASCENDING" + }, + { + field_path = "sort" + order = "ASCENDING" + } + ] + index15 = [ + { + field_path = "testId" + order = "ASCENDING" + }, + { + field_path = "key" + order = "ASCENDING" + }, + { + field_path = "sort" + order = "ASCENDING" + }, + { + field_path = "v" + order = "ASCENDING" + } + ] + index16 = [ + { + field_path = "testId" + order = "ASCENDING" + }, + { + field_path = "v" + order = "DESCENDING" + }, + { + field_path = "key" + order = "DESCENDING" + }, + { + field_path = "sort" + order = "DESCENDING" + }, + ] + index17 = [ + { + field_path = "v" + array_config = "CONTAINS" + }, + { + field_path = "testId" + order = "ASCENDING" + }, + { + field_path = "key" + order = "ASCENDING" + }, + { + field_path = "sort" + order = "ASCENDING" + }, + ] + index18 = [ + { + field_path = "key" + order = "ASCENDING" + }, + { + field_path = "testId" + order = "ASCENDING" + }, + + { + field_path = "sort" + order = "DESCENDING" + }, + { + field_path = "v" + order = "ASCENDING" + }, + ] + index19 = [ + { + field_path = "testId" + order = "ASCENDING" + }, + + { + field_path = "sort" + order = "DESCENDING" + }, + { + field_path = "key" + order = "ASCENDING" + }, + { + field_path = "v" + order = "ASCENDING" + }, + ] + index20 = [ + { + field_path = "testId" + order = "ASCENDING" + }, + { + field_path = "v" + order = "ASCENDING" + }, + + { + field_path = "sort" + order = "ASCENDING" + }, + { + field_path = "key" + order = "ASCENDING" + }, + + ] + index21 = [ + { + field_path = "testId" + order = "ASCENDING" + }, + { + field_path = "sort" + order = "DESCENDING" + }, + { + field_path = "key" + order = "DESCENDING" + }, + + ] + index22 = [ + { + field_path = "testId" + order = "ASCENDING" + }, + { + field_path = "v" + order = "DESCENDING" + }, + { + field_path = "sort" + order = "ASCENDING" + }, + { + field_path = "key" + order = "ASCENDING" + }, + ] + index23 = [ + { + field_path = "testId" + order = "ASCENDING" + }, + { + field_path = "name" + order = "ASCENDING" + }, + { + field_path = "metadata.createdAt" + order = "ASCENDING" + }, + ] + index24 = [ + { + field_path = "testId" + order = "ASCENDING" + }, + { + field_path = "name" + order = "DESCENDING" + }, + { + field_path = "field" + order = "DESCENDING" + }, + { + field_path = "`field.dot`" + order = "DESCENDING" + }, + { + field_path = "`field\\\\slash`" + order = "DESCENDING" + }, + ], + index25 = [ + { + field_path = "testId" + order = "ASCENDING" + }, + { + field_path = "v" + order = "ASCENDING" + }, + { + field_path = "key" + order = "ASCENDING" + }, + { + field_path = "sort" + order = "ASCENDING" + }, + ] } } diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 5a9595d9d26..36f55ee5165 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/firestore", - "version": "4.4.0", + "version": "4.6.1", "engines": { "node": ">=10.10.0" }, @@ -96,44 +96,44 @@ "lite/package.json" ], "dependencies": { - "@firebase/component": "0.6.4", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.3", - "@firebase/webchannel-wrapper": "0.10.5", + "@firebase/component": "0.6.6", + "@firebase/logger": "0.4.1", + "@firebase/util": "1.9.5", + "@firebase/webchannel-wrapper": "0.10.6", "@grpc/grpc-js": "~1.9.0", "@grpc/proto-loader": "^0.7.8", - "undici": "5.26.5", + "undici": "5.28.4", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.9.25", - "@firebase/app-compat": "0.2.25", - "@firebase/auth": "1.5.1", - "@rollup/plugin-alias": "3.1.9", + "@firebase/app": "0.10.2", + "@firebase/app-compat": "0.2.32", + "@firebase/auth": "1.7.2", + "@rollup/plugin-alias": "5.1.0", "@rollup/plugin-json": "4.1.0", "@types/eslint": "7.29.0", - "@types/json-stable-stringify": "1.0.34", + "@types/json-stable-stringify": "1.0.36", "chai-exclude": "2.1.0", - "json-stable-stringify": "1.0.2", - "protobufjs": "7.2.4", + "json-stable-stringify": "1.1.1", + "protobufjs": "7.2.6", "rollup": "2.79.1", - "rollup-plugin-copy": "3.4.0", + "rollup-plugin-copy": "3.5.0", "rollup-plugin-copy-assets": "2.0.3", "rollup-plugin-replace": "2.2.0", "rollup-plugin-sourcemaps": "0.6.3", "rollup-plugin-terser": "7.0.2", "rollup-plugin-typescript2": "0.31.2", - "rollup-plugin-dts": "5.3.0", + "rollup-plugin-dts": "5.3.1", "ts-node": "10.9.1", "typescript": "4.7.4" }, "repository": { "directory": "packages/firestore", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/firestore/src/api.ts b/packages/firestore/src/api.ts index 510d95c8a89..5f5b078fbd6 100644 --- a/packages/firestore/src/api.ts +++ b/packages/firestore/src/api.ts @@ -139,7 +139,11 @@ export { WhereFilterOp } from './api/filter'; -export { SnapshotListenOptions, Unsubscribe } from './api/reference_impl'; +export { + ListenSource, + SnapshotListenOptions, + Unsubscribe +} from './api/reference_impl'; export { TransactionOptions } from './api/transaction_options'; @@ -215,6 +219,10 @@ export { */ export { isBase64Available as _isBase64Available } from './platform/base64'; export { DatabaseId as _DatabaseId } from './core/database_info'; +export { + _internalQueryToProtoQueryTarget, + _internalAggregationQueryToProtoRunAggregationQueryRequest +} from './remote/internal_serializer'; export { cast as _cast, validateIsNotUsedTogether as _validateIsNotUsedTogether diff --git a/packages/firestore/src/api/reference_impl.ts b/packages/firestore/src/api/reference_impl.ts index 13cfb09f518..e730fb40da7 100644 --- a/packages/firestore/src/api/reference_impl.ts +++ b/packages/firestore/src/api/reference_impl.ts @@ -24,6 +24,7 @@ import { NextFn, PartialObserver } from '../api/observer'; +import { ListenerDataSource } from '../core/event_manager'; import { firestoreClientAddSnapshotsInSyncListener, firestoreClientGetDocumentFromLocalCache, @@ -78,8 +79,22 @@ export interface SnapshotListenOptions { * changed. Default is false. */ readonly includeMetadataChanges?: boolean; + + /** + * Set the source the query listens to. Default to "default", which + * listens to both cache and server. + */ + readonly source?: ListenSource; } +/** + * Describe the source a query listens to. + * + * Set to `default` to listen to both cache and server changes. Set to `cache` + * to listen to changes in cache only. + */ +export type ListenSource = 'default' | 'cache'; + /** * Reads the document referred to by this `DocumentReference`. * @@ -668,7 +683,8 @@ export function onSnapshot( reference = getModularInstance(reference); let options: SnapshotListenOptions = { - includeMetadataChanges: false + includeMetadataChanges: false, + source: 'default' }; let currArg = 0; if (typeof args[currArg] === 'object' && !isPartialObserver(args[currArg])) { @@ -677,7 +693,8 @@ export function onSnapshot( } const internalOptions = { - includeMetadataChanges: options.includeMetadataChanges + includeMetadataChanges: options.includeMetadataChanges, + source: options.source as ListenerDataSource }; if (isPartialObserver(args[currArg])) { diff --git a/packages/firestore/src/api/snapshot.ts b/packages/firestore/src/api/snapshot.ts index fe74e03bcf0..29e1616b61c 100644 --- a/packages/firestore/src/api/snapshot.ts +++ b/packages/firestore/src/api/snapshot.ts @@ -48,6 +48,22 @@ import { SnapshotListenOptions } from './reference_impl'; * Using the converter allows you to specify generic type arguments when * storing and retrieving objects from Firestore. * + * In this context, an "AppModel" is a class that is used in an application to + * package together related information and functionality. Such a class could, + * for example, have properties with complex, nested data types, properties used + * for memoization, properties of types not supported by Firestore (such as + * `symbol` and `bigint`), and helper functions that perform compound + * operations. Such classes are not suitable and/or possible to store into a + * Firestore database. Instead, instances of such classes need to be converted + * to "plain old JavaScript objects" (POJOs) with exclusively primitive + * properties, potentially nested inside other POJOs or arrays of POJOs. In this + * context, this type is referred to as the "DbModel" and would be an object + * suitable for persisting into Firestore. For convenience, applications can + * implement `FirestoreDataConverter` and register the converter with Firestore + * objects, such as `DocumentReference` or `Query`, to automatically convert + * `AppModel` to `DbModel` when storing into Firestore, and convert `DbModel` + * to `AppModel` when retrieving from Firestore. + * * @example * * Simple Example @@ -250,8 +266,14 @@ export interface FirestoreDataConverter< * `snapshot.data(options)`. * * Generally, the data returned from `snapshot.data()` can be cast to - * `DbModelType`; however, this is not guaranteed as writes to the database - * may have occurred without a type converter enforcing this specific layout. + * `DbModelType`; however, this is not guaranteed because Firestore does not + * enforce a schema on the database. For example, writes from a previous + * version of the application or writes from another client that did not use a + * type converter could have written data with different properties and/or + * property types. The implementation will need to choose whether to + * gracefully recover from non-conforming data or throw an error. + * + * To override this method, see {@link (FirestoreDataConverter.fromFirestore:1)}. * * @param snapshot - A `QueryDocumentSnapshot` containing your data and metadata. * @param options - The `SnapshotOptions` from the initial call to `data()`. diff --git a/packages/firestore/src/core/event_manager.ts b/packages/firestore/src/core/event_manager.ts index 1723abd15d9..b53c45669cb 100644 --- a/packages/firestore/src/core/event_manager.ts +++ b/packages/firestore/src/core/event_manager.ts @@ -32,6 +32,11 @@ import { ChangeType, DocumentViewChange, ViewSnapshot } from './view_snapshot'; class QueryListenersInfo { viewSnap: ViewSnapshot | undefined = undefined; listeners: QueryListener[] = []; + + // Helper methods that checks if the query has listeners that listening to remote store + hasRemoteListeners(): boolean { + return this.listeners.some(listener => listener.listensToRemoteStore()); + } } /** @@ -52,8 +57,13 @@ export interface Observer { * allows users to tree-shake the Watch logic. */ export interface EventManager { - onListen?: (query: Query) => Promise; - onUnlisten?: (query: Query) => Promise; + onListen?: ( + query: Query, + enableRemoteListen: boolean + ) => Promise; + onUnlisten?: (query: Query, disableRemoteListen: boolean) => Promise; + onFirstRemoteStoreListen?: (query: Query) => Promise; + onLastRemoteStoreUnlisten?: (query: Query) => Promise; } export function newEventManager(): EventManager { @@ -71,9 +81,50 @@ export class EventManagerImpl implements EventManager { snapshotsInSyncListeners: Set> = new Set(); /** Callback invoked when a Query is first listen to. */ - onListen?: (query: Query) => Promise; + onListen?: ( + query: Query, + enableRemoteListen: boolean + ) => Promise; /** Callback invoked once all listeners to a Query are removed. */ - onUnlisten?: (query: Query) => Promise; + onUnlisten?: (query: Query, disableRemoteListen: boolean) => Promise; + + /** + * Callback invoked when a Query starts listening to the remote store, while + * already listening to the cache. + */ + onFirstRemoteStoreListen?: (query: Query) => Promise; + /** + * Callback invoked when a Query stops listening to the remote store, while + * still listening to the cache. + */ + onLastRemoteStoreUnlisten?: (query: Query) => Promise; +} + +function validateEventManager(eventManagerImpl: EventManagerImpl): void { + debugAssert(!!eventManagerImpl.onListen, 'onListen not set'); + debugAssert( + !!eventManagerImpl.onFirstRemoteStoreListen, + 'onFirstRemoteStoreListen not set' + ); + debugAssert(!!eventManagerImpl.onUnlisten, 'onUnlisten not set'); + debugAssert( + !!eventManagerImpl.onLastRemoteStoreUnlisten, + 'onLastRemoteStoreUnlisten not set' + ); +} + +const enum ListenerSetupAction { + InitializeLocalListenAndRequireWatchConnection, + InitializeLocalListenOnly, + RequireWatchConnectionOnly, + NoActionRequired +} + +const enum ListenerRemovalAction { + TerminateLocalListenAndRequireWatchDisconnection, + TerminateLocalListenOnly, + RequireWatchDisconnectionOnly, + NoActionRequired } export async function eventManagerListen( @@ -81,28 +132,53 @@ export async function eventManagerListen( listener: QueryListener ): Promise { const eventManagerImpl = debugCast(eventManager, EventManagerImpl); + validateEventManager(eventManagerImpl); + + let listenerAction = ListenerSetupAction.NoActionRequired; - debugAssert(!!eventManagerImpl.onListen, 'onListen not set'); const query = listener.query; - let firstListen = false; let queryInfo = eventManagerImpl.queries.get(query); if (!queryInfo) { - firstListen = true; queryInfo = new QueryListenersInfo(); + listenerAction = listener.listensToRemoteStore() + ? ListenerSetupAction.InitializeLocalListenAndRequireWatchConnection + : ListenerSetupAction.InitializeLocalListenOnly; + } else if ( + !queryInfo.hasRemoteListeners() && + listener.listensToRemoteStore() + ) { + // Query has been listening to local cache, and tries to add a new listener sourced from watch. + listenerAction = ListenerSetupAction.RequireWatchConnectionOnly; } - if (firstListen) { - try { - queryInfo.viewSnap = await eventManagerImpl.onListen(query); - } catch (e) { - const firestoreError = wrapInUserErrorIfRecoverable( - e as Error, - `Initialization of query '${stringifyQuery(listener.query)}' failed` - ); - listener.onError(firestoreError); - return; + try { + switch (listenerAction) { + case ListenerSetupAction.InitializeLocalListenAndRequireWatchConnection: + queryInfo.viewSnap = await eventManagerImpl.onListen!( + query, + /** enableRemoteListen= */ true + ); + break; + case ListenerSetupAction.InitializeLocalListenOnly: + queryInfo.viewSnap = await eventManagerImpl.onListen!( + query, + /** enableRemoteListen= */ false + ); + break; + case ListenerSetupAction.RequireWatchConnectionOnly: + await eventManagerImpl.onFirstRemoteStoreListen!(query); + break; + default: + break; } + } catch (e) { + const firestoreError = wrapInUserErrorIfRecoverable( + e as Error, + `Initialization of query '${stringifyQuery(listener.query)}' failed` + ); + listener.onError(firestoreError); + return; } eventManagerImpl.queries.set(query, queryInfo); @@ -130,23 +206,47 @@ export async function eventManagerUnlisten( listener: QueryListener ): Promise { const eventManagerImpl = debugCast(eventManager, EventManagerImpl); + validateEventManager(eventManagerImpl); - debugAssert(!!eventManagerImpl.onUnlisten, 'onUnlisten not set'); const query = listener.query; - let lastListen = false; + let listenerAction = ListenerRemovalAction.NoActionRequired; const queryInfo = eventManagerImpl.queries.get(query); if (queryInfo) { const i = queryInfo.listeners.indexOf(listener); if (i >= 0) { queryInfo.listeners.splice(i, 1); - lastListen = queryInfo.listeners.length === 0; + + if (queryInfo.listeners.length === 0) { + listenerAction = listener.listensToRemoteStore() + ? ListenerRemovalAction.TerminateLocalListenAndRequireWatchDisconnection + : ListenerRemovalAction.TerminateLocalListenOnly; + } else if ( + !queryInfo.hasRemoteListeners() && + listener.listensToRemoteStore() + ) { + // The removed listener is the last one that sourced from watch. + listenerAction = ListenerRemovalAction.RequireWatchDisconnectionOnly; + } } } - - if (lastListen) { - eventManagerImpl.queries.delete(query); - return eventManagerImpl.onUnlisten(query); + switch (listenerAction) { + case ListenerRemovalAction.TerminateLocalListenAndRequireWatchDisconnection: + eventManagerImpl.queries.delete(query); + return eventManagerImpl.onUnlisten!( + query, + /** disableRemoteListen= */ true + ); + case ListenerRemovalAction.TerminateLocalListenOnly: + eventManagerImpl.queries.delete(query); + return eventManagerImpl.onUnlisten!( + query, + /** disableRemoteListen= */ false + ); + case ListenerRemovalAction.RequireWatchDisconnectionOnly: + return eventManagerImpl.onLastRemoteStoreUnlisten!(query); + default: + return; } } @@ -241,6 +341,14 @@ function raiseSnapshotsInSyncEvent(eventManagerImpl: EventManagerImpl): void { }); } +export enum ListenerDataSource { + /** Listen to both cache and server changes */ + Default = 'default', + + /** Listen to changes in cache only */ + Cache = 'cache' +} + export interface ListenOptions { /** Raise events even when only the metadata changes */ readonly includeMetadataChanges?: boolean; @@ -250,6 +358,9 @@ export interface ListenOptions { * offline. */ readonly waitForSyncWhenOnline?: boolean; + + /** Set the source events raised from. */ + readonly source?: ListenerDataSource; } /** @@ -359,6 +470,11 @@ export class QueryListener { return true; } + // Always raise event if listening to cache + if (!this.listensToRemoteStore()) { + return true; + } + // NOTE: We consider OnlineState.Unknown as online (it should become Offline // or Online if we wait long enough). const maybeOnline = onlineState !== OnlineState.Offline; @@ -417,4 +533,8 @@ export class QueryListener { this.raisedInitialEvent = true; this.queryObserver.next(snap); } + + listensToRemoteStore(): boolean { + return this.options.source !== ListenerDataSource.Cache; + } } diff --git a/packages/firestore/src/core/firestore_client.ts b/packages/firestore/src/core/firestore_client.ts index c563a4c7f77..902e7c9b226 100644 --- a/packages/firestore/src/core/firestore_client.ts +++ b/packages/firestore/src/core/firestore_client.ts @@ -89,7 +89,9 @@ import { syncEngineLoadBundle, syncEngineRegisterPendingWritesCallback, syncEngineUnlisten, - syncEngineWrite + syncEngineWrite, + triggerRemoteStoreListen, + triggerRemoteStoreUnlisten } from './sync_engine_impl'; import { Transaction } from './transaction'; import { TransactionOptions } from './transaction_options'; @@ -400,6 +402,14 @@ export async function getEventManager( null, onlineComponentProvider.syncEngine ); + eventManager.onFirstRemoteStoreListen = triggerRemoteStoreListen.bind( + null, + onlineComponentProvider.syncEngine + ); + eventManager.onLastRemoteStoreUnlisten = triggerRemoteStoreUnlisten.bind( + null, + onlineComponentProvider.syncEngine + ); return eventManager; } diff --git a/packages/firestore/src/core/sync_engine_impl.ts b/packages/firestore/src/core/sync_engine_impl.ts index 18a1dc681f5..f4db6f4a5bd 100644 --- a/packages/firestore/src/core/sync_engine_impl.ts +++ b/packages/firestore/src/core/sync_engine_impl.ts @@ -292,11 +292,11 @@ export function newSyncEngine( */ export async function syncEngineListen( syncEngine: SyncEngine, - query: Query + query: Query, + shouldListenToRemote: boolean = true ): Promise { const syncEngineImpl = ensureWatchCallbacks(syncEngine); - let targetId; let viewSnapshot; const queryView = syncEngineImpl.queryViewsByQuery.get(query); @@ -307,19 +307,58 @@ export async function syncEngineListen( // behalf of another tab and the user of the primary also starts listening // to the query. EventManager will not have an assigned target ID in this // case and calls `listen` to obtain this ID. - targetId = queryView.targetId; - syncEngineImpl.sharedClientState.addLocalQueryTarget(targetId); + syncEngineImpl.sharedClientState.addLocalQueryTarget(queryView.targetId); viewSnapshot = queryView.view.computeInitialSnapshot(); } else { - const targetData = await localStoreAllocateTarget( - syncEngineImpl.localStore, - queryToTarget(query) + viewSnapshot = await allocateTargetAndMaybeListen( + syncEngineImpl, + query, + shouldListenToRemote, + /** shouldInitializeView= */ true ); + debugAssert(!!viewSnapshot, 'viewSnapshot is not initialized'); + } - const status = syncEngineImpl.sharedClientState.addLocalQueryTarget( - targetData.targetId - ); - targetId = targetData.targetId; + return viewSnapshot; +} + +/** Query has been listening to the cache, and tries to initiate the remote store listen */ +export async function triggerRemoteStoreListen( + syncEngine: SyncEngine, + query: Query +): Promise { + const syncEngineImpl = ensureWatchCallbacks(syncEngine); + await allocateTargetAndMaybeListen( + syncEngineImpl, + query, + /** shouldListenToRemote= */ true, + /** shouldInitializeView= */ false + ); +} + +async function allocateTargetAndMaybeListen( + syncEngineImpl: SyncEngineImpl, + query: Query, + shouldListenToRemote: boolean, + shouldInitializeView: boolean +): Promise { + const targetData = await localStoreAllocateTarget( + syncEngineImpl.localStore, + queryToTarget(query) + ); + + const targetId = targetData.targetId; + + // PORTING NOTE: When the query is listening to cache only, we skip sending it over to Watch by + // not registering it in shared client state, and directly calculate initial snapshots and + // subsequent updates from cache. Otherwise, register the target ID with local Firestore client + // as active watch target. + const status: QueryTargetState = shouldListenToRemote + ? syncEngineImpl.sharedClientState.addLocalQueryTarget(targetId) + : 'not-current'; + + let viewSnapshot; + if (shouldInitializeView) { viewSnapshot = await initializeViewAndComputeSnapshot( syncEngineImpl, query, @@ -327,10 +366,10 @@ export async function syncEngineListen( status === 'current', targetData.resumeToken ); + } - if (syncEngineImpl.isPrimaryClient) { - remoteStoreListen(syncEngineImpl.remoteStore, targetData); - } + if (syncEngineImpl.isPrimaryClient && shouldListenToRemote) { + remoteStoreListen(syncEngineImpl.remoteStore, targetData); } return viewSnapshot; @@ -393,7 +432,8 @@ async function initializeViewAndComputeSnapshot( /** Stops listening to the query. */ export async function syncEngineUnlisten( syncEngine: SyncEngine, - query: Query + query: Query, + shouldUnlistenToRemote: boolean ): Promise { const syncEngineImpl = debugCast(syncEngine, SyncEngineImpl); const queryView = syncEngineImpl.queryViewsByQuery.get(query)!; @@ -430,7 +470,9 @@ export async function syncEngineUnlisten( ) .then(() => { syncEngineImpl.sharedClientState.clearQueryState(queryView.targetId); - remoteStoreUnlisten(syncEngineImpl.remoteStore, queryView.targetId); + if (shouldUnlistenToRemote) { + remoteStoreUnlisten(syncEngineImpl.remoteStore, queryView.targetId); + } removeAndCleanupTarget(syncEngineImpl, queryView.targetId); }) .catch(ignoreIfPrimaryLeaseLoss); @@ -445,6 +487,28 @@ export async function syncEngineUnlisten( } } +/** Unlistens to the remote store while still listening to the cache. */ +export async function triggerRemoteStoreUnlisten( + syncEngine: SyncEngine, + query: Query +): Promise { + const syncEngineImpl = debugCast(syncEngine, SyncEngineImpl); + const queryView = syncEngineImpl.queryViewsByQuery.get(query)!; + debugAssert( + !!queryView, + 'Trying to unlisten on query not found:' + stringifyQuery(query) + ); + const queries = syncEngineImpl.queriesByTarget.get(queryView.targetId)!; + + if (syncEngineImpl.isPrimaryClient && queries.length === 1) { + // PORTING NOTE: Unregister the target ID with local Firestore client as + // watch target. + syncEngineImpl.sharedClientState.removeLocalQueryTarget(queryView.targetId); + + remoteStoreUnlisten(syncEngineImpl.remoteStore, queryView.targetId); + } +} + /** * Initiates the write of local mutation batch which involves adding the * writes to the mutation queue, notifying the remote store about new @@ -1504,8 +1568,12 @@ export async function syncEngineApplyActiveTargetsChange( } for (const targetId of added) { - if (syncEngineImpl.queriesByTarget.has(targetId)) { - // A target might have been added in a previous attempt + // A target is already listening to remote store if it is already registered to + // sharedClientState. + const targetAlreadyListeningToRemoteStore = + syncEngineImpl.queriesByTarget.has(targetId) && + syncEngineImpl.sharedClientState.isActiveQueryTarget(targetId); + if (targetAlreadyListeningToRemoteStore) { logDebug(LOG_TAG, 'Adding an already active target ' + targetId); continue; } diff --git a/packages/firestore/src/index/firestore_index_value_writer.ts b/packages/firestore/src/index/firestore_index_value_writer.ts index 9bbcd6fcc63..9d5d86ab640 100644 --- a/packages/firestore/src/index/firestore_index_value_writer.ts +++ b/packages/firestore/src/index/firestore_index_value_writer.ts @@ -16,7 +16,11 @@ */ import { DocumentKey } from '../model/document_key'; -import { normalizeByteString, normalizeNumber } from '../model/normalize'; +import { + normalizeByteString, + normalizeNumber, + normalizeTimestamp +} from '../model/normalize'; import { isMaxValue } from '../model/values'; import { ArrayValue, MapValue, Value } from '../protos/firestore_proto_api'; import { fail } from '../util/assert'; @@ -93,14 +97,13 @@ export class FirestoreIndexValueWriter { } } } else if ('timestampValue' in indexValue) { - const timestamp = indexValue.timestampValue!; + let timestamp = indexValue.timestampValue!; this.writeValueTypeLabel(encoder, INDEX_TYPE_TIMESTAMP); if (typeof timestamp === 'string') { - encoder.writeString(timestamp); - } else { - encoder.writeString(`${timestamp.seconds || ''}`); - encoder.writeNumber(timestamp.nanos || 0); + timestamp = normalizeTimestamp(timestamp); } + encoder.writeString(`${timestamp.seconds || ''}`); + encoder.writeNumber(timestamp.nanos || 0); } else if ('stringValue' in indexValue) { this.writeIndexString(indexValue.stringValue!, encoder); this.writeTruncationMarker(encoder); diff --git a/packages/firestore/src/lite-api/snapshot.ts b/packages/firestore/src/lite-api/snapshot.ts index e1fe19522db..af3e343f916 100644 --- a/packages/firestore/src/lite-api/snapshot.ts +++ b/packages/firestore/src/lite-api/snapshot.ts @@ -46,6 +46,22 @@ import { AbstractUserDataWriter } from './user_data_writer'; * Using the converter allows you to specify generic type arguments when * storing and retrieving objects from Firestore. * + * In this context, an "AppModel" is a class that is used in an application to + * package together related information and functionality. Such a class could, + * for example, have properties with complex, nested data types, properties used + * for memoization, properties of types not supported by Firestore (such as + * `symbol` and `bigint`), and helper functions that perform compound + * operations. Such classes are not suitable and/or possible to store into a + * Firestore database. Instead, instances of such classes need to be converted + * to "plain old JavaScript objects" (POJOs) with exclusively primitive + * properties, potentially nested inside other POJOs or arrays of POJOs. In this + * context, this type is referred to as the "DbModel" and would be an object + * suitable for persisting into Firestore. For convenience, applications can + * implement `FirestoreDataConverter` and register the converter with Firestore + * objects, such as `DocumentReference` or `Query`, to automatically convert + * `AppModel` to `DbModel` when storing into Firestore, and convert `DbModel` + * to `AppModel` when retrieving from Firestore. + * * @example * * Simple Example @@ -250,9 +266,14 @@ export interface FirestoreDataConverter< * type `AppModelType`. You can access your data by calling: * `snapshot.data()`. * + * * Generally, the data returned from `snapshot.data()` can be cast to - * `DbModelType`; however, this is not guaranteed as writes to the database - * may have occurred without a type converter enforcing this specific layout. + * `DbModelType`; however, this is not guaranteed because Firestore does not + * enforce a schema on the database. For example, writes from a previous + * version of the application or writes from another client that did not use a + * type converter could have written data with different properties and/or + * property types. The implementation will need to choose whether to + * gracefully recover from non-conforming data or throw an error. * * @param snapshot - A `QueryDocumentSnapshot` containing your data and * metadata. diff --git a/packages/firestore/src/local/indexeddb_schema.ts b/packages/firestore/src/local/indexeddb_schema.ts index c4373f3881e..b832f29a035 100644 --- a/packages/firestore/src/local/indexeddb_schema.ts +++ b/packages/firestore/src/local/indexeddb_schema.ts @@ -51,9 +51,10 @@ import { DbTimestampKey } from './indexeddb_sentinels'; * document lookup via `getAll()`. * 14. Add overlays. * 15. Add indexing support. + * 16. Parse timestamp strings before creating index entries. */ -export const SCHEMA_VERSION = 15; +export const SCHEMA_VERSION = 16; /** * Wrapper class to store timestamps (seconds and nanos) in IndexedDb objects. diff --git a/packages/firestore/src/local/indexeddb_schema_converter.ts b/packages/firestore/src/local/indexeddb_schema_converter.ts index 3509db11a14..b65a63a627f 100644 --- a/packages/firestore/src/local/indexeddb_schema_converter.ts +++ b/packages/firestore/src/local/indexeddb_schema_converter.ts @@ -256,6 +256,19 @@ export class SchemaConverter implements SimpleDbSchemaConverter { p = p.next(() => createFieldIndex(db)); } + if (fromVersion < 16 && toVersion >= 16) { + // Clear the object stores to remove possibly corrupted index entries + p = p + .next(() => { + const indexStateStore = txn.objectStore(DbIndexStateStore); + indexStateStore.clear(); + }) + .next(() => { + const indexEntryStore = txn.objectStore(DbIndexEntryStore); + indexEntryStore.clear(); + }); + } + return p; } diff --git a/packages/firestore/src/local/indexeddb_sentinels.ts b/packages/firestore/src/local/indexeddb_sentinels.ts index f0b92c1224a..854b146ed7f 100644 --- a/packages/firestore/src/local/indexeddb_sentinels.ts +++ b/packages/firestore/src/local/indexeddb_sentinels.ts @@ -414,6 +414,7 @@ export const V15_STORES = [ DbIndexStateStore, DbIndexEntryStore ]; +export const V16_STORES = V15_STORES; /** * The list of all default IndexedDB stores used throughout the SDK. This is @@ -424,7 +425,9 @@ export const ALL_STORES = V12_STORES; /** Returns the object stores for the provided schema. */ export function getObjectStores(schemaVersion: number): string[] { - if (schemaVersion === 15) { + if (schemaVersion === 16) { + return V16_STORES; + } else if (schemaVersion === 15) { return V15_STORES; } else if (schemaVersion === 14) { return V14_STORES; diff --git a/packages/firestore/src/local/query_engine.ts b/packages/firestore/src/local/query_engine.ts index 1da72145f58..4872b4ca2c1 100644 --- a/packages/firestore/src/local/query_engine.ts +++ b/packages/firestore/src/local/query_engine.ts @@ -53,7 +53,7 @@ import { LocalDocumentsView } from './local_documents_view'; import { PersistencePromise } from './persistence_promise'; import { PersistenceTransaction } from './persistence_transaction'; import { QueryContext } from './query_context'; -import { SimpleDb } from './simple_db'; +import { getAndroidVersion } from './simple_db'; const DEFAULT_INDEX_AUTO_CREATION_MIN_COLLECTION_SIZE = 100; @@ -69,7 +69,7 @@ function getDefaultRelativeIndexReadCostPerDocument(): number { // Googlers can see b/299284287 for details. if (isSafari()) { return 8; - } else if (SimpleDb.getAndroidVersion(getUA()) > 0) { + } else if (getAndroidVersion(getUA()) > 0) { return 6; } else { return 4; diff --git a/packages/firestore/src/local/shared_client_state.ts b/packages/firestore/src/local/shared_client_state.ts index 67a528957b4..0d0e430c12f 100644 --- a/packages/firestore/src/local/shared_client_state.ts +++ b/packages/firestore/src/local/shared_client_state.ts @@ -349,7 +349,7 @@ export class QueryTargetMetadata { /** * Metadata state of a single client denoting the query targets it is actively - * listening to. + * listening to the watch. */ // Visible for testing. export interface ClientState { diff --git a/packages/firestore/src/local/simple_db.ts b/packages/firestore/src/local/simple_db.ts index 2fc821efd21..e79df248a0f 100644 --- a/packages/firestore/src/local/simple_db.ts +++ b/packages/firestore/src/local/simple_db.ts @@ -201,7 +201,7 @@ export class SimpleDb { const isUnsupportedIOS = 0 < iOSVersion && iOSVersion < 10; // Android browser: Disable for userse running version < 4.5. - const androidVersion = SimpleDb.getAndroidVersion(ua); + const androidVersion = getAndroidVersion(ua); const isUnsupportedAndroid = 0 < androidVersion && androidVersion < 4.5; if ( @@ -246,16 +246,6 @@ export class SimpleDb { return Number(version); } - // visible for testing - /** Parse User Agent to determine Android version. Returns -1 if not found. */ - static getAndroidVersion(ua: string): number { - const androidVersionRegex = ua.match(/Android ([\d.]+)/i); - const version = androidVersionRegex - ? androidVersionRegex[1].split('.').slice(0, 2).join('.') - : '-1'; - return Number(version); - } - /* * Creates a new SimpleDb wrapper for IndexedDb database `name`. * @@ -470,6 +460,15 @@ export class SimpleDb { } } +/** Parse User Agent to determine Android version. Returns -1 if not found. */ +export function getAndroidVersion(ua: string): number { + const androidVersionRegex = ua.match(/Android ([\d.]+)/i); + const version = androidVersionRegex + ? androidVersionRegex[1].split('.').slice(0, 2).join('.') + : '-1'; + return Number(version); +} + /** * A controller for iterating over a key range or index. It allows an iterate * callback to delete the currently-referenced object, or jump to a new key diff --git a/packages/firestore/src/platform/browser/webchannel_connection.ts b/packages/firestore/src/platform/browser/webchannel_connection.ts index 05cd79ecf9e..aa790f0ac2b 100644 --- a/packages/firestore/src/platform/browser/webchannel_connection.ts +++ b/packages/firestore/src/platform/browser/webchannel_connection.ts @@ -27,8 +27,9 @@ import { EventTarget, StatEvent, Event, + FetchXmlHttpFactory, Stat -} from '@firebase/webchannel-wrapper'; +} from '@firebase/webchannel-wrapper/webchannel-blob'; import { Token } from '../../api/credentials'; import { ExperimentalLongPollingOptions } from '../../api/long_polling_options'; @@ -208,7 +209,7 @@ export class WebChannelConnection extends RestConnection { } if (this.useFetchStreams) { - request.useFetchStreams = true; + request.xmlHttpFactory = new FetchXmlHttpFactory({}); } this.modifyHeadersForRequest( @@ -306,6 +307,7 @@ export class WebChannelConnection extends RestConnection { LOG_TAG, `RPC '${rpcName}' stream ${streamId} transport opened.` ); + streamBridge.callOnConnected(); } }); diff --git a/packages/firestore/src/platform/node/grpc_connection.ts b/packages/firestore/src/platform/node/grpc_connection.ts index ab9e44792ca..dec3137af76 100644 --- a/packages/firestore/src/platform/node/grpc_connection.ts +++ b/packages/firestore/src/platform/node/grpc_connection.ts @@ -286,9 +286,15 @@ export class GrpcConnection implements Connection { } }); + let onConnectedSent = false; grpcStream.on('data', (msg: Resp) => { if (!closed) { logDebug(LOG_TAG, `RPC '${rpcName}' stream ${streamId} received:`, msg); + // Emulate the "onConnected" event that WebChannelConnection sends. + if (!onConnectedSent) { + stream.callOnConnected(); + onConnectedSent = true; + } stream.callOnMessage(msg); } }); diff --git a/packages/firestore/src/remote/bloom_filter.ts b/packages/firestore/src/remote/bloom_filter.ts index 4c0e4ef6b7e..afb8d731211 100644 --- a/packages/firestore/src/remote/bloom_filter.ts +++ b/packages/firestore/src/remote/bloom_filter.ts @@ -14,7 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Md5, Integer } from '@firebase/webchannel-wrapper'; + +import { Md5, Integer } from '@firebase/webchannel-wrapper/bloom-blob'; import { newTextEncoder } from '../platform/text_serializer'; diff --git a/packages/firestore/src/remote/connection.ts b/packages/firestore/src/remote/connection.ts index b727bc63c17..2bf982eb4d1 100644 --- a/packages/firestore/src/remote/connection.ts +++ b/packages/firestore/src/remote/connection.ts @@ -109,10 +109,14 @@ export interface Connection { * A bidirectional stream that can be used to send an receive messages. * * A stream can be closed locally with close() or can be closed remotely or - * through network errors. onClose is guaranteed to be called. onOpen will only - * be called if the stream successfully established a connection. + * through network errors. onClose is guaranteed to be called. onOpen will be + * called once the stream is ready to send messages (which may or may not be + * before an actual connection to the backend has been established). The + * onConnected event is called when an actual, physical connection with the + * backend has been established, and may occur before or after the onOpen event. */ export interface Stream { + onConnected(callback: () => void): void; onOpen(callback: () => void): void; onClose(callback: (err?: FirestoreError) => void): void; onMessage(callback: (msg: O) => void): void; diff --git a/packages/firestore/src/remote/internal_serializer.ts b/packages/firestore/src/remote/internal_serializer.ts new file mode 100644 index 00000000000..8f278247581 --- /dev/null +++ b/packages/firestore/src/remote/internal_serializer.ts @@ -0,0 +1,89 @@ +/** + * @license + * Copyright 2017 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ensureFirestoreConfigured, Firestore } from '../api/database'; +import { AggregateImpl } from '../core/aggregate'; +import { queryToAggregateTarget, queryToTarget } from '../core/query'; +import { AggregateSpec } from '../lite-api/aggregate_types'; +import { Query } from '../lite-api/reference'; +import { cast } from '../util/input_validation'; +import { mapToArray } from '../util/obj'; + +import { toQueryTarget, toRunAggregationQueryRequest } from './serializer'; + +/** + * @internal + * @private + * + * This function is for internal use only. + * + * Returns the `QueryTarget` representation of the given query. Returns `null` + * if the Firestore client associated with the given query has not been + * initialized or has been terminated. + * + * @param query - The Query to convert to proto representation. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function _internalQueryToProtoQueryTarget(query: Query): any { + const firestore = cast(query.firestore, Firestore); + const client = ensureFirestoreConfigured(firestore); + const serializer = client._onlineComponents?.datastore.serializer; + if (serializer === undefined) { + return null; + } + return toQueryTarget(serializer!, queryToTarget(query._query)).queryTarget; +} + +/** + * @internal + * @private + * + * This function is for internal use only. + * + * Returns `RunAggregationQueryRequest` which contains the proto representation + * of the given aggregation query request. Returns null if the Firestore client + * associated with the given query has not been initialized or has been + * terminated. + * + * @param query - The Query to convert to proto representation. + * @param aggregateSpec - The set of aggregations and their aliases. + */ +export function _internalAggregationQueryToProtoRunAggregationQueryRequest< + AggregateSpecType extends AggregateSpec + // eslint-disable-next-line @typescript-eslint/no-explicit-any +>(query: Query, aggregateSpec: AggregateSpecType): any { + const aggregates = mapToArray(aggregateSpec, (aggregate, alias) => { + return new AggregateImpl( + alias, + aggregate.aggregateType, + aggregate._internalFieldPath + ); + }); + const firestore = cast(query.firestore, Firestore); + const client = ensureFirestoreConfigured(firestore); + const serializer = client._onlineComponents?.datastore.serializer; + if (serializer === undefined) { + return null; + } + + return toRunAggregationQueryRequest( + serializer!, + queryToAggregateTarget(query._query), + aggregates, + /* skipAliasing= */ true + ).request; +} diff --git a/packages/firestore/src/remote/persistent_stream.ts b/packages/firestore/src/remote/persistent_stream.ts index b7f657876b4..21c35aace28 100644 --- a/packages/firestore/src/remote/persistent_stream.ts +++ b/packages/firestore/src/remote/persistent_stream.ts @@ -125,6 +125,11 @@ const enum PersistentStreamState { * events by the concrete implementation classes. */ export interface PersistentStreamListener { + /** + * Called after receiving an acknowledgement from the server, confirming that + * we are able to connect to it. + */ + onConnected: () => Promise; /** * Called after the stream was established and can accept outgoing * messages @@ -483,6 +488,9 @@ export abstract class PersistentStream< const dispatchIfNotClosed = this.getCloseGuardedDispatcher(this.closeCount); this.stream = this.startRpc(authToken, appCheckToken); + this.stream.onConnected(() => { + dispatchIfNotClosed(() => this.listener!.onConnected()); + }); this.stream.onOpen(() => { dispatchIfNotClosed(() => { debugAssert( diff --git a/packages/firestore/src/remote/remote_store.ts b/packages/firestore/src/remote/remote_store.ts index 8cb361bfe09..2e9cb1546e3 100644 --- a/packages/firestore/src/remote/remote_store.ts +++ b/packages/firestore/src/remote/remote_store.ts @@ -403,6 +403,13 @@ function cleanUpWatchStreamState(remoteStoreImpl: RemoteStoreImpl): void { remoteStoreImpl.watchChangeAggregator = undefined; } +async function onWatchStreamConnected( + remoteStoreImpl: RemoteStoreImpl +): Promise { + // Mark the client as online since we got a "connected" notification. + remoteStoreImpl.onlineStateTracker.set(OnlineState.Online); +} + async function onWatchStreamOpen( remoteStoreImpl: RemoteStoreImpl ): Promise { @@ -923,6 +930,7 @@ function ensureWatchStream( remoteStoreImpl.datastore, remoteStoreImpl.asyncQueue, { + onConnected: onWatchStreamConnected.bind(null, remoteStoreImpl), onOpen: onWatchStreamOpen.bind(null, remoteStoreImpl), onClose: onWatchStreamClose.bind(null, remoteStoreImpl), onWatchChange: onWatchStreamChange.bind(null, remoteStoreImpl) @@ -969,6 +977,7 @@ function ensureWriteStream( remoteStoreImpl.datastore, remoteStoreImpl.asyncQueue, { + onConnected: () => Promise.resolve(), onOpen: onWriteStreamOpen.bind(null, remoteStoreImpl), onClose: onWriteStreamClose.bind(null, remoteStoreImpl), onHandshakeComplete: onWriteHandshakeComplete.bind( diff --git a/packages/firestore/src/remote/serializer.ts b/packages/firestore/src/remote/serializer.ts index 175c3110f60..811c2ac4df6 100644 --- a/packages/firestore/src/remote/serializer.ts +++ b/packages/firestore/src/remote/serializer.ts @@ -262,8 +262,14 @@ export function fromBytes( return ByteString.fromBase64String(value ? value : ''); } else { hardAssert( - value === undefined || value instanceof Uint8Array, - 'value must be undefined or Uint8Array' + value === undefined || + // Check if the value is an instance of both Buffer and Uint8Array, + // despite the fact that Buffer extends Uint8Array. In some + // environments, such as jsdom, the prototype chain of Buffer + // does not indicate that it extends Uint8Array. + value instanceof Buffer || + value instanceof Uint8Array, + 'value must be undefined, Buffer, or Uint8Array' ); return ByteString.fromUint8Array(value ? value : new Uint8Array()); } @@ -897,7 +903,8 @@ export function toQueryTarget( export function toRunAggregationQueryRequest( serializer: JsonProtoSerializer, target: Target, - aggregates: Aggregate[] + aggregates: Aggregate[], + skipAliasing?: boolean ): { request: ProtoRunAggregationQueryRequest; aliasMap: Record; @@ -913,7 +920,9 @@ export function toRunAggregationQueryRequest( // Map all client-side aliases to a unique short-form // alias. This avoids issues with client-side aliases that // exceed the 1500-byte string size limit. - const serverAlias = `aggregate_${aggregationNum++}`; + const serverAlias = skipAliasing + ? aggregate.alias + : `aggregate_${aggregationNum++}`; aliasMap[serverAlias] = aggregate.alias; if (aggregate.aggregateType === 'count') { diff --git a/packages/firestore/src/remote/stream_bridge.ts b/packages/firestore/src/remote/stream_bridge.ts index bfecb707b8a..78ae01116ac 100644 --- a/packages/firestore/src/remote/stream_bridge.ts +++ b/packages/firestore/src/remote/stream_bridge.ts @@ -26,6 +26,7 @@ import { Stream } from './connection'; * interface. The stream callbacks are invoked with the callOn... methods. */ export class StreamBridge implements Stream { + private wrappedOnConnected: (() => void) | undefined; private wrappedOnOpen: (() => void) | undefined; private wrappedOnClose: ((err?: FirestoreError) => void) | undefined; private wrappedOnMessage: ((msg: O) => void) | undefined; @@ -38,6 +39,14 @@ export class StreamBridge implements Stream { this.closeFn = args.closeFn; } + onConnected(callback: () => void): void { + debugAssert( + !this.wrappedOnConnected, + 'Called onConnected on stream twice!' + ); + this.wrappedOnConnected = callback; + } + onOpen(callback: () => void): void { debugAssert(!this.wrappedOnOpen, 'Called onOpen on stream twice!'); this.wrappedOnOpen = callback; @@ -61,6 +70,14 @@ export class StreamBridge implements Stream { this.sendFn(msg); } + callOnConnected(): void { + debugAssert( + this.wrappedOnConnected !== undefined, + 'Cannot call onConnected because no callback was set' + ); + this.wrappedOnConnected(); + } + callOnOpen(): void { debugAssert( this.wrappedOnOpen !== undefined, diff --git a/packages/firestore/test/integration/api/composite_index_query.test.ts b/packages/firestore/test/integration/api/composite_index_query.test.ts index da70ac1ece7..04cdafe7169 100644 --- a/packages/firestore/test/integration/api/composite_index_query.test.ts +++ b/packages/firestore/test/integration/api/composite_index_query.test.ts @@ -30,7 +30,12 @@ import { count, doc, writeBatch, - collectionGroup + collectionGroup, + FieldPath, + and, + getCountFromServer, + documentId, + disableNetwork } from '../util/firebase_export'; import { apiDescribe } from '../util/helpers'; @@ -302,4 +307,649 @@ apiDescribe('Composite Index Queries', persistence => { }); }); }); + + describe('Multiple Inequality', () => { + it('can use multiple inequality filters', async () => { + const testDocs = { + doc1: { key: 'a', sort: 0, v: 0 }, + doc2: { key: 'b', sort: 3, v: 1 }, + doc3: { key: 'c', sort: 1, v: 3 }, + doc4: { key: 'd', sort: 2, v: 2 } + }; + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestDocs(persistence, testDocs, async coll => { + // Multiple inequality fields + let snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '!=', 'a'), + where('sort', '<=', 2), + where('v', '>', 2) + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, ['doc3']); + + // Duplicate inequality fields + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '!=', 'a'), + where('sort', '<=', 2), + where('sort', '>', 1) + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, ['doc4']); + + // With multiple IN + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '>=', 'a'), + where('sort', '<=', 2), + where('v', 'in', [2, 3, 4]), + where('sort', 'in', [2, 3]) + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, ['doc4']); + + // With NOT-IN + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '>=', 'a'), + where('sort', '<=', 2), + where('v', 'not-in', [2, 4, 5]) + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, ['doc1', 'doc3']); + + // With orderby + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '>=', 'a'), + where('sort', '<=', 2), + orderBy('v', 'desc') + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, [ + 'doc3', + 'doc4', + 'doc1' + ]); + + // With limit + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '>=', 'a'), + where('sort', '<=', 2), + orderBy('v', 'desc'), + limit(2) + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, ['doc3', 'doc4']); + + // With limitToLast + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '>=', 'a'), + where('sort', '<=', 2), + orderBy('v', 'desc'), + limitToLast(2) + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, ['doc4', 'doc1']); + }); + }); + + it('can use on special values', async () => { + const testDocs = { + doc1: { key: 'a', sort: 0, v: 0 }, + doc2: { key: 'b', sort: NaN, v: 1 }, + doc3: { key: 'c', sort: null, v: 3 }, + doc4: { key: 'd', v: 0 }, + doc5: { key: 'e', sort: 1 }, + doc6: { key: 'f', sort: 1, v: 1 } + }; + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestDocs(persistence, testDocs, async coll => { + let snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '!=', 'a'), + where('sort', '<=', 2) + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, ['doc5', 'doc6']); + + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '!=', 'a'), + where('sort', '<=', 2), + where('v', '<=', 1) + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, ['doc6']); + }); + }); + + it('can use with array membership', async () => { + const testDocs = { + doc1: { key: 'a', sort: 0, v: [0] }, + doc2: { key: 'b', sort: 1, v: [0, 1, 3] }, + doc3: { key: 'c', sort: 1, v: [] }, + doc4: { key: 'd', sort: 2, v: [1] }, + doc5: { key: 'e', sort: 3, v: [2, 4] }, + doc6: { key: 'f', sort: 4, v: [NaN] }, + doc7: { key: 'g', sort: 4, v: [null] } + }; + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestDocs(persistence, testDocs, async coll => { + let snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '!=', 'a'), + where('sort', '>=', 1), + where('v', 'array-contains', 0) + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, ['doc2']); + + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '!=', 'a'), + where('sort', '>=', 1), + where('v', 'array-contains-any', [0, 1]) + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, ['doc2', 'doc4']); + }); + }); + + it('can use with nested field', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const testData = (n?: number): any => { + n = n || 1; + return { + name: 'room ' + n, + metadata: { + createdAt: n + }, + field: 'field ' + n, + 'field.dot': n, + 'field\\slash': n + }; + }; + + const testDocs = { + 'doc1': testData(400), + 'doc2': testData(200), + 'doc3': testData(100), + 'doc4': testData(300) + }; + + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestDocs(persistence, testDocs, async coll => { + let snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('metadata.createdAt', '<=', 500), + where('metadata.createdAt', '>', 100), + where('name', '!=', 'room 200'), + orderBy('name') + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, ['doc4', 'doc1']); + + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('field', '>=', 'field 100'), + where(new FieldPath('field.dot'), '!=', 300), + where('field\\slash', '<', 400), + orderBy('name', 'desc') + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, ['doc2', 'doc3']); + }); + }); + + it('can use with nested composite filters', async () => { + const testDocs = { + doc1: { key: 'a', sort: 0, v: 5 }, + doc2: { key: 'aa', sort: 4, v: 4 }, + doc3: { key: 'c', sort: 3, v: 3 }, + doc4: { key: 'b', sort: 2, v: 2 }, + doc5: { key: 'b', sort: 2, v: 1 }, + doc6: { key: 'b', sort: 0, v: 0 } + }; + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestDocs(persistence, testDocs, async coll => { + let snapshot = await testHelper.getDocs( + testHelper.compositeQuery( + coll, + or( + and(where('key', '==', 'b'), where('sort', '<=', 2)), + and(where('key', '!=', 'b'), where('v', '>', 4)) + ) + ) + ); + // Implicitly ordered by: 'key' asc, 'sort' asc, 'v' asc, __name__ asc + testHelper.assertSnapshotResultIdsMatch(snapshot, [ + 'doc1', + 'doc6', + 'doc5', + 'doc4' + ]); + + snapshot = await testHelper.getDocs( + testHelper.compositeQuery( + coll, + or( + and(where('key', '==', 'b'), where('sort', '<=', 2)), + and(where('key', '!=', 'b'), where('v', '>', 4)) + ), + orderBy('sort', 'desc'), + orderBy('key') + ) + ); + // Ordered by: 'sort' desc, 'key' asc, 'v' asc, __name__ asc + testHelper.assertSnapshotResultIdsMatch(snapshot, [ + 'doc5', + 'doc4', + 'doc1', + 'doc6' + ]); + + snapshot = await testHelper.getDocs( + testHelper.compositeQuery( + coll, + and( + or( + and(where('key', '==', 'b'), where('sort', '<=', 4)), + and(where('key', '!=', 'b'), where('v', '>=', 4)) + ), + or( + and(where('key', '>', 'b'), where('sort', '>=', 1)), + and(where('key', '<', 'b'), where('v', '>', 0)) + ) + ) + ) + ); + // Implicitly ordered by: 'key' asc, 'sort' asc, 'v' asc, __name__ asc + testHelper.assertSnapshotResultIdsMatch(snapshot, ['doc1', 'doc2']); + }); + }); + + it('inequality fields will be implicitly ordered lexicographically', async () => { + const testDocs = { + doc1: { key: 'a', sort: 0, v: 5 }, + doc2: { key: 'aa', sort: 4, v: 4 }, + doc3: { key: 'b', sort: 3, v: 3 }, + doc4: { key: 'b', sort: 2, v: 2 }, + doc5: { key: 'b', sort: 2, v: 1 }, + doc6: { key: 'b', sort: 0, v: 0 } + }; + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestDocs(persistence, testDocs, async coll => { + // Implicitly ordered by: 'key' asc, 'sort' asc, __name__ asc + let snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '!=', 'a'), + where('sort', '>', 1), + where('v', 'in', [1, 2, 3, 4]) + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, [ + 'doc2', + 'doc4', + 'doc5', + 'doc3' + ]); + + // Implicitly ordered by: 'key' asc, 'sort' asc,__name__ asc + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('sort', '>', 1), + where('key', '!=', 'a'), + where('v', 'in', [1, 2, 3, 4]) + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, [ + 'doc2', + 'doc4', + 'doc5', + 'doc3' + ]); + }); + }); + + it('can use multiple explicit order by field', async () => { + const testDocs = { + doc1: { key: 'a', sort: 5, v: 0 }, + doc2: { key: 'aa', sort: 4, v: 0 }, + doc3: { key: 'b', sort: 3, v: 1 }, + doc4: { key: 'b', sort: 2, v: 1 }, + doc5: { key: 'bb', sort: 1, v: 1 }, + doc6: { key: 'c', sort: 0, v: 2 } + }; + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestDocs(persistence, testDocs, async coll => { + // Ordered by: 'v' asc, 'key' asc, 'sort' asc, __name__ asc + let snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '>', 'a'), + where('sort', '>=', 1), + orderBy('v') + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, [ + 'doc2', + 'doc4', + 'doc3', + 'doc5' + ]); + + // Ordered by: 'v asc, 'sort' asc, 'key' asc, __name__ asc + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '>', 'a'), + where('sort', '>=', 1), + orderBy('v'), + orderBy('sort') + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, [ + 'doc2', + 'doc5', + 'doc4', + 'doc3' + ]); + + // Implicit order by matches the direction of last explicit order by. + // Ordered by: 'v' desc, 'key' desc, 'sort' desc, __name__ desc + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '>', 'a'), + where('sort', '>=', 1), + orderBy('v', 'desc') + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, [ + 'doc5', + 'doc3', + 'doc4', + 'doc2' + ]); + + // Ordered by: 'v desc, 'sort' asc, 'key' asc, __name__ asc + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('key', '>', 'a'), + where('sort', '>=', 1), + orderBy('v', 'desc'), + orderBy('sort') + ) + ); + testHelper.assertSnapshotResultIdsMatch(snapshot, [ + 'doc5', + 'doc4', + 'doc3', + 'doc2' + ]); + }); + }); + + it('can use in aggregate query', async () => { + const testDocs = { + doc1: { key: 'a', sort: 5, v: 0 }, + doc2: { key: 'aa', sort: 4, v: 0 }, + doc3: { key: 'b', sort: 3, v: 1 }, + doc4: { key: 'b', sort: 2, v: 1 }, + doc5: { key: 'bb', sort: 1, v: 1 } + }; + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestDocs(persistence, testDocs, async coll => { + const snapshot1 = await getCountFromServer( + testHelper.query( + coll, + where('key', '>', 'a'), + where('sort', '>=', 1), + orderBy('v') + ) + ); + + expect(snapshot1.data().count).to.equal(4); + + const snapshot2 = await getAggregateFromServer( + testHelper.query( + coll, + where('key', '>', 'a'), + where('sort', '>=', 1), + where('v', '!=', 0) + ), + { + count: count(), + sum: sum('sort'), + avg: average('v') + } + ); + expect(snapshot2.data().count).to.equal(3); + expect(snapshot2.data().sum).to.equal(6); + expect(snapshot2.data().avg).to.equal(1); + }); + }); + + it('can use document ID im multiple inequality query', () => { + const testDocs = { + doc1: { key: 'a', sort: 5 }, + doc2: { key: 'aa', sort: 4 }, + doc3: { key: 'b', sort: 3 }, + doc4: { key: 'b', sort: 2 }, + doc5: { key: 'bb', sort: 1 } + }; + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestDocs(persistence, testDocs, async coll => { + let snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where('sort', '>=', 1), + where('key', '!=', 'a'), + where(documentId(), '<', 'doc5') + ) + ); + // Document Key in inequality field will implicitly ordered to the last. + // Implicitly ordered by: 'key' asc, 'sort' asc, __name__ asc + testHelper.assertSnapshotResultIdsMatch(snapshot, [ + 'doc2', + 'doc4', + 'doc3' + ]); + + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where(documentId(), '<', 'doc5'), + where('sort', '>=', 1), + where('key', '!=', 'a') + ) + ); + // Changing filters order will not effect implicit order. + // Implicitly ordered by: 'key' asc, 'sort' asc, __name__ asc + testHelper.assertSnapshotResultIdsMatch(snapshot, [ + 'doc2', + 'doc4', + 'doc3' + ]); + + snapshot = await testHelper.getDocs( + testHelper.query( + coll, + where(documentId(), '<', 'doc5'), + where('sort', '>=', 1), + where('key', '!=', 'a'), + orderBy('sort', 'desc') + ) + ); + // Ordered by: 'sort' desc,'key' desc, __name__ desc + testHelper.assertSnapshotResultIdsMatch(snapshot, [ + 'doc2', + 'doc3', + 'doc4' + ]); + }); + }); + + it('can get documents while offline', () => { + const testDocs = { + doc1: { key: 'a', sort: 1 }, + doc2: { key: 'aa', sort: 4 }, + doc3: { key: 'b', sort: 3 }, + doc4: { key: 'b', sort: 2 } + }; + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestDocs( + persistence.toLruGc(), + testDocs, + async (coll, db) => { + const query_ = testHelper.query( + coll, + where('key', '!=', 'a'), + where('sort', '<=', 3) + ); + //populate the cache. + const snapshot1 = await testHelper.getDocs(query_); + expect(snapshot1.size).to.equal(2); + + await disableNetwork(db); + + const snapshot2 = await testHelper.getDocs(query_); + expect(snapshot2.metadata.fromCache).to.be.true; + expect(snapshot2.metadata.hasPendingWrites).to.be.false; + // Implicitly ordered by: 'key' asc, 'sort' asc, __name__ asc + testHelper.assertSnapshotResultIdsMatch(snapshot2, ['doc4', 'doc3']); + } + ); + }); + + // eslint-disable-next-line no-restricted-properties + (persistence.gc === 'lru' ? it : it.skip)( + 'can get same result from server and cache', + () => { + const testDocs = { + doc1: { a: 1, b: 0 }, + doc2: { a: 2, b: 1 }, + doc3: { a: 3, b: 2 }, + doc4: { a: 1, b: 3 }, + doc5: { a: 1, b: 1 } + }; + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestDocs(persistence, testDocs, async coll => { + // implicit AND: a != 1 && b < 2 + await testHelper.assertOnlineAndOfflineResultsMatch( + testHelper.query(coll, where('a', '!=', 1), where('b', '<', 2)), + 'doc2' + ); + + // explicit AND: a != 1 && b < 2 + await testHelper.assertOnlineAndOfflineResultsMatch( + testHelper.compositeQuery( + coll, + and(where('a', '!=', 1), where('b', '<', 2)) + ), + 'doc2' + ); + + // explicit AND: a < 3 && b not-in [2, 3] + // Implicitly ordered by: a asc, b asc, __name__ asc + await testHelper.assertOnlineAndOfflineResultsMatch( + testHelper.compositeQuery( + coll, + and(where('a', '<', 3), where('b', 'not-in', [2, 3])) + ), + 'doc1', + 'doc5', + 'doc2' + ); + + // a <3 && b != 0, implicitly ordered by: a asc, b asc, __name__ asc + await testHelper.assertOnlineAndOfflineResultsMatch( + testHelper.query( + coll, + where('b', '!=', 0), + where('a', '<', 3), + limit(2) + ), + 'doc5', + 'doc4' + ); + + // a <3 && b != 0, ordered by: b desc, a desc, __name__ desc + await testHelper.assertOnlineAndOfflineResultsMatch( + testHelper.query( + coll, + where('a', '<', 3), + where('b', '!=', 0), + orderBy('b', 'desc'), + limit(2) + ), + 'doc4', + 'doc2' + ); + + // explicit OR: multiple inequality: a>2 || b<1. + await testHelper.assertOnlineAndOfflineResultsMatch( + testHelper.compositeQuery( + coll, + or(where('a', '>', 2), where('b', '<', 1)) + ), + 'doc1', + 'doc3' + ); + }); + } + ); + + it('inequality query will reject if document key is not the last orderBy field', () => { + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestCollection(persistence, async coll => { + // Implicitly ordered by: __name__ asc, 'key' asc, + const queryForRejection = testHelper.query( + coll, + where('key', '!=', 42), + orderBy(documentId()) + ); + + await expect( + testHelper.getDocs(queryForRejection) + ).to.be.eventually.rejectedWith( + /order by clause cannot contain more fields after the key/i + ); + }); + }); + + it('inequality query will reject if document key appears only in equality filter', () => { + const testHelper = new CompositeIndexTestHelper(); + return testHelper.withTestCollection(persistence, async coll => { + const query_ = testHelper.query( + coll, + where('key', '!=', 42), + where(documentId(), '==', 'doc1') + ); + await expect(testHelper.getDocs(query_)).to.be.eventually.rejectedWith( + 'Equality on key is not allowed if there are other inequality fields and key does not appear in inequalities.' + ); + }); + }); + }); }); diff --git a/packages/firestore/test/integration/api/query.test.ts b/packages/firestore/test/integration/api/query.test.ts index 7f1d10dd7c1..7bb8d70c193 100644 --- a/packages/firestore/test/integration/api/query.test.ts +++ b/packages/firestore/test/integration/api/query.test.ts @@ -23,11 +23,9 @@ import { EventsAccumulator } from '../util/events_accumulator'; import { addDoc, and, - average, Bytes, collection, collectionGroup, - count, deleteDoc, disableNetwork, doc, @@ -38,10 +36,7 @@ import { enableNetwork, endAt, endBefore, - FieldPath, GeoPoint, - getAggregateFromServer, - getCountFromServer, getDocs, limit, limitToLast, @@ -53,7 +48,6 @@ import { setDoc, startAfter, startAt, - sum, Timestamp, updateDoc, where, @@ -67,7 +61,6 @@ import { RetryError, toChangesArray, toDataArray, - toIds, PERSISTENCE_MODE_UNSPECIFIED, withEmptyTestCollection, withRetry, @@ -1347,604 +1340,6 @@ apiDescribe('Queries', persistence => { }); }); - // eslint-disable-next-line no-restricted-properties - (USE_EMULATOR ? describe : describe.skip)('Multiple Inequality', () => { - it('can use multiple inequality filters', async () => { - const testDocs = { - doc1: { key: 'a', sort: 0, v: 0 }, - doc2: { key: 'b', sort: 3, v: 1 }, - doc3: { key: 'c', sort: 1, v: 3 }, - doc4: { key: 'd', sort: 2, v: 2 } - }; - return withTestCollection(persistence, testDocs, async coll => { - // Multiple inequality fields - const snapshot1 = await getDocs( - query( - coll, - where('key', '!=', 'a'), - where('sort', '<=', 2), - where('v', '>', 2) - ) - ); - expect(toIds(snapshot1)).to.deep.equal(['doc3']); - - // Duplicate inequality fields - const snapshot2 = await getDocs( - query( - coll, - where('key', '!=', 'a'), - where('sort', '<=', 2), - where('sort', '>', 1) - ) - ); - expect(toIds(snapshot2)).to.deep.equal(['doc4']); - - // With multiple IN - const snapshot3 = await getDocs( - query( - coll, - where('key', '>=', 'a'), - where('sort', '<=', 2), - where('v', 'in', [2, 3, 4]), - where('sort', 'in', [2, 3]) - ) - ); - expect(toIds(snapshot3)).to.deep.equal(['doc4']); - - // With NOT-IN - const snapshot4 = await getDocs( - query( - coll, - where('key', '>=', 'a'), - where('sort', '<=', 2), - where('v', 'not-in', [2, 4, 5]) - ) - ); - expect(toIds(snapshot4)).to.deep.equal(['doc1', 'doc3']); - - // With orderby - const snapshot5 = await getDocs( - query( - coll, - where('key', '>=', 'a'), - where('sort', '<=', 2), - orderBy('v', 'desc') - ) - ); - expect(toIds(snapshot5)).to.deep.equal(['doc3', 'doc4', 'doc1']); - - // With limit - const snapshot6 = await getDocs( - query( - coll, - where('key', '>=', 'a'), - where('sort', '<=', 2), - orderBy('v', 'desc'), - limit(2) - ) - ); - expect(toIds(snapshot6)).to.deep.equal(['doc3', 'doc4']); - - // With limitToLast - const snapshot7 = await getDocs( - query( - coll, - where('key', '>=', 'a'), - where('sort', '<=', 2), - orderBy('v', 'desc'), - limitToLast(2) - ) - ); - expect(toIds(snapshot7)).to.deep.equal(['doc4', 'doc1']); - }); - }); - - it('can use on special values', async () => { - const testDocs = { - doc1: { key: 'a', sort: 0, v: 0 }, - doc2: { key: 'b', sort: NaN, v: 1 }, - doc3: { key: 'c', sort: null, v: 3 }, - doc4: { key: 'd', v: 0 }, - doc5: { key: 'e', sort: 1 }, - doc6: { key: 'f', sort: 1, v: 1 } - }; - return withTestCollection(persistence, testDocs, async coll => { - const snapshot1 = await getDocs( - query(coll, where('key', '!=', 'a'), where('sort', '<=', 2)) - ); - expect(toIds(snapshot1)).to.deep.equal(['doc5', 'doc6']); - - const snapshot2 = await getDocs( - query( - coll, - where('key', '!=', 'a'), - where('sort', '<=', 2), - where('v', '<=', 1) - ) - ); - expect(toIds(snapshot2)).to.deep.equal(['doc6']); - }); - }); - it('can use with array membership', async () => { - const testDocs = { - doc1: { key: 'a', sort: 0, v: [0] }, - doc2: { key: 'b', sort: 1, v: [0, 1, 3] }, - doc3: { key: 'c', sort: 1, v: [] }, - doc4: { key: 'd', sort: 2, v: [1] }, - doc5: { key: 'e', sort: 3, v: [2, 4] }, - doc6: { key: 'f', sort: 4, v: [NaN] }, - doc7: { key: 'g', sort: 4, v: [null] } - }; - return withTestCollection(persistence, testDocs, async coll => { - const snapshot1 = await getDocs( - query( - coll, - where('key', '!=', 'a'), - where('sort', '>=', 1), - where('v', 'array-contains', 0) - ) - ); - expect(toIds(snapshot1)).to.deep.equal(['doc2']); - - const snapshot2 = await getDocs( - query( - coll, - where('key', '!=', 'a'), - where('sort', '>=', 1), - where('v', 'array-contains-any', [0, 1]) - ) - ); - expect(toIds(snapshot2)).to.deep.equal(['doc2', 'doc4']); - }); - }); - - it('can use with nested field', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const testData = (n?: number): any => { - n = n || 1; - return { - name: 'room ' + n, - metadata: { - createdAt: n - }, - field: 'field ' + n, - 'field.dot': n, - 'field\\slash': n - }; - }; - - const testDocs = { - 'doc1': testData(400), - 'doc2': testData(200), - 'doc3': testData(100), - 'doc4': testData(300) - }; - - return withTestCollection(persistence, testDocs, async coll => { - const snapshot1 = await getDocs( - query( - coll, - where('metadata.createdAt', '<=', 500), - where('metadata.createdAt', '>', 100), - where('name', '!=', 'room 200'), - orderBy('name') - ) - ); - expect(toIds(snapshot1)).to.deep.equal(['doc4', 'doc1']); - - const snapshot2 = await getDocs( - query( - coll, - where('field', '>=', 'field 100'), - where(new FieldPath('field.dot'), '!=', 300), - where('field\\slash', '<', 400), - orderBy('name', 'desc') - ) - ); - expect(toIds(snapshot2)).to.deep.equal(['doc2', 'doc3']); - }); - }); - - it('can use with nested composite filters', async () => { - const testDocs = { - doc1: { key: 'a', sort: 0, v: 5 }, - doc2: { key: 'aa', sort: 4, v: 4 }, - doc3: { key: 'c', sort: 3, v: 3 }, - doc4: { key: 'b', sort: 2, v: 2 }, - doc5: { key: 'b', sort: 2, v: 1 }, - doc6: { key: 'b', sort: 0, v: 0 } - }; - return withTestCollection(persistence, testDocs, async coll => { - const snapshot1 = await getDocs( - query( - coll, - or( - and(where('key', '==', 'b'), where('sort', '<=', 2)), - and(where('key', '!=', 'b'), where('v', '>', 4)) - ) - ) - ); - // Implicitly ordered by: 'key' asc, 'sort' asc, 'v' asc, __name__ asc - expect(toIds(snapshot1)).to.deep.equal([ - 'doc1', - 'doc6', - 'doc5', - 'doc4' - ]); - - const snapshot2 = await getDocs( - query( - coll, - or( - and(where('key', '==', 'b'), where('sort', '<=', 2)), - and(where('key', '!=', 'b'), where('v', '>', 4)) - ), - orderBy('sort', 'desc'), - orderBy('key') - ) - ); - // Ordered by: 'sort' desc, 'key' asc, 'v' asc, __name__ asc - expect(toIds(snapshot2)).to.deep.equal([ - 'doc5', - 'doc4', - 'doc1', - 'doc6' - ]); - - const snapshot3 = await getDocs( - query( - coll, - and( - or( - and(where('key', '==', 'b'), where('sort', '<=', 4)), - and(where('key', '!=', 'b'), where('v', '>=', 4)) - ), - or( - and(where('key', '>', 'b'), where('sort', '>=', 1)), - and(where('key', '<', 'b'), where('v', '>', 0)) - ) - ) - ) - ); - // Implicitly ordered by: 'key' asc, 'sort' asc, 'v' asc, __name__ asc - expect(toIds(snapshot3)).to.deep.equal(['doc1', 'doc2']); - }); - }); - - it('inequality fields will be implicitly ordered lexicographically', async () => { - const testDocs = { - doc1: { key: 'a', sort: 0, v: 5 }, - doc2: { key: 'aa', sort: 4, v: 4 }, - doc3: { key: 'b', sort: 3, v: 3 }, - doc4: { key: 'b', sort: 2, v: 2 }, - doc5: { key: 'b', sort: 2, v: 1 }, - doc6: { key: 'b', sort: 0, v: 0 } - }; - return withTestCollection(persistence, testDocs, async coll => { - // Implicitly ordered by: 'key' asc, 'sort' asc, __name__ asc - const snapshot1 = await getDocs( - query( - coll, - where('key', '!=', 'a'), - where('sort', '>', 1), - where('v', 'in', [1, 2, 3, 4]) - ) - ); - expect(toIds(snapshot1)).to.deep.equal([ - 'doc2', - 'doc4', - 'doc5', - 'doc3' - ]); - - // Implicitly ordered by: 'key' asc, 'sort' asc,__name__ asc - const snapshot2 = await getDocs( - query( - coll, - where('sort', '>', 1), - where('key', '!=', 'a'), - where('v', 'in', [1, 2, 3, 4]) - ) - ); - expect(toIds(snapshot2)).to.deep.equal([ - 'doc2', - 'doc4', - 'doc5', - 'doc3' - ]); - }); - }); - - it('can use multiple explicit order by field', async () => { - const testDocs = { - doc1: { key: 'a', sort: 5, v: 0 }, - doc2: { key: 'aa', sort: 4, v: 0 }, - doc3: { key: 'b', sort: 3, v: 1 }, - doc4: { key: 'b', sort: 2, v: 1 }, - doc5: { key: 'bb', sort: 1, v: 1 }, - doc6: { key: 'c', sort: 0, v: 2 } - }; - - return withTestCollection(persistence, testDocs, async coll => { - // Ordered by: 'v' asc, 'key' asc, 'sort' asc, __name__ asc - const snapshot1 = await getDocs( - query( - coll, - where('key', '>', 'a'), - where('sort', '>=', 1), - orderBy('v') - ) - ); - expect(toIds(snapshot1)).to.deep.equal([ - 'doc2', - 'doc4', - 'doc3', - 'doc5' - ]); - - // Ordered by: 'v asc, 'sort' asc, 'key' asc, __name__ asc - const snapshot2 = await getDocs( - query( - coll, - where('key', '>', 'a'), - where('sort', '>=', 1), - orderBy('v'), - orderBy('sort') - ) - ); - expect(toIds(snapshot2)).to.deep.equal([ - 'doc2', - 'doc5', - 'doc4', - 'doc3' - ]); - - // Implicit order by matches the direction of last explicit order by. - // Ordered by: 'v' desc, 'key' desc, 'sort' desc, __name__ desc - const snapshot3 = await getDocs( - query( - coll, - where('key', '>', 'a'), - where('sort', '>=', 1), - orderBy('v', 'desc') - ) - ); - expect(toIds(snapshot3)).to.deep.equal([ - 'doc5', - 'doc3', - 'doc4', - 'doc2' - ]); - - // Ordered by: 'v desc, 'sort' asc, 'key' asc, __name__ asc - const snapshot4 = await getDocs( - query( - coll, - where('key', '>', 'a'), - where('sort', '>=', 1), - orderBy('v', 'desc'), - orderBy('sort') - ) - ); - expect(toIds(snapshot4)).to.deep.equal([ - 'doc5', - 'doc4', - 'doc3', - 'doc2' - ]); - }); - }); - - it('can use in aggregate query', async () => { - const testDocs = { - doc1: { key: 'a', sort: 5, v: 0 }, - doc2: { key: 'aa', sort: 4, v: 0 }, - doc3: { key: 'b', sort: 3, v: 1 }, - doc4: { key: 'b', sort: 2, v: 1 }, - doc5: { key: 'bb', sort: 1, v: 1 } - }; - - return withTestCollection(persistence, testDocs, async coll => { - const snapshot1 = await getCountFromServer( - query( - coll, - where('key', '>', 'a'), - where('sort', '>=', 1), - orderBy('v') - ) - ); - expect(snapshot1.data().count).to.equal(4); - - const snapshot2 = await getAggregateFromServer( - query( - coll, - where('key', '>', 'a'), - where('sort', '>=', 1), - where('v', '!=', 0) - ), - { - count: count(), - sum: sum('sort'), - avg: average('v') - } - ); - expect(snapshot2.data().count).to.equal(3); - expect(snapshot2.data().sum).to.equal(6); - expect(snapshot2.data().avg).to.equal(1); - }); - }); - - it('can use document ID im multiple inequality query', () => { - const testDocs = { - doc1: { key: 'a', sort: 5 }, - doc2: { key: 'aa', sort: 4 }, - doc3: { key: 'b', sort: 3 }, - doc4: { key: 'b', sort: 2 }, - doc5: { key: 'bb', sort: 1 } - }; - return withTestCollection(persistence, testDocs, async coll => { - const snapshot1 = await getDocs( - query( - coll, - where('sort', '>=', 1), - where('key', '!=', 'a'), - where(documentId(), '<', 'doc5') - ) - ); - // Document Key in inequality field will implicitly ordered to the last. - // Implicitly ordered by: 'key' asc, 'sort' asc, __name__ asc - expect(toIds(snapshot1)).to.deep.equal(['doc2', 'doc4', 'doc3']); - - const snapshot2 = await getDocs( - query( - coll, - where(documentId(), '<', 'doc5'), - where('sort', '>=', 1), - where('key', '!=', 'a') - ) - ); - // Changing filters order will not effect implicit order. - // Implicitly ordered by: 'key' asc, 'sort' asc, __name__ asc - expect(toIds(snapshot2)).to.deep.equal(['doc2', 'doc4', 'doc3']); - - const snapshot3 = await getDocs( - query( - coll, - where(documentId(), '<', 'doc5'), - where('sort', '>=', 1), - where('key', '!=', 'a'), - orderBy('sort', 'desc') - ) - ); - // Ordered by: 'sort' desc,'key' desc, __name__ desc - expect(toIds(snapshot3)).to.deep.equal(['doc2', 'doc3', 'doc4']); - }); - }); - - it('can get documents while offline', () => { - const testDocs = { - doc1: { key: 'a', sort: 1 }, - doc2: { key: 'aa', sort: 4 }, - doc3: { key: 'b', sort: 3 }, - doc4: { key: 'b', sort: 2 } - }; - return withTestCollection( - persistence.toLruGc(), - testDocs, - async (coll, db) => { - const query_ = query( - coll, - where('key', '!=', 'a'), - where('sort', '<=', 3) - ); - //populate the cache. - const snapshot1 = await getDocs(query_); - expect(snapshot1.size).to.equal(2); - - await disableNetwork(db); - - const snapshot2 = await getDocs(query_); - expect(snapshot2.metadata.fromCache).to.be.true; - expect(snapshot2.metadata.hasPendingWrites).to.be.false; - // Implicitly ordered by: 'key' asc, 'sort' asc, __name__ asc - expect(toIds(snapshot2)).to.deep.equal(['doc4', 'doc3']); - } - ); - }); - - // eslint-disable-next-line no-restricted-properties - (persistence.gc === 'lru' ? it : it.skip)( - 'can get same result from server and cache', - () => { - const testDocs = { - doc1: { a: 1, b: 0 }, - doc2: { a: 2, b: 1 }, - doc3: { a: 3, b: 2 }, - doc4: { a: 1, b: 3 }, - doc5: { a: 1, b: 1 } - }; - - return withTestCollection(persistence, testDocs, async coll => { - // implicit AND: a != 1 && b < 2 - await checkOnlineAndOfflineResultsMatch( - query(coll, where('a', '!=', 1), where('b', '<', 2)), - 'doc2' - ); - - // explicit AND: a != 1 && b < 2 - await checkOnlineAndOfflineResultsMatch( - query(coll, and(where('a', '!=', 1), where('b', '<', 2))), - 'doc2' - ); - - // explicit AND: a < 3 && b not-in [2, 3] - // Implicitly ordered by: a asc, b asc, __name__ asc - await checkOnlineAndOfflineResultsMatch( - query(coll, and(where('a', '<', 3), where('b', 'not-in', [2, 3]))), - 'doc1', - 'doc5', - 'doc2' - ); - - // a <3 && b != 0, implicitly ordered by: a asc, b asc, __name__ asc - await checkOnlineAndOfflineResultsMatch( - query(coll, where('b', '!=', 0), where('a', '<', 3), limit(2)), - 'doc5', - 'doc4' - ); - - // a <3 && b != 0, ordered by: b desc, a desc, __name__ desc - await checkOnlineAndOfflineResultsMatch( - query( - coll, - where('a', '<', 3), - where('b', '!=', 0), - orderBy('b', 'desc'), - limit(2) - ), - 'doc4', - 'doc2' - ); - - // explicit OR: multiple inequality: a>2 || b<1. - await checkOnlineAndOfflineResultsMatch( - query(coll, or(where('a', '>', 2), where('b', '<', 1))), - 'doc1', - 'doc3' - ); - }); - } - ); - - it('inequality query will reject if document key is not the last orderBy field', () => { - return withEmptyTestCollection(persistence, async coll => { - // Implicitly ordered by: __name__ asc, 'key' asc, - const queryForRejection = query( - coll, - where('key', '!=', 42), - orderBy(documentId()) - ); - - await expect(getDocs(queryForRejection)).to.be.eventually.rejectedWith( - 'order by clause cannot contain more fields after the key' - ); - }); - }); - - it('inequality query will reject if document key appears only in equality filter', () => { - return withEmptyTestCollection(persistence, async coll => { - const query_ = query( - coll, - where('key', '!=', 42), - where(documentId(), '==', 'doc1') - ); - await expect(getDocs(query_)).to.be.eventually.rejectedWith( - 'Equality on key is not allowed if there are other inequality fields and key does not appear in inequalities.' - ); - }); - }); - }); - // OR Query tests only run when the SDK's local cache is configured to use // LRU garbage collection (rather than eager garbage collection) because // they validate that the result from server and cache match. @@ -2937,7 +2332,7 @@ apiDescribe('Hanging query issue - #7652', persistence => { } }); -function verifyDocumentChange( +export function verifyDocumentChange( change: DocumentChange, id: string, oldIndex: number, diff --git a/packages/firestore/test/integration/api/snasphot_listener_source.test.ts b/packages/firestore/test/integration/api/snasphot_listener_source.test.ts new file mode 100644 index 00000000000..39a93d61912 --- /dev/null +++ b/packages/firestore/test/integration/api/snasphot_listener_source.test.ts @@ -0,0 +1,786 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'chai'; + +import { EventsAccumulator } from '../util/events_accumulator'; +import { + addDoc, + disableNetwork, + doc, + DocumentSnapshot, + enableNetwork, + getDoc, + getDocs, + limit, + limitToLast, + onSnapshot, + orderBy, + query, + QuerySnapshot, + runTransaction, + updateDoc, + where +} from '../util/firebase_export'; +import { + apiDescribe, + toDataArray, + withTestCollection, + withTestDocAndInitialData +} from '../util/helpers'; + +apiDescribe('Snapshot Listener source options ', persistence => { + // eslint-disable-next-line no-restricted-properties + (persistence.gc === 'lru' ? describe : describe.skip)( + 'listen to persistence cache', + () => { + it('can raise snapshot from cache for Query', () => { + const testDocs = { + a: { k: 'a' } + }; + return withTestCollection(persistence, testDocs, async coll => { + await getDocs(coll); // Populate the cache. + + const storeEvent = new EventsAccumulator(); + const unsubscribe = onSnapshot( + coll, + { source: 'cache' }, + storeEvent.storeEvent + ); + + const snapshot = await storeEvent.awaitEvent(); + expect(snapshot.metadata.fromCache).to.equal(true); + expect(toDataArray(snapshot)).to.deep.equal([{ k: 'a' }]); + + await storeEvent.assertNoAdditionalEvents(); + unsubscribe(); + }); + }); + + it('can raise snapshot from cache for DocumentReference', () => { + const testDocs = { k: 'a' }; + return withTestDocAndInitialData( + persistence, + testDocs, + async docRef => { + await getDoc(docRef); // Populate the cache. + + const storeEvent = new EventsAccumulator(); + const unsubscribe = onSnapshot( + docRef, + { source: 'cache' }, + storeEvent.storeEvent + ); + + const snapshot = await storeEvent.awaitEvent(); + expect(snapshot.metadata.fromCache).to.equal(true); + expect(snapshot.data()).to.deep.equal({ k: 'a' }); + + await storeEvent.assertNoAdditionalEvents(); + unsubscribe(); + } + ); + }); + + it('listen to cache would not be affected by online status change', () => { + const testDocs = { + a: { k: 'a' } + }; + return withTestCollection(persistence, testDocs, async (coll, db) => { + await getDocs(coll); // Populate the cache. + + const storeEvent = new EventsAccumulator(); + const unsubscribe = onSnapshot( + coll, + { includeMetadataChanges: true, source: 'cache' }, + storeEvent.storeEvent + ); + + const snapshot = await storeEvent.awaitEvent(); + expect(snapshot.metadata.fromCache).to.equal(true); + expect(toDataArray(snapshot)).to.deep.equal([{ k: 'a' }]); + + await disableNetwork(db); + await enableNetwork(db); + + await storeEvent.assertNoAdditionalEvents(); + unsubscribe(); + }); + }); + + it('multiple listeners sourced from cache can work independently', () => { + const testDocs = { + a: { k: 'a', sort: 0 }, + b: { k: 'b', sort: 1 } + }; + return withTestCollection(persistence, testDocs, async coll => { + await getDocs(coll); // Populate the cache. + const testQuery = query( + coll, + where('sort', '>', 0), + orderBy('sort', 'asc') + ); + + const storeEvent = new EventsAccumulator(); + const unsubscribe1 = onSnapshot( + testQuery, + { source: 'cache' }, + storeEvent.storeEvent + ); + + const unsubscribe2 = onSnapshot( + testQuery, + { source: 'cache' }, + storeEvent.storeEvent + ); + + let snapshots = await storeEvent.awaitEvents(2); + expect(toDataArray(snapshots[0])).to.deep.equal([ + { k: 'b', sort: 1 } + ]); + expect(snapshots[0].metadata).to.deep.equal(snapshots[1].metadata); + expect(toDataArray(snapshots[0])).to.deep.equal( + toDataArray(snapshots[1]) + ); + + await addDoc(coll, { k: 'c', sort: 2 }); + + snapshots = await storeEvent.awaitEvents(2); + expect(toDataArray(snapshots[0])).to.deep.equal([ + { k: 'b', sort: 1 }, + { k: 'c', sort: 2 } + ]); + expect(snapshots[0].metadata).to.deep.equal(snapshots[1].metadata); + expect(toDataArray(snapshots[0])).to.deep.equal( + toDataArray(snapshots[1]) + ); + + // Detach one listener, and do a local mutation. The other listener + // should not be affected. + unsubscribe1(); + + await addDoc(coll, { k: 'd', sort: 3 }); + + const snapshot = await storeEvent.awaitEvent(); + expect(snapshot.metadata.fromCache).to.equal(true); + expect(toDataArray(snapshot)).to.deep.equal([ + { k: 'b', sort: 1 }, + { k: 'c', sort: 2 }, + { k: 'd', sort: 3 } + ]); + await storeEvent.assertNoAdditionalEvents(); + unsubscribe2(); + }); + }); + + // Two queries that mapped to the same target ID are referred to as + // "mirror queries". An example for a mirror query is a limitToLast() + // query and a limit() query that share the same backend Target ID. + // Since limitToLast() queries are sent to the backend with a modified + // orderBy() clause, they can map to the same target representation as + // limit() query, even if both queries appear separate to the user. + it('can listen/un-listen/re-listen to mirror queries from cache', () => { + const testDocs = { + a: { k: 'a', sort: 0 }, + b: { k: 'b', sort: 1 }, + c: { k: 'c', sort: 1 } + }; + return withTestCollection(persistence, testDocs, async coll => { + await getDocs(coll); // Populate the cache. + + // Setup `limit` query + const storeLimitEvent = new EventsAccumulator(); + let limitUnlisten = onSnapshot( + query(coll, orderBy('sort', 'asc'), limit(2)), + { source: 'cache' }, + storeLimitEvent.storeEvent + ); + + // Setup mirroring `limitToLast` query + const storeLimitToLastEvent = new EventsAccumulator(); + let limitToLastUnlisten = onSnapshot( + query(coll, orderBy('sort', 'desc'), limitToLast(2)), + { source: 'cache' }, + storeLimitToLastEvent.storeEvent + ); + + // Verify both queries get expected results. + let snapshot = await storeLimitEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal([ + { k: 'a', sort: 0 }, + { k: 'b', sort: 1 } + ]); + snapshot = await storeLimitToLastEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal([ + { k: 'b', sort: 1 }, + { k: 'a', sort: 0 } + ]); + + // Un-listen then re-listen to the limit query. + limitUnlisten(); + limitUnlisten = onSnapshot( + query(coll, orderBy('sort', 'asc'), limit(2)), + { source: 'cache' }, + storeLimitEvent.storeEvent + ); + snapshot = await storeLimitEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal([ + { k: 'a', sort: 0 }, + { k: 'b', sort: 1 } + ]); + expect(snapshot.metadata.fromCache).to.equal(true); + + // Add a document that would change the result set. + await addDoc(coll, { k: 'd', sort: -1 }); + + // Verify both queries get expected results. + snapshot = await storeLimitEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal([ + { k: 'd', sort: -1 }, + { k: 'a', sort: 0 } + ]); + expect(snapshot.metadata.hasPendingWrites).to.equal(true); + + snapshot = await storeLimitToLastEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal([ + { k: 'a', sort: 0 }, + { k: 'd', sort: -1 } + ]); + expect(snapshot.metadata.hasPendingWrites).to.equal(true); + + // Un-listen to limitToLast, update a doc, then re-listen limitToLast. + limitToLastUnlisten(); + + await updateDoc(doc(coll, 'a'), { k: 'a', sort: -2 }); + limitToLastUnlisten = onSnapshot( + query(coll, orderBy('sort', 'desc'), limitToLast(2)), + { source: 'cache' }, + storeLimitToLastEvent.storeEvent + ); + + // Verify both queries get expected results. + snapshot = await storeLimitEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal([ + { k: 'a', sort: -2 }, + { k: 'd', sort: -1 } + ]); + expect(snapshot.metadata.hasPendingWrites).to.equal(true); + + snapshot = await storeLimitToLastEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal([ + { k: 'd', sort: -1 }, + { k: 'a', sort: -2 } + ]); + // We listened to LimitToLast query after the doc update. + expect(snapshot.metadata.hasPendingWrites).to.equal(false); + + limitUnlisten(); + limitToLastUnlisten(); + }); + }); + + it('can listen to default source first and then cache', () => { + const testDocs = { + a: { k: 'a', sort: 0 }, + b: { k: 'b', sort: 1 } + }; + return withTestCollection(persistence, testDocs, async coll => { + // Listen to the query with default options, which will also populates the cache + const storeDefaultEvent = new EventsAccumulator(); + const testQuery = query( + coll, + where('sort', '>=', 1), + orderBy('sort', 'asc') + ); + + const defaultUnlisten = onSnapshot( + testQuery, + storeDefaultEvent.storeEvent + ); + let snapshot = await storeDefaultEvent.awaitRemoteEvent(); + expect(toDataArray(snapshot)).to.deep.equal([{ k: 'b', sort: 1 }]); + expect(snapshot.metadata.fromCache).to.equal(false); + + // Listen to the same query from cache + const storeCacheEvent = new EventsAccumulator(); + const cacheUnlisten = onSnapshot( + testQuery, + { source: 'cache' }, + storeCacheEvent.storeEvent + ); + snapshot = await storeCacheEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal([{ k: 'b', sort: 1 }]); + // The metadata is sync with server due to the default listener + expect(snapshot.metadata.fromCache).to.equal(false); + + await storeDefaultEvent.assertNoAdditionalEvents(); + await storeCacheEvent.assertNoAdditionalEvents(); + + defaultUnlisten(); + cacheUnlisten(); + }); + }); + + it('can listen to cache source first and then default', () => { + const testDocs = { + a: { k: 'a', sort: 0 }, + b: { k: 'b', sort: 1 } + }; + return withTestCollection(persistence, testDocs, async coll => { + // Listen to the cache + const storeCacheEvent = new EventsAccumulator(); + const testQuery = query( + coll, + where('sort', '!=', 0), + orderBy('sort', 'asc') + ); + + const cacheUnlisten = onSnapshot( + testQuery, + { source: 'cache' }, + storeCacheEvent.storeEvent + ); + let snapshot = await storeCacheEvent.awaitEvent(); + // Cache is empty + expect(toDataArray(snapshot)).to.deep.equal([]); + expect(snapshot.metadata.fromCache).to.equal(true); + + // Listen to the same query from server + const storeDefaultEvent = new EventsAccumulator(); + const defaultUnlisten = onSnapshot( + testQuery, + storeDefaultEvent.storeEvent + ); + snapshot = await storeDefaultEvent.awaitEvent(); + const expectedData = [{ k: 'b', sort: 1 }]; + expect(toDataArray(snapshot)).to.deep.equal(expectedData); + expect(snapshot.metadata.fromCache).to.equal(false); + + // Default listener updates the cache, which triggers cache listener to raise snapshot. + snapshot = await storeCacheEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal(expectedData); + // The metadata is sync with server due to the default listener + expect(snapshot.metadata.fromCache).to.equal(false); + + await storeDefaultEvent.assertNoAdditionalEvents(); + await storeCacheEvent.assertNoAdditionalEvents(); + + defaultUnlisten(); + cacheUnlisten(); + }); + }); + + it('will not get metadata only updates if listening to cache only', () => { + const testDocs = { + a: { k: 'a', sort: 0 }, + b: { k: 'b', sort: 1 } + }; + return withTestCollection(persistence, testDocs, async coll => { + await getDocs(coll); // Populate the cache. + const testQuery = query( + coll, + where('sort', '!=', 0), + orderBy('sort', 'asc') + ); + + const storeEvent = new EventsAccumulator(); + const unsubscribe = onSnapshot( + testQuery, + { includeMetadataChanges: true, source: 'cache' }, + storeEvent.storeEvent + ); + + let snapshot = await storeEvent.awaitEvent(); + expect(snapshot.metadata.fromCache).to.equal(true); + expect(toDataArray(snapshot)).to.deep.equal([{ k: 'b', sort: 1 }]); + + await addDoc(coll, { k: 'c', sort: 2 }); + + snapshot = await storeEvent.awaitEvent(); + expect(snapshot.metadata.hasPendingWrites).to.equal(true); + expect(snapshot.metadata.fromCache).to.equal(true); + expect(toDataArray(snapshot)).to.deep.equal([ + { k: 'b', sort: 1 }, + { k: 'c', sort: 2 } + ]); + + // As we are not listening to server, the listener will not get notified + // when local mutation is acknowledged by server. + await storeEvent.assertNoAdditionalEvents(); + unsubscribe(); + }); + }); + + it('will have synced metadata updates when listening to both cache and default source', () => { + const testDocs = { + a: { k: 'a', sort: 0 }, + b: { k: 'b', sort: 1 } + }; + return withTestCollection(persistence, testDocs, async coll => { + await getDocs(coll); // Populate the cache. + const testQuery = query( + coll, + where('sort', '!=', 0), + orderBy('sort', 'asc') + ); + + // Listen to the query from cache + const storeCacheEvent = new EventsAccumulator(); + const cacheUnlisten = onSnapshot( + testQuery, + { includeMetadataChanges: true, source: 'cache' }, + storeCacheEvent.storeEvent + ); + let snapshot = await storeCacheEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal([{ k: 'b', sort: 1 }]); + expect(snapshot.metadata.fromCache).to.equal(true); + + // Listen to the same query from server + const storeDefaultEvent = new EventsAccumulator(); + const defaultUnlisten = onSnapshot( + testQuery, + { includeMetadataChanges: true }, + storeDefaultEvent.storeEvent + ); + snapshot = await storeDefaultEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal([{ k: 'b', sort: 1 }]); + // First snapshot will be raised from cache. + expect(snapshot.metadata.fromCache).to.equal(true); + snapshot = await storeDefaultEvent.awaitEvent(); + // Second snapshot will be raised from server result + expect(snapshot.metadata.fromCache).to.equal(false); + + // As listening to metadata changes, the cache listener also gets triggered and synced + // with default listener. + snapshot = await storeCacheEvent.awaitEvent(); + expect(snapshot.metadata.fromCache).to.equal(false); + + await addDoc(coll, { k: 'c', sort: 2 }); + + // snapshot gets triggered by local mutation + snapshot = await storeDefaultEvent.awaitEvent(); + const expectedData = [ + { k: 'b', sort: 1 }, + { k: 'c', sort: 2 } + ]; + expect(toDataArray(snapshot)).to.deep.equal(expectedData); + expect(snapshot.metadata.hasPendingWrites).to.equal(true); + expect(snapshot.metadata.fromCache).to.equal(false); + + snapshot = await storeCacheEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal(expectedData); + expect(snapshot.metadata.hasPendingWrites).to.equal(true); + expect(snapshot.metadata.fromCache).to.equal(false); + + // Local mutation gets acknowledged by the server + snapshot = await storeDefaultEvent.awaitEvent(); + expect(snapshot.metadata.hasPendingWrites).to.equal(false); + expect(snapshot.metadata.fromCache).to.equal(false); + + snapshot = await storeCacheEvent.awaitEvent(); + expect(snapshot.metadata.hasPendingWrites).to.equal(false); + expect(snapshot.metadata.fromCache).to.equal(false); + + cacheUnlisten(); + defaultUnlisten(); + }); + }); + + it('can un-listen to default source while still listening to cache', () => { + const testDocs = { + a: { k: 'a', sort: 0 }, + b: { k: 'b', sort: 1 } + }; + return withTestCollection(persistence, testDocs, async coll => { + const testQuery = query( + coll, + where('sort', '!=', 0), + orderBy('sort', 'asc') + ); + + // Listen to the query with both source options + const storeDefaultEvent = new EventsAccumulator(); + const defaultUnlisten = onSnapshot( + testQuery, + storeDefaultEvent.storeEvent + ); + await storeDefaultEvent.awaitEvent(); + const storeCacheEvent = new EventsAccumulator(); + const cacheUnlisten = onSnapshot( + testQuery, + { source: 'cache' }, + storeCacheEvent.storeEvent + ); + await storeCacheEvent.awaitEvent(); + + // Un-listen to the default listener. + defaultUnlisten(); + await storeDefaultEvent.assertNoAdditionalEvents(); + + // Add a document and verify listener to cache works as expected + await addDoc(coll, { k: 'c', sort: -1 }); + + const snapshot = await storeCacheEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal([ + { k: 'c', sort: -1 }, + { k: 'b', sort: 1 } + ]); + + await storeCacheEvent.assertNoAdditionalEvents(); + cacheUnlisten(); + }); + }); + + it('can un-listen to cache while still listening to server', () => { + const testDocs = { + a: { k: 'a', sort: 0 }, + b: { k: 'b', sort: 1 } + }; + return withTestCollection(persistence, testDocs, async coll => { + const testQuery = query( + coll, + where('sort', '!=', 0), + orderBy('sort', 'asc') + ); + + // Listen to the query with both source options + const storeDefaultEvent = new EventsAccumulator(); + const defaultUnlisten = onSnapshot( + testQuery, + storeDefaultEvent.storeEvent + ); + await storeDefaultEvent.awaitEvent(); + const storeCacheEvent = new EventsAccumulator(); + const cacheUnlisten = onSnapshot( + testQuery, + { source: 'cache' }, + storeCacheEvent.storeEvent + ); + await storeCacheEvent.awaitEvent(); + + // Un-listen to cache. + cacheUnlisten(); + await storeCacheEvent.assertNoAdditionalEvents(); + + // Add a document and verify listener to server works as expected. + await addDoc(coll, { k: 'c', sort: -1 }); + + const snapshot = await storeDefaultEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal([ + { k: 'c', sort: -1 }, + { k: 'b', sort: 1 } + ]); + + await storeDefaultEvent.assertNoAdditionalEvents(); + defaultUnlisten(); + }); + }); + + it('can listen/un-listen/re-listen to same query with different source options', () => { + const testDocs = { + a: { k: 'a', sort: 0 }, + b: { k: 'b', sort: 1 } + }; + return withTestCollection(persistence, testDocs, async coll => { + const testQuery = query( + coll, + where('sort', '>', 0), + orderBy('sort', 'asc') + ); + + // Listen to the query with default options, which also populates the cache + const storeDefaultEvent = new EventsAccumulator(); + let defaultUnlisten = onSnapshot( + testQuery, + storeDefaultEvent.storeEvent + ); + let snapshot = await storeDefaultEvent.awaitEvent(); + let expectedData = [{ k: 'b', sort: 1 }]; + expect(toDataArray(snapshot)).to.deep.equal(expectedData); + + // Listen to the same query from cache + const storeCacheEvent = new EventsAccumulator(); + let cacheUnlisten = onSnapshot( + testQuery, + { source: 'cache' }, + storeCacheEvent.storeEvent + ); + snapshot = await storeCacheEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal(expectedData); + + // Un-listen to the default listener, add a doc and re-listen. + defaultUnlisten(); + await addDoc(coll, { k: 'c', sort: 2 }); + + snapshot = await storeCacheEvent.awaitEvent(); + expectedData = [ + { k: 'b', sort: 1 }, + { k: 'c', sort: 2 } + ]; + expect(toDataArray(snapshot)).to.deep.equal(expectedData); + + defaultUnlisten = onSnapshot(testQuery, storeDefaultEvent.storeEvent); + snapshot = await storeDefaultEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal(expectedData); + + // Un-listen to cache, update a doc, then re-listen to cache. + cacheUnlisten(); + await updateDoc(doc(coll, 'b'), { k: 'b', sort: 3 }); + + snapshot = await storeDefaultEvent.awaitEvent(); + expectedData = [ + { k: 'c', sort: 2 }, + { k: 'b', sort: 3 } + ]; + expect(toDataArray(snapshot)).to.deep.equal(expectedData); + + cacheUnlisten = onSnapshot( + testQuery, + { source: 'cache' }, + storeCacheEvent.storeEvent + ); + + snapshot = await storeCacheEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal(expectedData); + + defaultUnlisten(); + cacheUnlisten(); + }); + }); + + it('can listen to composite index queries from cache', () => { + const testDocs = { + a: { k: 'a', sort: 0 }, + b: { k: 'b', sort: 1 } + }; + return withTestCollection(persistence, testDocs, async coll => { + await getDocs(coll); // Populate the cache. + + const testQuery = query( + coll, + where('k', '<=', 'a'), + where('sort', '>=', 0) + ); + const storeEvent = new EventsAccumulator(); + const unsubscribe = onSnapshot( + testQuery, + { source: 'cache' }, + storeEvent.storeEvent + ); + + const snapshot = await storeEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal([{ k: 'a', sort: 0 }]); + unsubscribe(); + }); + }); + + it('can raise initial snapshot from cache, even if it is empty', () => { + return withTestCollection(persistence, {}, async coll => { + let snapshot = await getDocs(coll); // Populate the cache. + expect(toDataArray(snapshot)).to.deep.equal([]); // Precondition check. + + const storeEvent = new EventsAccumulator(); + onSnapshot(coll, { source: 'cache' }, storeEvent.storeEvent); + snapshot = await storeEvent.awaitEvent(); + expect(snapshot.metadata.fromCache).to.be.true; + expect(toDataArray(snapshot)).to.deep.equal([]); + }); + }); + + it('will not be triggered by transactions while listening to cache', () => { + return withTestCollection(persistence, {}, async (coll, db) => { + const accumulator = new EventsAccumulator(); + const unsubscribe = onSnapshot( + coll, + { source: 'cache' }, + accumulator.storeEvent + ); + + const snapshot = await accumulator.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal([]); + + const docRef = doc(coll); + // Use a transaction to perform a write without triggering any local events. + await runTransaction(db, async txn => { + txn.set(docRef, { k: 'a' }); + }); + + // There should be no events raised + await accumulator.assertNoAdditionalEvents(); + unsubscribe(); + }); + }); + + it('share server side updates when listening to both cache and default', () => { + const testDocs = { + a: { k: 'a', sort: 0 }, + b: { k: 'b', sort: 1 } + }; + return withTestCollection(persistence, testDocs, async (coll, db) => { + const testQuery = query( + coll, + where('sort', '>', 0), + orderBy('sort', 'asc') + ); + + // Listen to the query with default options, which will also populates the cache + const storeDefaultEvent = new EventsAccumulator(); + const defaultUnlisten = onSnapshot( + testQuery, + storeDefaultEvent.storeEvent + ); + let snapshot = await storeDefaultEvent.awaitRemoteEvent(); + let expectedData = [{ k: 'b', sort: 1 }]; + expect(toDataArray(snapshot)).to.deep.equal(expectedData); + + // Listen to the same query from cache + const storeCacheEvent = new EventsAccumulator(); + const cacheUnlisten = onSnapshot( + testQuery, + { source: 'cache' }, + storeCacheEvent.storeEvent + ); + snapshot = await storeCacheEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal(expectedData); + + // Use a transaction to mock server side updates + const docRef = doc(coll); + await runTransaction(db, async txn => { + txn.set(docRef, { k: 'c', sort: 2 }); + }); + + // Default listener receives the server update + snapshot = await storeDefaultEvent.awaitRemoteEvent(); + expectedData = [ + { k: 'b', sort: 1 }, + { k: 'c', sort: 2 } + ]; + expect(toDataArray(snapshot)).to.deep.equal(expectedData); + expect(snapshot.metadata.fromCache).to.be.false; + + // Cache listener raises snapshot as well + snapshot = await storeCacheEvent.awaitEvent(); + expect(toDataArray(snapshot)).to.deep.equal(expectedData); + expect(snapshot.metadata.fromCache).to.be.false; + + defaultUnlisten(); + cacheUnlisten(); + }); + }); + } + ); +}); diff --git a/packages/firestore/test/integration/api/validation.test.ts b/packages/firestore/test/integration/api/validation.test.ts index 8260b53bb4f..eb0119b5d39 100644 --- a/packages/firestore/test/integration/api/validation.test.ts +++ b/packages/firestore/test/integration/api/validation.test.ts @@ -173,7 +173,7 @@ apiDescribe('Validation:', persistence => { () => { const db = newTestFirestore(newTestApp('test-project')); // Verify that this doesn't throw. - connectFirestoreEmulator(db, 'localhost', 9000); + connectFirestoreEmulator(db, '127.0.0.1', 9000); } ); @@ -185,7 +185,7 @@ apiDescribe('Validation:', persistence => { 'Firestore has already been started and its settings can no longer be changed.'; await setDoc(doc(db, 'foo/bar'), {}); - expect(() => connectFirestoreEmulator(db, 'localhost', 9000)).to.throw( + expect(() => connectFirestoreEmulator(db, '127.0.0.1', 9000)).to.throw( errorMsg ); } @@ -197,7 +197,7 @@ apiDescribe('Validation:', persistence => { () => { const db = newTestFirestore(newTestApp('test-project')); // Verify that this doesn't throw. - connectFirestoreEmulator(db, 'localhost', 9000, { + connectFirestoreEmulator(db, '127.0.0.1', 9000, { mockUserToken: { sub: 'foo' } }); } @@ -209,7 +209,7 @@ apiDescribe('Validation:', persistence => { () => { const db = newTestFirestore(newTestApp('test-project')); // Verify that this doesn't throw. - connectFirestoreEmulator(db, 'localhost', 9000, { + connectFirestoreEmulator(db, '127.0.0.1', 9000, { mockUserToken: 'my-mock-user-token' }); } @@ -222,7 +222,7 @@ apiDescribe('Validation:', persistence => { const errorMsg = "mockUserToken must contain 'sub' or 'user_id' field!"; expect(() => - connectFirestoreEmulator(db, 'localhost', 9000, { + connectFirestoreEmulator(db, '127.0.0.1', 9000, { mockUserToken: {} as any }) ).to.throw(errorMsg); diff --git a/packages/firestore/test/integration/browser/webchannel.test.ts b/packages/firestore/test/integration/browser/webchannel.test.ts index 9d9847fc665..622bc67ade2 100644 --- a/packages/firestore/test/integration/browser/webchannel.test.ts +++ b/packages/firestore/test/integration/browser/webchannel.test.ts @@ -63,6 +63,10 @@ describeFn('WebChannel', () => { } }; + // Register an "onConnected" callback since it's required, even though we + // don't care about this event. + stream.onConnected(() => {}); + // Once the stream is open, send an "add_target" request stream.onOpen(() => { stream.send(payload); diff --git a/packages/firestore/test/integration/remote/stream.test.ts b/packages/firestore/test/integration/remote/stream.test.ts index 6726f92a772..53819ae21d5 100644 --- a/packages/firestore/test/integration/remote/stream.test.ts +++ b/packages/firestore/test/integration/remote/stream.test.ts @@ -22,7 +22,10 @@ import { Token } from '../../../src/api/credentials'; import { SnapshotVersion } from '../../../src/core/snapshot_version'; +import { Target } from '../../../src/core/target'; +import { TargetData, TargetPurpose } from '../../../src/local/target_data'; import { MutationResult } from '../../../src/model/mutation'; +import { ResourcePath } from '../../../src/model/path'; import { newPersistentWatchStream, newPersistentWriteStream @@ -57,7 +60,8 @@ type StreamEventType = | 'mutationResult' | 'watchChange' | 'open' - | 'close'; + | 'close' + | 'connected'; const SINGLE_MUTATION = [setMutation('docs/1', { foo: 'bar' })]; @@ -117,6 +121,10 @@ class StreamStatusListener implements WatchStreamListener, WriteStreamListener { return this.resolvePending('watchChange'); } + onConnected(): Promise { + return this.resolvePending('connected'); + } + onOpen(): Promise { return this.resolvePending('open'); } @@ -148,6 +156,14 @@ describe('Watch Stream', () => { }); }); }); + + it('gets connected event before first message', () => { + return withTestWatchStream(async (watchStream, streamListener) => { + await streamListener.awaitCallback('open'); + watchStream.watch(sampleTargetData()); + await streamListener.awaitCallback('connected'); + }); + }); }); class MockAuthCredentialsProvider extends EmptyAuthCredentialsProvider { @@ -190,6 +206,7 @@ describe('Write Stream', () => { 'Handshake must be complete before writing mutations' ); writeStream.writeHandshake(); + await streamListener.awaitCallback('connected'); await streamListener.awaitCallback('handshakeComplete'); // Now writes should succeed @@ -205,9 +222,10 @@ describe('Write Stream', () => { return withTestWriteStream((writeStream, streamListener, queue) => { return streamListener .awaitCallback('open') - .then(() => { + .then(async () => { writeStream.writeHandshake(); - return streamListener.awaitCallback('handshakeComplete'); + await streamListener.awaitCallback('connected'); + await streamListener.awaitCallback('handshakeComplete'); }) .then(() => { writeStream.markIdle(); @@ -228,6 +246,7 @@ describe('Write Stream', () => { return withTestWriteStream(async (writeStream, streamListener, queue) => { await streamListener.awaitCallback('open'); writeStream.writeHandshake(); + await streamListener.awaitCallback('connected'); await streamListener.awaitCallback('handshakeComplete'); // Mark the stream idle, but immediately cancel the idle timer by issuing another write. @@ -336,3 +355,16 @@ export async function withTestWatchStream( streamListener.verifyNoPendingCallbacks(); }); } + +function sampleTargetData(): TargetData { + const target: Target = { + path: ResourcePath.emptyPath(), + collectionGroup: null, + orderBy: [], + filters: [], + limit: null, + startAt: null, + endAt: null + }; + return new TargetData(target, 1, TargetPurpose.Listen, 1); +} diff --git a/packages/firestore/test/integration/util/composite_index_test_helper.ts b/packages/firestore/test/integration/util/composite_index_test_helper.ts index b04bb483558..5199539768b 100644 --- a/packages/firestore/test/integration/util/composite_index_test_helper.ts +++ b/packages/firestore/test/integration/util/composite_index_test_helper.ts @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { expect } from 'chai'; import { query as internalQuery, @@ -49,7 +50,8 @@ import { batchCommitDocsToCollection, checkOnlineAndOfflineResultsMatch, PERSISTENCE_MODE_UNSPECIFIED, - PersistenceMode + PersistenceMode, + toIds } from './helpers'; import { COMPOSITE_INDEX_TEST_COLLECTION, @@ -169,6 +171,15 @@ export class CompositeIndexTestHelper { ); } + // Asserts that the IDs in the query snapshot matches the expected Ids. The expected document + // IDs are hashed to match the actual document IDs created by the test helper. + assertSnapshotResultIdsMatch( + snapshot: QuerySnapshot, + expectedIds: string[] + ): void { + expect(toIds(snapshot)).to.deep.equal(this.toHashedIds(expectedIds)); + } + // Adds a filter on test id for a query. query(query_: Query, ...queryConstraints: QueryConstraint[]): Query { return internalQuery( diff --git a/packages/firestore/test/unit/api/database.test.ts b/packages/firestore/test/unit/api/database.test.ts index ddae011b3cb..9dcc7f5ae9d 100644 --- a/packages/firestore/test/unit/api/database.test.ts +++ b/packages/firestore/test/unit/api/database.test.ts @@ -547,9 +547,9 @@ describe('Settings', () => { it('gets settings from useEmulator', () => { // Use a new instance of Firestore in order to configure settings. const db = newTestFirestore(); - connectFirestoreEmulator(db, 'localhost', 9000); + connectFirestoreEmulator(db, '127.0.0.1', 9000); - expect(db._getSettings().host).to.equal('localhost:9000'); + expect(db._getSettings().host).to.equal('127.0.0.1:9000'); expect(db._getSettings().ssl).to.be.false; }); @@ -557,9 +557,9 @@ describe('Settings', () => { // Use a new instance of Firestore in order to configure settings. const db = newTestFirestore(); db._setSettings({ host: 'other.host' }); - connectFirestoreEmulator(db, 'localhost', 9000); + connectFirestoreEmulator(db, '127.0.0.1', 9000); - expect(db._getSettings().host).to.equal('localhost:9000'); + expect(db._getSettings().host).to.equal('127.0.0.1:9000'); expect(db._getSettings().ssl).to.be.false; }); @@ -567,7 +567,7 @@ describe('Settings', () => { // Use a new instance of Firestore in order to configure settings. const db = newTestFirestore(); const mockUserToken = { sub: 'foobar' }; - connectFirestoreEmulator(db, 'localhost', 9000, { mockUserToken }); + connectFirestoreEmulator(db, '127.0.0.1', 9000, { mockUserToken }); const credentials = db._authCredentials; expect(credentials).to.be.instanceOf(EmulatorAuthCredentialsProvider); @@ -579,7 +579,7 @@ describe('Settings', () => { it('sets credentials based on mockUserToken string', async () => { // Use a new instance of Firestore in order to configure settings. const db = newTestFirestore(); - connectFirestoreEmulator(db, 'localhost', 9000, { + connectFirestoreEmulator(db, '127.0.0.1', 9000, { mockUserToken: 'my-custom-mock-user-token' }); diff --git a/packages/firestore/test/unit/core/event_manager.test.ts b/packages/firestore/test/unit/core/event_manager.test.ts index 293514ceb6d..e6752437ac5 100644 --- a/packages/firestore/test/unit/core/event_manager.test.ts +++ b/packages/firestore/test/unit/core/event_manager.test.ts @@ -25,7 +25,8 @@ import { newEventManager, eventManagerOnWatchChange, QueryListener, - eventManagerOnOnlineStateChange + eventManagerOnOnlineStateChange, + EventManager } from '../../../src/core/event_manager'; import { Query } from '../../../src/core/query'; import { OnlineState } from '../../../src/core/types'; @@ -50,29 +51,45 @@ describe('EventManager', () => { function fakeQueryListener(query: Query): any { return { query, + options: {}, onViewSnapshot: () => {}, onError: () => {}, - applyOnlineStateChange: () => {} + applyOnlineStateChange: () => {}, + listensToRemoteStore: () => {} }; } // mock objects. - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let onListenSpy: any, onUnlistenSpy: any; + /* eslint-disable @typescript-eslint/no-explicit-any */ + let onListenSpy: any, + onUnlistenSpy: any, + onFirstRemoteStoreListenSpy: any, + onLastRemoteStoreUnlistenSpy: any; + /* eslint-enable @typescript-eslint/no-explicit-any */ beforeEach(() => { onListenSpy = sinon.stub().returns(Promise.resolve(0)); onUnlistenSpy = sinon.spy(); + onFirstRemoteStoreListenSpy = sinon.spy(); + onLastRemoteStoreUnlistenSpy = sinon.spy(); }); + function eventManagerBindSpy(eventManager: EventManager): void { + eventManager.onListen = onListenSpy.bind(null); + eventManager.onUnlisten = onUnlistenSpy.bind(null); + eventManager.onFirstRemoteStoreListen = + onFirstRemoteStoreListenSpy.bind(null); + eventManager.onLastRemoteStoreUnlisten = + onLastRemoteStoreUnlistenSpy.bind(null); + } + it('handles many listenables per query', async () => { const query1 = query('foo/bar'); const fakeListener1 = fakeQueryListener(query1); const fakeListener2 = fakeQueryListener(query1); const eventManager = newEventManager(); - eventManager.onListen = onListenSpy.bind(null); - eventManager.onUnlisten = onUnlistenSpy.bind(null); + eventManagerBindSpy(eventManager); await eventManagerListen(eventManager, fakeListener1); expect(onListenSpy.calledWith(query1)).to.be.true; @@ -92,8 +109,7 @@ describe('EventManager', () => { const fakeListener1 = fakeQueryListener(query1); const eventManager = newEventManager(); - eventManager.onListen = onListenSpy.bind(null); - eventManager.onUnlisten = onUnlistenSpy.bind(null); + eventManagerBindSpy(eventManager); await eventManagerUnlisten(eventManager, fakeListener1); expect(onUnlistenSpy.callCount).to.equal(0); @@ -118,8 +134,7 @@ describe('EventManager', () => { }; const eventManager = newEventManager(); - eventManager.onListen = onListenSpy.bind(null); - eventManager.onUnlisten = onUnlistenSpy.bind(null); + eventManagerBindSpy(eventManager); await eventManagerListen(eventManager, fakeListener1); await eventManagerListen(eventManager, fakeListener2); @@ -150,8 +165,7 @@ describe('EventManager', () => { }; const eventManager = newEventManager(); - eventManager.onListen = onListenSpy.bind(null); - eventManager.onUnlisten = onUnlistenSpy.bind(null); + eventManagerBindSpy(eventManager); await eventManagerListen(eventManager, fakeListener1); expect(events).to.deep.equal([OnlineState.Unknown]); diff --git a/packages/firestore/test/unit/core/webchannel_wrapper.test.ts b/packages/firestore/test/unit/core/webchannel_wrapper.test.ts index 3f3272aea48..c5e597f4216 100644 --- a/packages/firestore/test/unit/core/webchannel_wrapper.test.ts +++ b/packages/firestore/test/unit/core/webchannel_wrapper.test.ts @@ -19,7 +19,7 @@ // These tests are mostly to ensure that the exported classes correctly map to // underlying functionality from google-closure-library. -import { Md5, Integer } from '@firebase/webchannel-wrapper'; +import { Md5, Integer } from '@firebase/webchannel-wrapper/bloom-blob'; import { expect } from 'chai'; import { newTextEncoder } from '../../../src/platform/text_serializer'; diff --git a/packages/firestore/test/unit/index/firestore_index_value_writer.test.ts b/packages/firestore/test/unit/index/firestore_index_value_writer.test.ts new file mode 100644 index 00000000000..8f7cd7c973f --- /dev/null +++ b/packages/firestore/test/unit/index/firestore_index_value_writer.test.ts @@ -0,0 +1,173 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0x00 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0x00 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { expect } from 'chai'; + +import { FirestoreIndexValueWriter } from '../../../src/index/firestore_index_value_writer'; +import { IndexByteEncoder } from '../../../src/index/index_byte_encoder'; +import { Timestamp } from '../../../src/lite-api/timestamp'; +import { IndexKind } from '../../../src/model/field_index'; +import type { Value } from '../../../src/protos/firestore_proto_api'; +import { toTimestamp } from '../../../src/remote/serializer'; +import { JSON_SERIALIZER } from '../local/persistence_test_helpers'; + +import { compare } from './ordered_code_writer.test'; + +describe('Firestore Index Value Writer', () => { + function compareIndexEncodedValues( + value1: Value, + value2: Value, + direction: IndexKind + ): number { + const encoder1 = new IndexByteEncoder(); + const encoder2 = new IndexByteEncoder(); + FirestoreIndexValueWriter.INSTANCE.writeIndexValue( + value1, + encoder1.forKind(direction) + ); + + FirestoreIndexValueWriter.INSTANCE.writeIndexValue( + value2, + encoder2.forKind(direction) + ); + + return compare(encoder1.encodedBytes(), encoder2.encodedBytes()); + } + + describe('can gracefully handle different format of timestamp', () => { + it('can handle different format of timestamp', () => { + const value1 = { timestampValue: '2016-01-02T10:20:50.850Z' }; + const value2 = { timestampValue: '2016-01-02T10:20:50.850000Z' }; + const value3 = { timestampValue: '2016-01-02T10:20:50.850000000Z' }; + const value4 = { + timestampValue: { seconds: 1451730050, nanos: 850000000 } + }; + const value5 = { + timestampValue: toTimestamp( + JSON_SERIALIZER, + new Timestamp(1451730050, 850000000) + ) + }; + expect( + compareIndexEncodedValues(value1, value2, IndexKind.ASCENDING) + ).to.equal(0); + expect( + compareIndexEncodedValues(value1, value3, IndexKind.ASCENDING) + ).to.equal(0); + expect( + compareIndexEncodedValues(value1, value4, IndexKind.ASCENDING) + ).to.equal(0); + expect( + compareIndexEncodedValues(value1, value5, IndexKind.ASCENDING) + ).to.equal(0); + + expect( + compareIndexEncodedValues(value1, value2, IndexKind.DESCENDING) + ).to.equal(0); + expect( + compareIndexEncodedValues(value1, value3, IndexKind.DESCENDING) + ).to.equal(0); + expect( + compareIndexEncodedValues(value1, value4, IndexKind.DESCENDING) + ).to.equal(0); + expect( + compareIndexEncodedValues(value1, value5, IndexKind.DESCENDING) + ).to.equal(0); + }); + + it('can handle timestamps with 0 nanoseconds', () => { + const value1 = { timestampValue: '2016-01-02T10:20:50Z' }; + const value2 = { timestampValue: '2016-01-02T10:20:50.000000000Z' }; + const value3 = { timestampValue: { seconds: 1451730050, nanos: 0 } }; + const value4 = { + timestampValue: toTimestamp( + JSON_SERIALIZER, + new Timestamp(1451730050, 0) + ) + }; + expect( + compareIndexEncodedValues(value1, value2, IndexKind.ASCENDING) + ).to.equal(0); + expect( + compareIndexEncodedValues(value1, value3, IndexKind.ASCENDING) + ).to.equal(0); + expect( + compareIndexEncodedValues(value1, value4, IndexKind.ASCENDING) + ).to.equal(0); + + expect( + compareIndexEncodedValues(value1, value2, IndexKind.DESCENDING) + ).to.equal(0); + expect( + compareIndexEncodedValues(value1, value3, IndexKind.DESCENDING) + ).to.equal(0); + expect( + compareIndexEncodedValues(value1, value4, IndexKind.DESCENDING) + ).to.equal(0); + }); + + it('can compare timestamps with different formats', () => { + const value1 = { timestampValue: '2016-01-02T10:20:50Z' }; + const value2 = { timestampValue: '2016-01-02T10:20:50.000001Z' }; + const value3 = { + timestampValue: { seconds: 1451730050, nanos: 999999999 } + }; + const value4 = { + timestampValue: toTimestamp( + JSON_SERIALIZER, + new Timestamp(1451730050, 1) + ) + }; + expect( + compareIndexEncodedValues(value1, value2, IndexKind.ASCENDING) + ).to.equal(-1); + expect( + compareIndexEncodedValues(value1, value3, IndexKind.ASCENDING) + ).to.equal(-1); + expect( + compareIndexEncodedValues(value1, value4, IndexKind.ASCENDING) + ).to.equal(-1); + expect( + compareIndexEncodedValues(value2, value3, IndexKind.ASCENDING) + ).to.equal(-1); + expect( + compareIndexEncodedValues(value2, value4, IndexKind.ASCENDING) + ).to.equal(1); + expect( + compareIndexEncodedValues(value3, value4, IndexKind.ASCENDING) + ).to.equal(1); + + expect( + compareIndexEncodedValues(value1, value2, IndexKind.DESCENDING) + ).to.equal(1); + expect( + compareIndexEncodedValues(value1, value3, IndexKind.DESCENDING) + ).to.equal(1); + expect( + compareIndexEncodedValues(value1, value4, IndexKind.DESCENDING) + ).to.equal(1); + expect( + compareIndexEncodedValues(value2, value3, IndexKind.DESCENDING) + ).to.equal(1); + expect( + compareIndexEncodedValues(value2, value4, IndexKind.DESCENDING) + ).to.equal(-1); + expect( + compareIndexEncodedValues(value3, value4, IndexKind.DESCENDING) + ).to.equal(-1); + }); + }); +}); diff --git a/packages/firestore/test/unit/index/ordered_code_writer.test.ts b/packages/firestore/test/unit/index/ordered_code_writer.test.ts index b3f58987f49..6d87ddb4849 100644 --- a/packages/firestore/test/unit/index/ordered_code_writer.test.ts +++ b/packages/firestore/test/unit/index/ordered_code_writer.test.ts @@ -226,7 +226,7 @@ function fromHex(hexString: string): Uint8Array { return bytes; } -function compare(left: Uint8Array, right: Uint8Array): number { +export function compare(left: Uint8Array, right: Uint8Array): number { for (let i = 0; i < Math.min(left.length, right.length); ++i) { if (left[i] < right[i]) { return -1; diff --git a/packages/firestore/test/unit/lite-api/types.test.ts b/packages/firestore/test/unit/lite-api/types.test.ts index 55232aeee60..105819ed4e4 100644 --- a/packages/firestore/test/unit/lite-api/types.test.ts +++ b/packages/firestore/test/unit/lite-api/types.test.ts @@ -695,4 +695,82 @@ describe('FirestoreTypeConverter', () => { expect(data.numberProperty).to.equal(43); } }); + + it('setDoc() fails to compile if AppModelType argument is missing properties', () => + neverCall(async docRef => { + const converter = fakeConverter<{ foo: string }, {}>(); + const docRefWithConverter = docRef.withConverter(converter); + // @ts-expect-error The `foo` property declared in AppModelType is missing. + await setDoc(docRefWithConverter, {}); + })); + + it('setDoc() fails to compile if AppModelType argument contains undeclared properties', () => + neverCall(async docRef => { + const converter = fakeConverter<{ foo: string }, { bar: number }>(); + const docRefWithConverter = docRef.withConverter(converter); + // @ts-expect-error The `bar` property is not declared in AppModelType. + await setDoc(docRefWithConverter, { foo: 'foo', bar: 42 }); + })); + + it('setDoc() fails to compile if AppModelType argument contains a property with an incorrect type', () => + neverCall(async docRef => { + const converter = fakeConverter<{ foo: string }, { foo: number }>(); + const docRefWithConverter = docRef.withConverter(converter); + // @ts-expect-error The `foo` property is declared as `string` in + // AppModelType, but a `number` is specified. + await setDoc(docRefWithConverter, { foo: 42 }); + })); + + it('updateDoc() successfully compiles even if DbModelType argument is missing properties', () => + neverCall(async docRef => { + const converter = fakeConverter<{ foo: string }, { bar: number }>(); + const docRefWithConverter = docRef.withConverter(converter); + await updateDoc(docRefWithConverter, {}); + })); + + it('updateDoc() fails to compile if DbModelType argument contains undeclared properties', () => + neverCall(async docRef => { + const converter = fakeConverter<{ foo: string }, { bar: number }>(); + const docRefWithConverter = docRef.withConverter(converter); + // @ts-expect-error The `foo` property is not declared in DbModelType. + await updateDoc(docRefWithConverter, { foo: 'foo', bar: 42 }); + })); + + it('updateDoc() fails to compile if DbModelType argument contains a property with an incorrect type', () => + neverCall(async docRef => { + const converter = fakeConverter<{ foo: string }, { foo: number }>(); + const docRefWithConverter = docRef.withConverter(converter); + // @ts-expect-error The `foo` property is declared as `number` in + // DbModelType, but a `string` is specified. + await updateDoc(docRefWithConverter, { foo: 'foo' }); + })); + + it('getDoc() returns AppModelType', () => + neverCall>(async docRef => { + const converter = fakeConverter<{ foo: string }, { bar: number }>(); + const docRefWithConverter = docRef.withConverter(converter); + const snapshot = await getDoc(docRefWithConverter); + return snapshot.data()!; + })); }); + +/** + * Does nothing; however, this function can be useful in tests that only check + * the compile-time behavior of the TypeScript compiler. For example, a test + * that ensures that a certain statement successfully compiles could pass the + * code block to this function to exercise the compiler but the code will not + * actually be executed at runtime. + */ +function neverCall(_: (docRef: DocumentReference) => T): void {} + +/** + * Does nothing; this function does not actually exist but is merely _declared_ + * to exist. This facilitates creating variables typed as FirestoreDataConverter + * with the given type parameters at compile time. This can be useful in tests + * that only check compile-time behavior of the TypeScript compiler but don't + * actually get executed at runtime. + */ +declare function fakeConverter< + AppModelType, + DbModelType extends DocumentData +>(): FirestoreDataConverter; diff --git a/packages/firestore/test/unit/local/index_manager.test.ts b/packages/firestore/test/unit/local/index_manager.test.ts index 81b23b17efd..627e8a89f7f 100644 --- a/packages/firestore/test/unit/local/index_manager.test.ts +++ b/packages/firestore/test/unit/local/index_manager.test.ts @@ -30,6 +30,7 @@ import { queryWithLimit, queryWithStartAt } from '../../../src/core/query'; +import { Timestamp } from '../../../src/lite-api/timestamp'; import { displayNameForIndexType, IndexType @@ -41,7 +42,7 @@ import { import { IndexedDbPersistence } from '../../../src/local/indexeddb_persistence'; import { Persistence } from '../../../src/local/persistence'; import { documentMap } from '../../../src/model/collections'; -import { Document } from '../../../src/model/document'; +import { Document, MutableDocument } from '../../../src/model/document'; import { IndexKind, IndexOffset, @@ -49,6 +50,18 @@ import { } from '../../../src/model/field_index'; import { JsonObject } from '../../../src/model/object_value'; import { canonicalId } from '../../../src/model/values'; +import { + ApiClientObjectMap as ProtoObjectMap, + Document as ProtoDocument, + Value as ProtoValue +} from '../../../src/protos/firestore_proto_api'; +import { + fromDocument, + JsonProtoSerializer, + toName, + toTimestamp, + toVersion +} from '../../../src/remote/serializer'; import { addEqualityMatcher } from '../../util/equality_matcher'; import { bound, @@ -99,6 +112,11 @@ describe('IndexedDbIndexManager', async () => { } let persistencePromise: Promise; + const serializer = new JsonProtoSerializer( + persistenceHelpers.TEST_DATABASE_ID, + /* useProto3Json= */ true + ); + beforeEach(async () => { persistencePromise = persistenceHelpers.testIndexedDbPersistence(); }); @@ -1038,6 +1056,62 @@ describe('IndexedDbIndexManager', async () => { await verifyResults(testingQuery, 'coll/val3'); }); + it('can index timestamp fields of different format', async () => { + await indexManager.addFieldIndex( + fieldIndex('coll', { fields: [['date', IndexKind.ASCENDING]] }) + ); + + await addDocFromProto('coll/val1', { + 'date': { timestampValue: '2016-01-02T10:20:50Z' } + }); + await addDocFromProto('coll/val2', { + 'date': { timestampValue: '2016-01-02T10:20:50.000000000Z' } + }); + await addDocFromProto('coll/val3', { + 'date': { timestampValue: '2016-01-02T10:20:50.850Z' } + }); + await addDocFromProto('coll/val4', { + 'date': { timestampValue: '2016-01-02T10:20:50.850000000Z' } + }); + await addDocFromProto('coll/val5', { + 'date': { timestampValue: { seconds: 1451730050, nanos: 999999999 } } + }); + await addDocFromProto('coll/val6', { + 'date': { + timestampValue: toTimestamp(serializer, new Timestamp(1451730050, 1)) + } + }); + + let q = queryWithAddedOrderBy(query('coll'), orderBy('date')); + await verifyResults( + q, + 'coll/val1', + 'coll/val2', + 'coll/val6', + 'coll/val3', + 'coll/val4', + 'coll/val5' + ); + + q = queryWithAddedFilter( + query('coll'), + filter('date', '==', new Timestamp(1451730050, 850000000)) + ); + await verifyResults(q, 'coll/val3', 'coll/val4'); + + q = queryWithAddedFilter( + query('coll'), + filter('date', '>=', new Timestamp(1451730050, 850000000)) + ); + await verifyResults(q, 'coll/val3', 'coll/val4', 'coll/val5'); + + q = queryWithAddedFilter( + query('coll'), + filter('date', '>', new Timestamp(1451730050, 0)) + ); + await verifyResults(q, 'coll/val6', 'coll/val3', 'coll/val4', 'coll/val5'); + }); + it('support advances queries', async () => { // This test compares local query results with those received from the Java // Server SDK. @@ -1840,6 +1914,31 @@ describe('IndexedDbIndexManager', async () => { return addDocs(doc(key, 1, data)); } + function addDocFromProto( + key: string, + data: ProtoObjectMap | undefined + ): Promise { + return addDocs(docFromProto(key, 1, data)); + } + + function docFromProto( + keyStr: string, + versionNumber: number, + data: ProtoObjectMap | undefined + ): MutableDocument { + const proto: ProtoDocument = { + name: toName(serializer, key(keyStr)), + fields: data, + updateTime: toVersion(serializer, version(versionNumber)), + createTime: toVersion(serializer, version(versionNumber)) + }; + return fromDocument( + serializer, + proto, + /* hasCommittedMutations= */ undefined + ); + } + async function verifyResults(query: Query, ...keys: string[]): Promise { const target = queryToTarget(query); const actualResults = await indexManager.getDocumentsMatchingTarget(target); diff --git a/packages/firestore/test/unit/local/simple_db.test.ts b/packages/firestore/test/unit/local/simple_db.test.ts index aff2761b9c3..b2b7ed3f95a 100644 --- a/packages/firestore/test/unit/local/simple_db.test.ts +++ b/packages/firestore/test/unit/local/simple_db.test.ts @@ -22,6 +22,7 @@ import { Context } from 'mocha'; import { dbKeyComparator } from '../../../src/local/indexeddb_remote_document_cache'; import { PersistencePromise } from '../../../src/local/persistence_promise'; import { + getAndroidVersion, SimpleDb, SimpleDbSchemaConverter, SimpleDbStore, @@ -137,7 +138,7 @@ describe('SimpleDb', () => { ' AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1'; expect(SimpleDb.getIOSVersion(iPhoneSafariAgent)).to.equal(10.14); expect(SimpleDb.getIOSVersion(iPadSafariAgent)).to.equal(9.0); - expect(SimpleDb.getAndroidVersion(androidAgent)).to.equal(2.2); + expect(getAndroidVersion(androidAgent)).to.equal(2.2); }); it('can get', async () => { diff --git a/packages/firestore/test/unit/specs/bundle_spec.test.ts b/packages/firestore/test/unit/specs/bundle_spec.test.ts index 2e63799d80d..5a88dc8691c 100644 --- a/packages/firestore/test/unit/specs/bundle_spec.test.ts +++ b/packages/firestore/test/unit/specs/bundle_spec.test.ts @@ -52,7 +52,7 @@ interface TestBundledQuery { limitType?: LimitType; } -function bundleWithDocumentAndQuery( +export function bundleWithDocumentAndQuery( testDoc: TestBundleDocument, testQuery?: TestBundledQuery ): string { diff --git a/packages/firestore/test/unit/specs/listen_source_spec.test.ts b/packages/firestore/test/unit/specs/listen_source_spec.test.ts new file mode 100644 index 00000000000..ee2a9cf5944 --- /dev/null +++ b/packages/firestore/test/unit/specs/listen_source_spec.test.ts @@ -0,0 +1,843 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { LimitType, queryWithLimit } from '../../../src/core/query'; +import { doc, filter, orderBy, query } from '../../util/helpers'; + +import { bundleWithDocumentAndQuery } from './bundle_spec.test'; +import { describeSpec, specTest } from './describe_spec'; +import { client, spec } from './spec_builder'; + +describeSpec('Listens source options:', [], () => { + specTest( + 'Contents of query are cleared when listen is removed.', + ['eager-gc'], + 'Explicitly tests eager GC behavior', + () => { + const testQuery = query('collection'); + const docA = doc('collection/a', 0, { key: 'a' }).setHasLocalMutations(); + return ( + spec() + .userSets('collection/a', { key: 'a' }) + .userListensToCache(testQuery) + .expectEvents(testQuery, { + added: [docA], + hasPendingWrites: true, + fromCache: true + }) + .userUnlistensToCache(testQuery) + .writeAcks('collection/a', 1000) + // Cache is empty as docA is GCed. + .userListensToCache(testQuery) + .expectEvents(testQuery, { added: [], fromCache: true }) + ); + } + ); + + specTest( + 'Documents are cleared when listen is removed.', + ['eager-gc'], + () => { + const filteredQuery = query('collection', filter('matches', '==', true)); + const unfilteredQuery = query('collection'); + const docA = doc('collection/a', 0, { + matches: true + }).setHasLocalMutations(); + const docB = doc('collection/b', 0, { + matches: true + }).setHasLocalMutations(); + return ( + spec() + .userSets('collection/a', { matches: true }) + .userSets('collection/b', { matches: true }) + .userListensToCache(filteredQuery) + .expectEvents(filteredQuery, { + added: [docA, docB], + hasPendingWrites: true, + fromCache: true + }) + .writeAcks('collection/a', 1000) + .writeAcks('collection/b', 2000) + .userSets('collection/b', { matches: false }) + // DocB doesn't match because of a pending mutation + .expectEvents(filteredQuery, { + removed: [docB], + hasPendingWrites: true, + fromCache: true + }) + .userUnlistensToCache(filteredQuery) + .writeAcks('collection/b', 3000) + // Should get no events since documents were GCed + .userListensToCache(unfilteredQuery) + .expectEvents(unfilteredQuery, { added: [], fromCache: true }) + .userUnlistensToCache(unfilteredQuery) + ); + } + ); + + specTest("Doesn't include unknown documents in cached result", [], () => { + const testQuery = query('collection'); + const existingDoc = doc('collection/exists', 0, { + key: 'a' + }).setHasLocalMutations(); + return spec() + .userSets('collection/exists', { key: 'a' }) + .userPatches('collection/unknown', { key: 'b' }) + .userListensToCache(testQuery) + .expectEvents(testQuery, { + added: [existingDoc], + fromCache: true, + hasPendingWrites: true + }); + }); + + specTest("Doesn't raise 'hasPendingWrites' for deletes", [], () => { + const testQuery = query('collection'); + const docA = doc('collection/a', 1000, { key: 'a' }); + + return ( + spec() + .ensureManualLruGC() + // Populate the cache first + .userListens(testQuery) + .watchAcksFull(testQuery, 1000, docA) + .expectEvents(testQuery, { added: [docA] }) + .userUnlistens(testQuery) + .watchRemoves(testQuery) + // Listen to cache + .userListensToCache(testQuery) + .expectEvents(testQuery, { added: [docA], fromCache: true }) + .userDeletes('collection/a') + .expectEvents(testQuery, { removed: [docA], fromCache: true }) + .writeAcks('collection/a', 2000) + ); + }); + + specTest('onSnapshotsInSync fires for multiple listeners', [], () => { + const query1 = query('collection'); + const docAv1 = doc('collection/a', 1000, { v: 1 }); + const docAv2Local = doc('collection/a', 1000, { + v: 2 + }).setHasLocalMutations(); + const docAv3Local = doc('collection/a', 1000, { + v: 3 + }).setHasLocalMutations(); + const docAv4Local = doc('collection/a', 1000, { + v: 4 + }).setHasLocalMutations(); + + return ( + spec() + .ensureManualLruGC() + // Populate the cache first + .userListens(query1) + .watchAcksFull(query1, 1000, docAv1) + .expectEvents(query1, { added: [docAv1] }) + .userUnlistens(query1) + .watchRemoves(query1) + // Listen to cache + .userListensToCache(query1) + .expectEvents(query1, { added: [docAv1], fromCache: true }) + .userAddsSnapshotsInSyncListener() + .expectSnapshotsInSyncEvent() + .userSets('collection/a', { v: 2 }) + .expectEvents(query1, { + hasPendingWrites: true, + modified: [docAv2Local], + fromCache: true + }) + .expectSnapshotsInSyncEvent() + .userAddsSnapshotsInSyncListener() + .expectSnapshotsInSyncEvent() + .userAddsSnapshotsInSyncListener() + .expectSnapshotsInSyncEvent() + .userSets('collection/a', { v: 3 }) + .expectEvents(query1, { + hasPendingWrites: true, + modified: [docAv3Local], + fromCache: true + }) + .expectSnapshotsInSyncEvent(3) + .userRemovesSnapshotsInSyncListener() + .userSets('collection/a', { v: 4 }) + .expectEvents(query1, { + hasPendingWrites: true, + modified: [docAv4Local], + fromCache: true + }) + .expectSnapshotsInSyncEvent(2) + ); + }); + + specTest('Empty initial snapshot is raised from cache', [], () => { + const query1 = query('collection'); + return ( + spec() + .ensureManualLruGC() + // Populate the cache with the empty query results. + .userListens(query1) + .watchAcksFull(query1, 1000) + .expectEvents(query1, { fromCache: false }) + .userUnlistens(query1) + .watchRemoves(query1) + // Listen to the query again and verify that the empty snapshot is + // raised from cache. + .userListensToCache(query1, { resumeToken: 'resume-token-1000' }) + .expectEvents(query1, { fromCache: true }) + ); + }); + + specTest( + 'Empty-due-to-delete initial snapshot is raised from cache', + [], + () => { + const query1 = query('collection'); + const doc1 = doc('collection/a', 1000, { v: 1 }); + return ( + spec() + .ensureManualLruGC() + // Populate the cache with the empty query results. + .userListens(query1) + .watchAcksFull(query1, 1000, doc1) + .expectEvents(query1, { added: [doc1] }) + .userUnlistens(query1) + .watchRemoves(query1) + // Delete the only document in the result set locally on the client. + .userDeletes('collection/a') + // Listen to the query again and verify that the empty snapshot is + // raised from cache, even though the write is not yet acknowledged. + .userListensToCache(query1, { resumeToken: 'resume-token-1000' }) + .expectEvents(query1, { fromCache: true }) + ); + } + ); + + specTest('Newer docs from bundles should overwrite cache', [], () => { + const query1 = query('collection'); + const docA = doc('collection/a', 1000, { value: 'a' }); + const docAChanged = doc('collection/a', 2999, { value: 'b' }); + + const bundleString = bundleWithDocumentAndQuery({ + key: docA.key, + readTime: 3000, + createTime: 1999, + updateTime: 2999, + content: { value: 'b' } + }); + + return ( + spec() + .ensureManualLruGC() + // Populate the cache first + .userListens(query1) + .watchAcksFull(query1, 1000, docA) + .expectEvents(query1, { added: [docA] }) + .userUnlistens(query1) + .watchRemoves(query1) + // Listen to cache + .userListensToCache(query1) + .expectEvents(query1, { added: [docA], fromCache: true }) + .loadBundle(bundleString) + .expectEvents(query1, { modified: [docAChanged], fromCache: true }) + ); + }); + + specTest( + 'Newer deleted docs from bundles should delete cached docs', + [], + () => { + const query1 = query('collection'); + const docA = doc('collection/a', 1000, { value: 'a' }); + const bundleString = bundleWithDocumentAndQuery({ + key: docA.key, + readTime: 3000 + }); + + return ( + spec() + .ensureManualLruGC() + // Populate the cache first + .userListens(query1) + .watchAcksFull(query1, 1000, docA) + .expectEvents(query1, { added: [docA] }) + .userUnlistens(query1) + .watchRemoves(query1) + // Listen to cache + .userListensToCache(query1) + .expectEvents(query1, { added: [docA], fromCache: true }) + .loadBundle(bundleString) + .expectEvents(query1, { removed: [docA], fromCache: true }) + ); + } + ); + + specTest('Older deleted docs from bundles should do nothing', [], () => { + const query1 = query('collection'); + const docA = doc('collection/a', 1000, { value: 'a' }); + const bundleString = bundleWithDocumentAndQuery({ + key: docA.key, + readTime: 999 + }); + + return ( + spec() + .ensureManualLruGC() + // Populate the cache first + .userListens(query1) + .watchAcksFull(query1, 1000, docA) + .expectEvents(query1, { added: [docA] }) + .userUnlistens(query1) + .watchRemoves(query1) + // Listen to cache + .userListensToCache(query1) + .expectEvents(query1, { added: [docA], fromCache: true }) + // No events are expected here. + .loadBundle(bundleString) + ); + }); + + specTest( + 'Newer docs from bundles should keep not raise snapshot if there are unacknowledged writes', + [], + () => { + const query1 = query('collection'); + const docA = doc('collection/a', 250, { value: 'a' }); + const bundleString = bundleWithDocumentAndQuery({ + key: docA.key, + readTime: 1001, + createTime: 250, + updateTime: 1001, + content: { value: 'fromBundle' } + }); + + return ( + spec() + .ensureManualLruGC() + // Populate the cache first + .userListens(query1) + .watchAcksFull(query1, 250, docA) + .expectEvents(query1, { added: [docA] }) + .userUnlistens(query1) + .watchRemoves(query1) + // Listen to cache + .userListensToCache(query1) + .expectEvents(query1, { + added: [doc('collection/a', 250, { value: 'a' })], + fromCache: true + }) + .userPatches('collection/a', { value: 'patched' }) + .expectEvents(query1, { + modified: [ + doc('collection/a', 250, { + value: 'patched' + }).setHasLocalMutations() + ], + hasPendingWrites: true, + fromCache: true + }) + // Loading the bundle will not raise snapshots, because the + // mutation has not been acknowledged. + .loadBundle(bundleString) + ); + } + ); + + specTest( + 'Newer docs from bundles should raise snapshot only when Watch catches up with acknowledged writes', + [], + () => { + const query1 = query('collection'); + const docA = doc('collection/a', 250, { value: 'a' }); + const bundleBeforeMutationAck = bundleWithDocumentAndQuery({ + key: docA.key, + readTime: 500, + createTime: 250, + updateTime: 500, + content: { value: 'b' } + }); + + const bundleAfterMutationAck = bundleWithDocumentAndQuery({ + key: docA.key, + readTime: 1001, + createTime: 250, + updateTime: 1001, + content: { value: 'fromBundle' } + }); + return ( + spec() + .ensureManualLruGC() + // Populate the cache first + .userListens(query1) + .watchAcksFull(query1, 250, docA) + .expectEvents(query1, { added: [docA] }) + .userUnlistens(query1) + .watchRemoves(query1) + // Listen to cache + .userListensToCache(query1) + .expectEvents(query1, { + added: [doc('collection/a', 250, { value: 'a' })], + fromCache: true + }) + .userPatches('collection/a', { value: 'patched' }) + .expectEvents(query1, { + modified: [ + doc('collection/a', 250, { + value: 'patched' + }).setHasLocalMutations() + ], + hasPendingWrites: true, + fromCache: true + }) + .writeAcks('collection/a', 1000) + // loading bundleBeforeMutationAck will not raise snapshots, because its + // snapshot version is older than the acknowledged mutation. + .loadBundle(bundleBeforeMutationAck) + // loading bundleAfterMutationAck will raise a snapshot, because it is after + // the acknowledged mutation. + .loadBundle(bundleAfterMutationAck) + .expectEvents(query1, { + modified: [doc('collection/a', 1001, { value: 'fromBundle' })], + fromCache: true + }) + ); + } + ); + + specTest( + 'Primary client should not invoke watch request while all clients are listening to cache', + ['multi-client'], + () => { + const query1 = query('collection'); + + return ( + client(0) + .becomeVisible() + .client(1) + .userListensToCache(query1) + .expectEvents(query1, { added: [], fromCache: true }) + // Primary client should not invoke watch request for cache listeners + .client(0) + .expectListenToCache(query1) + .expectActiveTargets() + .client(1) + .userUnlistensToCache(query1) + .client(0) + .expectUnlistenToCache(query1) + ); + } + ); + + specTest( + 'Local mutations notifies listeners sourced from cache in all tabs', + ['multi-client'], + () => { + const query1 = query('collection'); + const docA = doc('collection/a', 0, { + key: 'a' + }).setHasLocalMutations(); + + return client(0) + .becomeVisible() + .userListensToCache(query1) + .expectEvents(query1, { added: [], fromCache: true }) + .client(1) + .userListensToCache(query1) + .expectEvents(query1, { added: [], fromCache: true }) + .client(0) + .userSets('collection/a', { key: 'a' }) + .expectEvents(query1, { + hasPendingWrites: true, + added: [docA], + fromCache: true + }) + .client(1) + .expectEvents(query1, { + hasPendingWrites: true, + added: [docA], + fromCache: true + }); + } + ); + + specTest( + 'Listeners with different source shares watch changes between primary and secondary clients', + ['multi-client'], + () => { + const query1 = query('collection'); + const docA = doc('collection/a', 1000, { key: 'a' }); + const docB = doc('collection/b', 2000, { key: 'a' }); + + return ( + client(0) + .becomeVisible() + // Listen to server in the primary client + .userListens(query1) + .watchAcksFull(query1, 1000, docA) + .expectEvents(query1, { added: [docA] }) + // Listen to cache in secondary clients + .client(1) + .userListensToCache(query1) + .expectEvents(query1, { added: [docA], fromCache: true }) + .client(2) + .userListensToCache(query1) + .expectEvents(query1, { added: [docA], fromCache: true }) + // Updates in the primary client notifies listeners sourcing from cache + // in secondary clients. + .client(0) + .watchSends({ affects: [query1] }, docB) + .watchSnapshots(2000) + .expectEvents(query1, { added: [docB] }) + .client(1) + .expectEvents(query1, { added: [docB] }) + .client(2) + .expectEvents(query1, { added: [docB] }) + // Un-listen to the server in the primary tab. + .client(0) + .userUnlistens(query1) + // There should be no active watch targets left. + .expectActiveTargets() + ); + } + ); + + specTest( + 'Clients can have multiple listeners with different sources', + ['multi-client'], + () => { + const query1 = query('collection'); + const docA = doc('collection/a', 1000, { key: 'a' }); + const docB = doc('collection/b', 2000, { key: 'a' }); + + return ( + client(0) + .becomeVisible() + // Listen to both server and cache in the primary client + .userListens(query1) + .watchAcksFull(query1, 1000, docA) + .expectEvents(query1, { added: [docA] }) + .userListensToCache(query1) + .expectEvents(query1, { added: [docA] }) + // Listen to both server and cache in the secondary client + .client(1) + .userListens(query1) + .expectEvents(query1, { added: [docA] }) + .userListensToCache(query1) + .expectEvents(query1, { added: [docA] }) + // Updates in the primary client notifies all listeners + .client(0) + .watchSends({ affects: [query1] }, docB) + .watchSnapshots(2000) + .expectEvents(query1, { added: [docB] }) + .expectEvents(query1, { added: [docB] }) + .client(1) + .expectEvents(query1, { added: [docB] }) + .expectEvents(query1, { added: [docB] }) + ); + } + ); + + specTest( + 'Query is executed by primary client even if primary client only has listeners sourced from cache', + ['multi-client'], + () => { + const query1 = query('collection'); + const docA = doc('collection/a', 1000, { key: 'a' }); + + return ( + client(0) + .becomeVisible() + // Listen to cache in primary client + .userListensToCache(query1) + .expectEvents(query1, { added: [], fromCache: true }) + // Listen to server in secondary client + .client(1) + .userListens(query1) + // The query is executed in the primary client + .client(0) + .expectListen(query1) + // Updates in the primary client notifies both listeners + .watchAcks(query1) + .watchSends({ affects: [query1] }, docA) + .watchSnapshots(1000) + .expectEvents(query1, { added: [docA], fromCache: true }) + .client(1) + .expectEvents(query1, { added: [docA], fromCache: true }) + .client(0) + .watchCurrents(query1, 'resume-token-2000') + .watchSnapshots(2000) + // Listeners in both tabs are in sync + .expectEvents(query1, { fromCache: false }) + .client(1) + .expectEvents(query1, { fromCache: false }) + ); + } + ); + + specTest( + 'Query only raises events in participating clients', + ['multi-client'], + () => { + const query1 = query('collection'); + const docA = doc('collection/a', 1000, { key: 'a' }); + + return client(0) + .becomeVisible() + .client(1) + .client(2) + .userListensToCache(query1) + .expectEvents(query1, { added: [], fromCache: true }) + .client(3) + .userListens(query1) + .client(0) // No events + .expectListen(query1) + .watchAcksFull(query1, 1000, docA) + .client(1) // No events + .client(2) + .expectEvents(query1, { added: [docA] }) + .client(3) + .expectEvents(query1, { added: [docA] }); + } + ); + + specTest( + 'Mirror queries being listened in different clients sourced from cache ', + ['multi-client'], + () => { + const fullQuery = query('collection'); + const limit = queryWithLimit( + query('collection', orderBy('sort', 'asc')), + 2, + LimitType.First + ); + const limitToLast = queryWithLimit( + query('collection', orderBy('sort', 'desc')), + 2, + LimitType.Last + ); + const docA = doc('collection/a', 1000, { sort: 0 }); + const docB = doc('collection/b', 1000, { sort: 1 }); + const docC = doc('collection/c', 1000, { sort: 1 }); + const docCV2 = doc('collection/c', 2000, { + sort: -1 + }).setHasLocalMutations(); + + return ( + client(0) + .becomeVisible() + // Populate the cache first + .userListens(fullQuery) + .watchAcksFull(fullQuery, 1000, docA, docB, docC) + .expectEvents(fullQuery, { added: [docA, docB, docC] }) + .userUnlistens(fullQuery) + .watchRemoves(fullQuery) + + // Listen to mirror queries from cache in 2 different tabs + .userListensToCache(limit) + .expectEvents(limit, { added: [docA, docB], fromCache: true }) + .client(1) + .userListensToCache(limitToLast) + .expectEvents(limitToLast, { added: [docB, docA], fromCache: true }) + // Un-listen to the query in primary tab and do a local mutation + .client(0) + .userUnlistensToCache(limit) + .userSets('collection/c', { sort: -1 }) + // Listener in the other tab should work as expected + .client(1) + .expectEvents(limitToLast, { + hasPendingWrites: true, + added: [docCV2], + removed: [docB], + fromCache: true + }) + ); + } + ); + + specTest( + 'Mirror queries being listened in the same secondary client sourced from cache', + ['multi-client'], + () => { + const fullQuery = query('collection'); + const limit = queryWithLimit( + query('collection', orderBy('sort', 'asc')), + 2, + LimitType.First + ); + const limitToLast = queryWithLimit( + query('collection', orderBy('sort', 'desc')), + 2, + LimitType.Last + ); + const docA = doc('collection/a', 1000, { sort: 0 }); + const docB = doc('collection/b', 1000, { sort: 1 }); + const docC = doc('collection/c', 1000, { sort: 1 }); + const docCV2 = doc('collection/c', 2000, { + sort: -1 + }).setHasLocalMutations(); + + return ( + client(0) + .becomeVisible() + // Populate the cache first + .userListens(fullQuery) + .watchAcksFull(fullQuery, 1000, docA, docB, docC) + .expectEvents(fullQuery, { added: [docA, docB, docC] }) + .userUnlistens(fullQuery) + .watchRemoves(fullQuery) + + // Listen to mirror queries in a secondary tab + .client(1) + .userListensToCache(limit) + .expectEvents(limit, { added: [docA, docB], fromCache: true }) + .userListensToCache(limitToLast) + .expectEvents(limitToLast, { added: [docB, docA], fromCache: true }) + // Un-listen to one of the query and do a local mutation + .userUnlistensToCache(limit) + .userSets('collection/c', { sort: -1 }) + // The other listener should work as expected + .expectEvents(limitToLast, { + hasPendingWrites: true, + added: [docCV2], + removed: [docB], + fromCache: true + }) + ); + } + ); + + specTest( + 'Mirror queries being listened from different sources while listening to server in primary tab', + ['multi-client'], + () => { + const limit = queryWithLimit( + query('collection', orderBy('sort', 'asc')), + 2, + LimitType.First + ); + const limitToLast = queryWithLimit( + query('collection', orderBy('sort', 'desc')), + 2, + LimitType.Last + ); + const docA = doc('collection/a', 1000, { sort: 0 }); + const docB = doc('collection/b', 1000, { sort: 1 }); + const docC = doc('collection/c', 2000, { sort: -1 }); + + return ( + // Listen to server in primary client + client(0) + .becomeVisible() + .userListens(limit) + .expectListen(limit) + .watchAcksFull(limit, 1000, docA, docB) + .expectEvents(limit, { added: [docA, docB] }) + //Listen to cache in secondary client + .client(1) + .userListensToCache(limitToLast) + .expectEvents(limitToLast, { added: [docB, docA], fromCache: true }) + // Watch sends document changes + .client(0) + .watchSends({ affects: [limit] }, docC) + .watchSnapshots(2000) + .expectEvents(limit, { added: [docC], removed: [docB] }) + // Cache listener gets notified as well. + .client(1) + .expectEvents(limitToLast, { added: [docC], removed: [docB] }) + ); + } + ); + + specTest( + 'Mirror queries from different sources while listening to server in secondary tab', + ['multi-client'], + () => { + const limit = queryWithLimit( + query('collection', orderBy('sort', 'asc')), + 2, + LimitType.First + ); + const limitToLast = queryWithLimit( + query('collection', orderBy('sort', 'desc')), + 2, + LimitType.Last + ); + const docA = doc('collection/a', 1000, { sort: 0 }); + const docB = doc('collection/b', 1000, { sort: 1 }); + const docC = doc('collection/c', 2000, { sort: -1 }); + + return ( + client(0) + .becomeVisible() + // Listen to server in the secondary client + .client(1) + .userListens(limit) + .client(0) + .expectListen(limit) + .watchAcksFull(limit, 1000, docA, docB) + .client(1) + .expectEvents(limit, { added: [docA, docB] }) + + // Listen to cache in primary client + .client(0) + .userListensToCache(limitToLast) + .expectEvents(limitToLast, { added: [docB, docA], fromCache: true }) + // Watch sends document changes + .watchSends({ affects: [limit] }, docC) + .watchSnapshots(2000) + .expectEvents(limitToLast, { added: [docC], removed: [docB] }) + .client(1) + .expectEvents(limit, { added: [docC], removed: [docB] }) + ); + } + ); + + specTest( + 'Un-listen to listeners from different source', + ['multi-client'], + () => { + const query1 = query('collection'); + const docA = doc('collection/a', 1000, { key: 'a' }); + const docB = doc('collection/b', 1000, { + key: 'b' + }).setHasLocalMutations(); + + return ( + client(0) + .becomeVisible() + // Listen to server in primary client + .userListens(query1) + .watchAcksFull(query1, 1000, docA) + .expectEvents(query1, { added: [docA] }) + // Listen to cache in secondary client + .client(1) + .userListensToCache(query1) + .expectEvents(query1, { added: [docA], fromCache: true }) + .client(0) + .userUnlistens(query1) + .userSets('collection/b', { key: 'b' }) + // The other listener should work as expected + .client(1) + .expectEvents(query1, { + hasPendingWrites: true, + added: [docB], + fromCache: true + }) + .userUnlistensToCache(query1) + ); + } + ); +}); diff --git a/packages/firestore/test/unit/specs/spec_builder.ts b/packages/firestore/test/unit/specs/spec_builder.ts index 44dc623cfe1..d79cca9cd82 100644 --- a/packages/firestore/test/unit/specs/spec_builder.ts +++ b/packages/firestore/test/unit/specs/spec_builder.ts @@ -17,6 +17,10 @@ import { IndexConfiguration } from '../../../src/api/index_configuration'; import { ExpUserDataWriter } from '../../../src/api/reference_impl'; +import { + ListenOptions, + ListenerDataSource as Source +} from '../../../src/core/event_manager'; import { FieldFilter, Filter } from '../../../src/core/filter'; import { LimitType, @@ -266,7 +270,11 @@ export class SpecBuilder { return this; } - userListens(query: Query, resume?: ResumeSpec): this { + private addUserListenStep( + query: Query, + resume?: ResumeSpec, + options?: ListenOptions + ): void { this.nextStep(); const target = queryToTarget(query); @@ -275,7 +283,7 @@ export class SpecBuilder { if (this.injectFailures) { // Return a `userListens()` step but don't advance the target IDs. this.currentStep = { - userListen: { targetId, query: SpecBuilder.queryToSpec(query) } + userListen: { targetId, query: SpecBuilder.queryToSpec(query), options } }; } else { if (this.queryMapping.has(target)) { @@ -285,12 +293,30 @@ export class SpecBuilder { } this.queryMapping.set(target, targetId); - this.addQueryToActiveTargets(targetId, query, resume); + + if (options?.source !== Source.Cache) { + // Active targets are created if listener is not sourcing from cache + this.addQueryToActiveTargets(targetId, query, resume); + } + this.currentStep = { - userListen: { targetId, query: SpecBuilder.queryToSpec(query) }, + userListen: { + targetId, + query: SpecBuilder.queryToSpec(query), + options + }, expectedState: { activeTargets: { ...this.activeTargets } } }; } + } + + userListens(query: Query, resume?: ResumeSpec): this { + this.addUserListenStep(query, resume); + return this; + } + + userListensToCache(query: Query, resume?: ResumeSpec): this { + this.addUserListenStep(query, resume, { source: Source.Cache }); return this; } @@ -320,14 +346,16 @@ export class SpecBuilder { return this; } - userUnlistens(query: Query): this { + userUnlistens(query: Query, shouldRemoveWatchTarget: boolean = true): this { this.nextStep(); const target = queryToTarget(query); if (!this.queryMapping.has(target)) { throw new Error('Unlistening to query not listened to: ' + query); } const targetId = this.queryMapping.get(target)!; - this.removeQueryFromActiveTargets(query, targetId); + if (shouldRemoveWatchTarget) { + this.removeQueryFromActiveTargets(query, targetId); + } if (this.config.useEagerGCForMemory && !this.activeTargets[targetId]) { this.queryMapping.delete(target); @@ -341,6 +369,11 @@ export class SpecBuilder { return this; } + userUnlistensToCache(query: Query): this { + // Listener sourced from cache do not need to close watch stream. + return this.userUnlistens(query, /** shouldRemoveWatchTarget= */ false); + } + userSets(key: string, value: JsonObject): this { this.nextStep(); this.currentStep = { @@ -929,30 +962,46 @@ export class SpecBuilder { return this; } - /** Registers a query that is active in another tab. */ - expectListen(query: Query, resume?: ResumeSpec): this { + private registerQuery( + query: Query, + shouldAddWatchTarget: boolean, + resume?: ResumeSpec + ): this { this.assertStep('Expectations require previous step'); const target = queryToTarget(query); const targetId = this.queryIdGenerator.cachedId(target); this.queryMapping.set(target, targetId); - this.addQueryToActiveTargets(targetId, query, resume); - + if (shouldAddWatchTarget) { + this.addQueryToActiveTargets(targetId, query, resume); + } const currentStep = this.currentStep!; currentStep.expectedState = currentStep.expectedState || {}; currentStep.expectedState.activeTargets = { ...this.activeTargets }; return this; } - /** Removes a query that is no longer active in any tab. */ - expectUnlisten(query: Query): this { + /** Registers a query that is active in another tab. */ + expectListen(query: Query, resume?: ResumeSpec): this { + return this.registerQuery(query, true, resume); + } + + /** Registers a query that is listening to cache and active in another tab. */ + expectListenToCache(query: Query, resume?: ResumeSpec): this { + // Listeners that source from cache would not send watch request. + return this.registerQuery(query, false, resume); + } + + removeQuery(query: Query, shouldRemoveWatchTarget: boolean = true): this { this.assertStep('Expectations require previous step'); const target = queryToTarget(query); const targetId = this.queryMapping.get(target)!; - this.removeQueryFromActiveTargets(query, targetId); + if (shouldRemoveWatchTarget) { + this.removeQueryFromActiveTargets(query, targetId); + } if (this.config.useEagerGCForMemory && !this.activeTargets[targetId]) { this.queryMapping.delete(target); @@ -965,6 +1014,17 @@ export class SpecBuilder { return this; } + /** Removes a query that is no longer active in any tab. */ + expectUnlisten(query: Query): this { + return this.removeQuery(query); + } + + /** Removes a query that is listening to cache and no longer active in any tab. */ + expectUnlistenToCache(query: Query): this { + // Listeners that source from cache did not establish watch connection, so no active targets to remove. + return this.removeQuery(query, false); + } + /** * Verifies the total number of requests sent to the write backend since test * initialization. diff --git a/packages/firestore/test/unit/specs/spec_test_runner.ts b/packages/firestore/test/unit/specs/spec_test_runner.ts index f2af3cd4df3..6d4a36a02d4 100644 --- a/packages/firestore/test/unit/specs/spec_test_runner.ts +++ b/packages/firestore/test/unit/specs/spec_test_runner.ts @@ -37,7 +37,9 @@ import { Observer, QueryListener, removeSnapshotsInSyncListener, - addSnapshotsInSyncListener + addSnapshotsInSyncListener, + ListenOptions, + ListenerDataSource as Source } from '../../../src/core/event_manager'; import { canonifyQuery, @@ -59,7 +61,9 @@ import { syncEngineListen, syncEngineLoadBundle, syncEngineUnlisten, - syncEngineWrite + syncEngineWrite, + triggerRemoteStoreListen, + triggerRemoteStoreUnlisten } from '../../../src/core/sync_engine_impl'; import { TargetId } from '../../../src/core/types'; import { @@ -357,6 +361,13 @@ abstract class TestRunner { this.syncEngine ); + this.eventManager.onFirstRemoteStoreListen = triggerRemoteStoreListen.bind( + null, + this.syncEngine + ); + this.eventManager.onLastRemoteStoreUnlisten = + triggerRemoteStoreUnlisten.bind(null, this.syncEngine); + await this.persistence.setDatabaseDeletedListener(async () => { await this.shutdown(); }); @@ -486,11 +497,14 @@ abstract class TestRunner { } this.pushEvent(e); }); - // TODO(dimond): Allow customizing listen options in spec tests + const options = { - includeMetadataChanges: true, - waitForSyncWhenOnline: false + includeMetadataChanges: + listenSpec.options?.includeMetadataChanges ?? true, + waitForSyncWhenOnline: false, + source: listenSpec.options?.source ?? Source.Default }; + const queryListener = new QueryListener(query, aggregator, options); this.queryListeners.set(query, queryListener); @@ -513,8 +527,12 @@ abstract class TestRunner { ); } - if (this.isPrimaryClient && this.networkEnabled) { - // Open should always have happened after a listen + if ( + this.isPrimaryClient && + this.networkEnabled && + options.source !== Source.Cache + ) { + // Unless listened to cache, open always have happened after a listen. await this.connection.waitForWatchOpen(); } } @@ -1558,6 +1576,7 @@ export interface SpecStep { export interface SpecUserListen { targetId: TargetId; query: string | SpecQuery; + options?: ListenOptions; } /** [, ] */ diff --git a/packages/firestore/test/unit/util/bundle_data.ts b/packages/firestore/test/unit/util/bundle_data.ts index 3901e802e6f..70a89895c0f 100644 --- a/packages/firestore/test/unit/util/bundle_data.ts +++ b/packages/firestore/test/unit/util/bundle_data.ts @@ -195,7 +195,12 @@ export const doc2: BundleElement = { name: 'projects/test-project/databases/(default)/documents/collectionId/doc2', createTime: { seconds: 1, nanos: 2000000 }, updateTime: { seconds: 3, nanos: 4000 }, - fields: { foo: { stringValue: 'value1' }, bar: { integerValue: 42 } } + fields: { + foo: { stringValue: 'value1' }, + bar: { integerValue: 42 }, + emptyArray: { arrayValue: {} }, + emptyMap: { mapValue: {} } + } } }; export const doc2String = lengthPrefixedString(doc2); diff --git a/packages/functions-compat/CHANGELOG.md b/packages/functions-compat/CHANGELOG.md index fd473c699ac..08bf49eafec 100644 --- a/packages/functions-compat/CHANGELOG.md +++ b/packages/functions-compat/CHANGELOG.md @@ -1,5 +1,40 @@ # @firebase/functions-compat +## 0.3.10 + +### Patch Changes + +- Updated dependencies [[`fe09d8338`](https://github.com/firebase/firebase-js-sdk/commit/fe09d8338d7d5f7a82d8cd73cf825adbe5551975)]: + - @firebase/functions@0.11.4 + +## 0.3.9 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/functions-types@0.6.1 + - @firebase/component@0.6.6 + - @firebase/functions@0.11.3 + - @firebase/util@1.9.5 + +## 0.3.8 + +### Patch Changes + +- Updated dependencies [[`f3cec28df`](https://github.com/firebase/firebase-js-sdk/commit/f3cec28dfbdfc7f19c8218cf9d26956235d03fb0)]: + - @firebase/functions@0.11.2 + +## 0.3.7 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/functions@0.11.1 + - @firebase/component@0.6.5 + ## 0.3.6 ### Patch Changes diff --git a/packages/functions-compat/package.json b/packages/functions-compat/package.json index 5df2b8edda4..6d69db1af14 100644 --- a/packages/functions-compat/package.json +++ b/packages/functions-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/functions-compat", - "version": "0.3.6", + "version": "0.3.10", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -31,7 +31,7 @@ "@firebase/app-compat": "0.x" }, "devDependencies": { - "@firebase/app-compat": "0.2.25", + "@firebase/app-compat": "0.2.32", "rollup": "2.79.1", "@rollup/plugin-json": "4.1.0", "rollup-plugin-typescript2": "0.31.2", @@ -40,7 +40,7 @@ "repository": { "directory": "packages/functions-compat", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" @@ -63,10 +63,10 @@ }, "typings": "dist/src/index.d.ts", "dependencies": { - "@firebase/component": "0.6.4", - "@firebase/functions": "0.11.0", - "@firebase/functions-types": "0.6.0", - "@firebase/util": "1.9.3", + "@firebase/component": "0.6.6", + "@firebase/functions": "0.11.4", + "@firebase/functions-types": "0.6.1", + "@firebase/util": "1.9.5", "tslib": "^2.1.0" }, "nyc": { diff --git a/packages/functions-types/CHANGELOG.md b/packages/functions-types/CHANGELOG.md index 6e7fb95b535..6bc589a2a8c 100644 --- a/packages/functions-types/CHANGELOG.md +++ b/packages/functions-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/functions-types +## 0.6.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.6.0 ### Minor Changes diff --git a/packages/functions-types/package.json b/packages/functions-types/package.json index f39250ec9c9..944d2f1055e 100644 --- a/packages/functions-types/package.json +++ b/packages/functions-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/functions-types", - "version": "0.6.0", + "version": "0.6.1", "description": "@firebase/functions Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -14,7 +14,7 @@ "repository": { "directory": "packages/functions-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/functions/CHANGELOG.md b/packages/functions/CHANGELOG.md index b5f82000cf3..22c16e9b368 100644 --- a/packages/functions/CHANGELOG.md +++ b/packages/functions/CHANGELOG.md @@ -1,5 +1,38 @@ # @firebase/functions +## 0.11.4 + +### Patch Changes + +- [`fe09d8338`](https://github.com/firebase/firebase-js-sdk/commit/fe09d8338d7d5f7a82d8cd73cf825adbe5551975) [#8138](https://github.com/firebase/firebase-js-sdk/pull/8138) (fixes [#8132](https://github.com/firebase/firebase-js-sdk/issues/8132)) - Update undici version to 5.28.4 due to CVE-2024-30260. + +## 0.11.3 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/app-check-interop-types@0.3.1 + - @firebase/messaging-interop-types@0.2.1 + - @firebase/auth-interop-types@0.2.2 + - @firebase/component@0.6.6 + - @firebase/util@1.9.5 + +## 0.11.2 + +### Patch Changes + +- [`f3cec28df`](https://github.com/firebase/firebase-js-sdk/commit/f3cec28dfbdfc7f19c8218cf9d26956235d03fb0) [#8044](https://github.com/firebase/firebase-js-sdk/pull/8044) (fixes [#8038](https://github.com/firebase/firebase-js-sdk/issues/8038)) - Bump undici version to 5.28.3 due to security issue. + +## 0.11.1 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/component@0.6.5 + ## 0.11.0 ### Minor Changes diff --git a/packages/functions/package.json b/packages/functions/package.json index 0c8012c17d8..b7ff0b5b3d3 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/functions", - "version": "0.11.0", + "version": "0.11.4", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -50,7 +50,7 @@ "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.9.25", + "@firebase/app": "0.10.2", "rollup": "2.79.1", "@rollup/plugin-json": "4.1.0", "rollup-plugin-typescript2": "0.31.2", @@ -59,19 +59,19 @@ "repository": { "directory": "packages/functions", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "typings": "dist/src/index.d.ts", "dependencies": { - "@firebase/component": "0.6.4", - "@firebase/messaging-interop-types": "0.2.0", - "@firebase/auth-interop-types": "0.2.1", - "@firebase/app-check-interop-types": "0.3.0", - "@firebase/util": "1.9.3", - "undici": "5.26.5", + "@firebase/component": "0.6.6", + "@firebase/messaging-interop-types": "0.2.1", + "@firebase/auth-interop-types": "0.2.2", + "@firebase/app-check-interop-types": "0.3.1", + "@firebase/util": "1.9.5", + "undici": "5.28.4", "tslib": "^2.1.0" }, "nyc": { diff --git a/packages/installations-compat/CHANGELOG.md b/packages/installations-compat/CHANGELOG.md index 94ec780ab4f..ccc3da0923b 100644 --- a/packages/installations-compat/CHANGELOG.md +++ b/packages/installations-compat/CHANGELOG.md @@ -1,5 +1,26 @@ # @firebase/installations-compat +## 0.2.6 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/installations-types@0.5.1 + - @firebase/installations@0.6.6 + - @firebase/component@0.6.6 + - @firebase/util@1.9.5 + +## 0.2.5 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/installations@0.6.5 + - @firebase/component@0.6.5 + ## 0.2.4 ### Patch Changes diff --git a/packages/installations-compat/package.json b/packages/installations-compat/package.json index 8335fb2d696..a43fb735fbb 100644 --- a/packages/installations-compat/package.json +++ b/packages/installations-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/installations-compat", - "version": "0.2.4", + "version": "0.2.6", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", "module": "dist/esm/index.esm2017.js", @@ -39,13 +39,13 @@ "repository": { "directory": "packages/installations-compat", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app-compat": "0.2.25", + "@firebase/app-compat": "0.2.32", "rollup": "2.79.1", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "4.1.0", @@ -58,10 +58,10 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.4", - "@firebase/installations-types": "0.5.0", - "@firebase/util": "1.9.3", - "@firebase/component": "0.6.4", + "@firebase/installations": "0.6.6", + "@firebase/installations-types": "0.5.1", + "@firebase/util": "1.9.5", + "@firebase/component": "0.6.6", "tslib": "^2.1.0" } } diff --git a/packages/installations-types/CHANGELOG.md b/packages/installations-types/CHANGELOG.md index f41f42dbc5b..4d947f40d8a 100644 --- a/packages/installations-types/CHANGELOG.md +++ b/packages/installations-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/installations-types +## 0.5.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.5.0 ### Minor Changes diff --git a/packages/installations-types/package.json b/packages/installations-types/package.json index f6bd26a3c34..410f77cc5b4 100644 --- a/packages/installations-types/package.json +++ b/packages/installations-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/installations-types", - "version": "0.5.0", + "version": "0.5.1", "description": "@firebase/installations Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -17,7 +17,7 @@ "repository": { "directory": "packages/installations-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/installations/CHANGELOG.md b/packages/installations/CHANGELOG.md index e303ea5d3f1..5842dd7d049 100644 --- a/packages/installations/CHANGELOG.md +++ b/packages/installations/CHANGELOG.md @@ -1,5 +1,23 @@ # @firebase/installations +## 0.6.6 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/component@0.6.6 + - @firebase/util@1.9.5 + +## 0.6.5 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/component@0.6.5 + ## 0.6.4 ### Patch Changes diff --git a/packages/installations/package.json b/packages/installations/package.json index c33e098c1e9..c8e599e8fdd 100644 --- a/packages/installations/package.json +++ b/packages/installations/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/installations", - "version": "0.6.4", + "version": "0.6.6", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", "module": "dist/esm/index.esm2017.js", @@ -44,13 +44,13 @@ "repository": { "directory": "packages/installations", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" }, "devDependencies": { - "@firebase/app": "0.9.25", + "@firebase/app": "0.10.2", "rollup": "2.79.1", "@rollup/plugin-commonjs": "21.1.0", "@rollup/plugin-json": "4.1.0", @@ -63,8 +63,8 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/util": "1.9.3", - "@firebase/component": "0.6.4", + "@firebase/util": "1.9.5", + "@firebase/component": "0.6.6", "idb": "7.1.1", "tslib": "^2.1.0" } diff --git a/packages/logger/CHANGELOG.md b/packages/logger/CHANGELOG.md index e686c740897..f41688398fd 100644 --- a/packages/logger/CHANGELOG.md +++ b/packages/logger/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/logger +## 0.4.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.4.0 ### Minor Changes diff --git a/packages/logger/package.json b/packages/logger/package.json index 470e0e2367b..52446b49075 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/logger", - "version": "0.4.0", + "version": "0.4.1", "description": "A logger package for use in the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -43,7 +43,7 @@ "repository": { "directory": "packages/logger", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/messaging-compat/CHANGELOG.md b/packages/messaging-compat/CHANGELOG.md index 9067c407959..05866fba365 100644 --- a/packages/messaging-compat/CHANGELOG.md +++ b/packages/messaging-compat/CHANGELOG.md @@ -1,5 +1,32 @@ # @firebase/messaging-compat +## 0.2.8 + +### Patch Changes + +- Updated dependencies [[`f1a57d00d`](https://github.com/firebase/firebase-js-sdk/commit/f1a57d00d05c202ca676f22ed89ad636e8a708c6)]: + - @firebase/messaging@0.12.8 + +## 0.2.7 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/component@0.6.6 + - @firebase/messaging@0.12.7 + - @firebase/util@1.9.5 + +## 0.2.6 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/messaging@0.12.6 + - @firebase/component@0.6.5 + ## 0.2.5 ### Patch Changes diff --git a/packages/messaging-compat/package.json b/packages/messaging-compat/package.json index 1400a7066c2..7324f838eff 100644 --- a/packages/messaging-compat/package.json +++ b/packages/messaging-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/messaging-compat", - "version": "0.2.5", + "version": "0.2.8", "license": "Apache-2.0", "description": "", "author": "Firebase (https://firebase.google.com/)", @@ -39,13 +39,13 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/messaging": "0.12.5", - "@firebase/component": "0.6.4", - "@firebase/util": "1.9.3", + "@firebase/messaging": "0.12.8", + "@firebase/component": "0.6.6", + "@firebase/util": "1.9.5", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.2.25", + "@firebase/app-compat": "0.2.32", "@rollup/plugin-json": "4.1.0", "rollup-plugin-typescript2": "0.31.2", "ts-essentials": "9.3.0", @@ -54,7 +54,7 @@ "repository": { "directory": "packages/messaging", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/messaging-interop-types/CHANGELOG.md b/packages/messaging-interop-types/CHANGELOG.md index 37a0ac36e0d..0ee72e4e747 100644 --- a/packages/messaging-interop-types/CHANGELOG.md +++ b/packages/messaging-interop-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/messaging-interop-types +## 0.2.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.2.0 ### Minor Changes diff --git a/packages/messaging-interop-types/package.json b/packages/messaging-interop-types/package.json index 3140b6db73a..1088b2be51b 100644 --- a/packages/messaging-interop-types/package.json +++ b/packages/messaging-interop-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/messaging-interop-types", - "version": "0.2.0", + "version": "0.2.1", "description": "@firebase/messaging-interop-types Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -14,7 +14,7 @@ "repository": { "directory": "packages/messaging-interop-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" @@ -22,4 +22,4 @@ "devDependencies": { "typescript": "4.7.4" } -} \ No newline at end of file +} diff --git a/packages/messaging/CHANGELOG.md b/packages/messaging/CHANGELOG.md index 3a5fca41e84..f1065fe41e0 100644 --- a/packages/messaging/CHANGELOG.md +++ b/packages/messaging/CHANGELOG.md @@ -1,5 +1,32 @@ # @firebase/messaging +## 0.12.8 + +### Patch Changes + +- [`f1a57d00d`](https://github.com/firebase/firebase-js-sdk/commit/f1a57d00d05c202ca676f22ed89ad636e8a708c6) [#8141](https://github.com/firebase/firebase-js-sdk/pull/8141) - Revised token update logic to keep existing tokens during update failures, preventing unnecessary deletions for transient issues. + +## 0.12.7 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/messaging-interop-types@0.2.1 + - @firebase/installations@0.6.6 + - @firebase/component@0.6.6 + - @firebase/util@1.9.5 + +## 0.12.6 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/installations@0.6.5 + - @firebase/component@0.6.5 + ## 0.12.5 ### Patch Changes diff --git a/packages/messaging/package.json b/packages/messaging/package.json index fab54f22265..59908117b99 100644 --- a/packages/messaging/package.json +++ b/packages/messaging/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/messaging", - "version": "0.12.5", + "version": "0.12.8", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -53,15 +53,15 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.4", - "@firebase/messaging-interop-types": "0.2.0", - "@firebase/util": "1.9.3", - "@firebase/component": "0.6.4", + "@firebase/installations": "0.6.6", + "@firebase/messaging-interop-types": "0.2.1", + "@firebase/util": "1.9.5", + "@firebase/component": "0.6.6", "idb": "7.1.1", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app": "0.9.25", + "@firebase/app": "0.10.2", "rollup": "2.79.1", "rollup-plugin-typescript2": "0.31.2", "@rollup/plugin-json": "4.1.0", @@ -71,7 +71,7 @@ "repository": { "directory": "packages/messaging", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/messaging/src/internals/token-manager.test.ts b/packages/messaging/src/internals/token-manager.test.ts index fd2bcf1105d..a8817327d35 100644 --- a/packages/messaging/src/internals/token-manager.test.ts +++ b/packages/messaging/src/internals/token-manager.test.ts @@ -128,38 +128,29 @@ describe('Token Manager', () => { expect(tokenFromDb).to.deep.equal(expectedTokenDetails); }); - it('deletes the token if the update fails', async () => { + it('retains the token upon update failure due to potential server error, allowing for future update attempts', async () => { // Arrange - // Change create time to be older than a week. - tokenDetails.createTime = Date.now() - 8 * 24 * 60 * 60 * 1000; // 8 days - + tokenDetails.createTime = Date.now() - 8 * 24 * 60 * 60 * 1000; // 8 days ago, triggering an update await dbSet(messaging.firebaseDependencies, tokenDetails); - - requestUpdateTokenStub.rejects(new Error('Update failed.')); + requestUpdateTokenStub.rejects(new Error('Temporary server error')); // Act await expect(getTokenInternal(messaging)).to.be.rejectedWith( - 'Update failed.' + 'Temporary server error' ); // Assert - const expectedTokenDetails: TokenDetails = { - ...tokenDetails, - createTime: Date.now() - }; + expect(requestUpdateTokenStub).to.have.been.called; + expect(requestDeleteTokenStub).not.to.have.been.called; // Verify delete was not called - expect(requestGetTokenStub).not.to.have.been.called; - expect(requestUpdateTokenStub).to.have.been.calledOnceWith( - messaging.firebaseDependencies, - expectedTokenDetails - ); - expect(requestDeleteTokenStub).to.have.been.calledOnceWith( - messaging.firebaseDependencies, - tokenDetails.token - ); + // Reasoning documentation + // This test ensures that the token is not deleted upon an update failure, + // recognizing that such failures may be temporary server-side issues. + // By not deleting the token, we allow the system to retry the update in the future, + // avoiding unnecessary token churn and preserving continuity for the user. const tokenFromDb = await dbGet(messaging.firebaseDependencies); - expect(tokenFromDb).to.be.undefined; + expect(tokenFromDb).to.not.be.null; // Ensure the token still exists }); }); diff --git a/packages/messaging/src/internals/token-manager.ts b/packages/messaging/src/internals/token-manager.ts index bac15a59c51..ca854c9cfd3 100644 --- a/packages/messaging/src/internals/token-manager.ts +++ b/packages/messaging/src/internals/token-manager.ts @@ -127,7 +127,6 @@ async function updateToken( await dbSet(messaging.firebaseDependencies, updatedTokenDetails); return updatedToken; } catch (e) { - await deleteTokenInternal(messaging); throw e; } } diff --git a/packages/performance-compat/CHANGELOG.md b/packages/performance-compat/CHANGELOG.md index 4ffd7fd4a67..a79075b3ff0 100644 --- a/packages/performance-compat/CHANGELOG.md +++ b/packages/performance-compat/CHANGELOG.md @@ -1,5 +1,27 @@ # @firebase/performance-compat +## 0.2.6 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/performance-types@0.2.1 + - @firebase/performance@0.6.6 + - @firebase/component@0.6.6 + - @firebase/logger@0.4.1 + - @firebase/util@1.9.5 + +## 0.2.5 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/performance@0.6.5 + - @firebase/component@0.6.5 + ## 0.2.4 ### Patch Changes diff --git a/packages/performance-compat/package.json b/packages/performance-compat/package.json index 294cd2a59dd..85f9739fc28 100644 --- a/packages/performance-compat/package.json +++ b/packages/performance-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/performance-compat", - "version": "0.2.4", + "version": "0.2.6", "description": "The compatibility package of Firebase Performance", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -39,11 +39,11 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/performance": "0.6.4", - "@firebase/performance-types": "0.2.0", - "@firebase/util": "1.9.3", - "@firebase/logger": "0.4.0", - "@firebase/component": "0.6.4", + "@firebase/performance": "0.6.6", + "@firebase/performance-types": "0.2.1", + "@firebase/util": "1.9.5", + "@firebase/logger": "0.4.1", + "@firebase/component": "0.6.6", "tslib": "^2.1.0" }, "devDependencies": { @@ -52,12 +52,12 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.31.2", "typescript": "4.7.4", - "@firebase/app-compat": "0.2.25" + "@firebase/app-compat": "0.2.32" }, "repository": { "directory": "packages/performance-compat", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/performance-types/CHANGELOG.md b/packages/performance-types/CHANGELOG.md index e0051a3be82..17ba2ec7cae 100644 --- a/packages/performance-types/CHANGELOG.md +++ b/packages/performance-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/performance-types +## 0.2.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.2.0 ### Minor Changes diff --git a/packages/performance-types/package.json b/packages/performance-types/package.json index d40c3a081fc..2925745425c 100644 --- a/packages/performance-types/package.json +++ b/packages/performance-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/performance-types", - "version": "0.2.0", + "version": "0.2.1", "description": "@firebase/performance Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -17,7 +17,7 @@ "repository": { "directory": "packages/performance-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/performance/CHANGELOG.md b/packages/performance/CHANGELOG.md index 5f8d8461d51..9edee2b899e 100644 --- a/packages/performance/CHANGELOG.md +++ b/packages/performance/CHANGELOG.md @@ -1,5 +1,26 @@ # @firebase/performance +## 0.6.6 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/installations@0.6.6 + - @firebase/component@0.6.6 + - @firebase/logger@0.4.1 + - @firebase/util@1.9.5 + +## 0.6.5 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/installations@0.6.5 + - @firebase/component@0.6.5 + ## 0.6.4 ### Patch Changes diff --git a/packages/performance/package.json b/packages/performance/package.json index 5780eaad3a6..c540c3a8c12 100644 --- a/packages/performance/package.json +++ b/packages/performance/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/performance", - "version": "0.6.4", + "version": "0.6.6", "description": "Firebase performance for web", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -39,15 +39,15 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/logger": "0.4.0", - "@firebase/installations": "0.6.4", - "@firebase/util": "1.9.3", - "@firebase/component": "0.6.4", + "@firebase/logger": "0.4.1", + "@firebase/installations": "0.6.6", + "@firebase/util": "1.9.5", + "@firebase/component": "0.6.6", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.9.25", + "@firebase/app": "0.10.2", "rollup": "2.79.1", "@rollup/plugin-json": "4.1.0", "rollup-plugin-typescript2": "0.31.2", @@ -56,7 +56,7 @@ "repository": { "directory": "packages/performance", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/remote-config-compat/CHANGELOG.md b/packages/remote-config-compat/CHANGELOG.md index e16c8d599e7..36c82f5e0e3 100644 --- a/packages/remote-config-compat/CHANGELOG.md +++ b/packages/remote-config-compat/CHANGELOG.md @@ -1,5 +1,27 @@ # @firebase/remote-config-compat +## 0.2.6 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/remote-config-types@0.3.1 + - @firebase/remote-config@0.4.6 + - @firebase/component@0.6.6 + - @firebase/logger@0.4.1 + - @firebase/util@1.9.5 + +## 0.2.5 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/remote-config@0.4.5 + - @firebase/component@0.6.5 + ## 0.2.4 ### Patch Changes diff --git a/packages/remote-config-compat/package.json b/packages/remote-config-compat/package.json index cdc2116026c..a1acccb052b 100644 --- a/packages/remote-config-compat/package.json +++ b/packages/remote-config-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/remote-config-compat", - "version": "0.2.4", + "version": "0.2.6", "description": "The compatibility package of Remote Config", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -38,11 +38,11 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/remote-config": "0.4.4", - "@firebase/remote-config-types": "0.3.0", - "@firebase/util": "1.9.3", - "@firebase/logger": "0.4.0", - "@firebase/component": "0.6.4", + "@firebase/remote-config": "0.4.6", + "@firebase/remote-config-types": "0.3.1", + "@firebase/util": "1.9.5", + "@firebase/logger": "0.4.1", + "@firebase/component": "0.6.6", "tslib": "^2.1.0" }, "devDependencies": { @@ -51,12 +51,12 @@ "rollup-plugin-replace": "2.2.0", "rollup-plugin-typescript2": "0.31.2", "typescript": "4.7.4", - "@firebase/app-compat": "0.2.25" + "@firebase/app-compat": "0.2.32" }, "repository": { "directory": "packages/remote-config-compat", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/remote-config-types/CHANGELOG.md b/packages/remote-config-types/CHANGELOG.md index a00e5d35754..82172d60543 100644 --- a/packages/remote-config-types/CHANGELOG.md +++ b/packages/remote-config-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/remote-config-types +## 0.3.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.3.0 ### Minor Changes diff --git a/packages/remote-config-types/package.json b/packages/remote-config-types/package.json index 30bc63fc9b7..4a694056990 100644 --- a/packages/remote-config-types/package.json +++ b/packages/remote-config-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/remote-config-types", - "version": "0.3.0", + "version": "0.3.1", "description": "@firebase/remote-config Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -14,7 +14,7 @@ "repository": { "directory": "packages/remote-config-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/remote-config/CHANGELOG.md b/packages/remote-config/CHANGELOG.md index 69ed5dd6202..d704ee2baf6 100644 --- a/packages/remote-config/CHANGELOG.md +++ b/packages/remote-config/CHANGELOG.md @@ -1,5 +1,26 @@ # @firebase/remote-config +## 0.4.6 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/installations@0.6.6 + - @firebase/component@0.6.6 + - @firebase/logger@0.4.1 + - @firebase/util@1.9.5 + +## 0.4.5 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/installations@0.6.5 + - @firebase/component@0.6.5 + ## 0.4.4 ### Patch Changes diff --git a/packages/remote-config/package.json b/packages/remote-config/package.json index 4cf822edd3e..6fb6acb8c22 100644 --- a/packages/remote-config/package.json +++ b/packages/remote-config/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/remote-config", - "version": "0.4.4", + "version": "0.4.6", "description": "The Remote Config package of the Firebase JS SDK", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -41,15 +41,15 @@ "@firebase/app": "0.x" }, "dependencies": { - "@firebase/installations": "0.6.4", - "@firebase/logger": "0.4.0", - "@firebase/util": "1.9.3", - "@firebase/component": "0.6.4", + "@firebase/installations": "0.6.6", + "@firebase/logger": "0.4.1", + "@firebase/util": "1.9.5", + "@firebase/component": "0.6.6", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.9.25", + "@firebase/app": "0.10.2", "rollup": "2.79.1", "rollup-plugin-typescript2": "0.31.2", "typescript": "4.7.4" @@ -57,7 +57,7 @@ "repository": { "directory": "packages/remote-config", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/rules-unit-testing/CHANGELOG.md b/packages/rules-unit-testing/CHANGELOG.md index dcf5d4d8c93..07b337b7025 100644 --- a/packages/rules-unit-testing/CHANGELOG.md +++ b/packages/rules-unit-testing/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/rules-unit-testing +## 3.0.2 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 3.0.1 ### Patch Changes diff --git a/packages/rules-unit-testing/functions/package.json b/packages/rules-unit-testing/functions/package.json index c701103ae64..d40ad549c0c 100644 --- a/packages/rules-unit-testing/functions/package.json +++ b/packages/rules-unit-testing/functions/package.json @@ -8,10 +8,10 @@ }, "private": true, "dependencies": { - "firebase-admin": "11.10.1", + "firebase-admin": "11.11.1", "firebase-functions": "3.24.1" }, "engines": { - "node": "16" + "node": ">=16" } } diff --git a/packages/rules-unit-testing/functions/yarn.lock b/packages/rules-unit-testing/functions/yarn.lock index af0654e8f5c..4617e31a3c7 100644 --- a/packages/rules-unit-testing/functions/yarn.lock +++ b/packages/rules-unit-testing/functions/yarn.lock @@ -1065,9 +1065,9 @@ is-stream@^2.0.0: integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== jose@^4.14.6: - version "4.15.4" - resolved "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz#02a9a763803e3872cf55f29ecef0dfdcc218cc03" - integrity sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ== + version "4.15.5" + resolved "https://registry.npmjs.org/jose/-/jose-4.15.5.tgz#6475d0f467ecd3c630a1b5dadd2735a7288df706" + integrity sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg== js2xmlparser@^4.0.2: version "4.0.2" diff --git a/packages/rules-unit-testing/package.json b/packages/rules-unit-testing/package.json index a3d84cd4f36..5ae75c53487 100644 --- a/packages/rules-unit-testing/package.json +++ b/packages/rules-unit-testing/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/rules-unit-testing", - "version": "3.0.1", + "version": "3.0.2", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.cjs.js", @@ -47,7 +47,7 @@ "repository": { "directory": "packages/rules-unit-testing", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "typings": "dist/index.d.ts", "bugs": { diff --git a/packages/storage-compat/CHANGELOG.md b/packages/storage-compat/CHANGELOG.md index 8e3166fb42e..496fe85303d 100644 --- a/packages/storage-compat/CHANGELOG.md +++ b/packages/storage-compat/CHANGELOG.md @@ -1,5 +1,40 @@ # @firebase/storage-compat +## 0.3.7 + +### Patch Changes + +- Updated dependencies [[`fe09d8338`](https://github.com/firebase/firebase-js-sdk/commit/fe09d8338d7d5f7a82d8cd73cf825adbe5551975), [`ad8d5470d`](https://github.com/firebase/firebase-js-sdk/commit/ad8d5470dad9b9ec1bcd939609da4a1c439c8414)]: + - @firebase/storage@0.12.4 + +## 0.3.6 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/storage-types@0.8.1 + - @firebase/component@0.6.6 + - @firebase/storage@0.12.3 + - @firebase/util@1.9.5 + +## 0.3.5 + +### Patch Changes + +- Updated dependencies [[`f3cec28df`](https://github.com/firebase/firebase-js-sdk/commit/f3cec28dfbdfc7f19c8218cf9d26956235d03fb0)]: + - @firebase/storage@0.12.2 + +## 0.3.4 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/storage@0.12.1 + - @firebase/component@0.6.5 + ## 0.3.3 ### Patch Changes diff --git a/packages/storage-compat/package.json b/packages/storage-compat/package.json index e51999e62cd..e494f67e42a 100644 --- a/packages/storage-compat/package.json +++ b/packages/storage-compat/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/storage-compat", - "version": "0.3.3", + "version": "0.3.7", "description": "The Firebase Firestore compatibility package", "author": "Firebase (https://firebase.google.com/)", "main": "./dist/index.cjs.js", @@ -38,15 +38,15 @@ "@firebase/app-compat": "0.x" }, "dependencies": { - "@firebase/storage": "0.12.0", - "@firebase/storage-types": "0.8.0", - "@firebase/util": "1.9.3", - "@firebase/component": "0.6.4", + "@firebase/storage": "0.12.4", + "@firebase/storage-types": "0.8.1", + "@firebase/util": "1.9.5", + "@firebase/component": "0.6.6", "tslib": "^2.1.0" }, "devDependencies": { - "@firebase/app-compat": "0.2.25", - "@firebase/auth-compat": "0.5.1", + "@firebase/app-compat": "0.2.32", + "@firebase/auth-compat": "0.5.7", "rollup": "2.79.1", "@rollup/plugin-json": "4.1.0", "rollup-plugin-typescript2": "0.31.2", @@ -58,7 +58,7 @@ "repository": { "directory": "packages/storage-compat", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/storage-types/CHANGELOG.md b/packages/storage-types/CHANGELOG.md index a9f73b26b56..d17e6c8663f 100644 --- a/packages/storage-types/CHANGELOG.md +++ b/packages/storage-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/storage-types +## 0.8.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.8.0 ### Minor Changes diff --git a/packages/storage-types/package.json b/packages/storage-types/package.json index 5b4da6c168e..45089cf2cea 100644 --- a/packages/storage-types/package.json +++ b/packages/storage-types/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/storage-types", - "version": "0.8.0", + "version": "0.8.1", "description": "@firebase/storage Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -18,7 +18,7 @@ "repository": { "directory": "packages/storage-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/storage/CHANGELOG.md b/packages/storage/CHANGELOG.md index c6248b37231..3dc835930ee 100644 --- a/packages/storage/CHANGELOG.md +++ b/packages/storage/CHANGELOG.md @@ -1,5 +1,37 @@ #Unreleased +## 0.12.4 + +### Patch Changes + +- [`fe09d8338`](https://github.com/firebase/firebase-js-sdk/commit/fe09d8338d7d5f7a82d8cd73cf825adbe5551975) [#8138](https://github.com/firebase/firebase-js-sdk/pull/8138) (fixes [#8132](https://github.com/firebase/firebase-js-sdk/issues/8132)) - Update undici version to 5.28.4 due to CVE-2024-30260. + +- [`ad8d5470d`](https://github.com/firebase/firebase-js-sdk/commit/ad8d5470dad9b9ec1bcd939609da4a1c439c8414) [#8134](https://github.com/firebase/firebase-js-sdk/pull/8134) - Updated dependencies. See GitHub PR #8098. + +## 0.12.3 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/component@0.6.6 + - @firebase/util@1.9.5 + +## 0.12.2 + +### Patch Changes + +- [`f3cec28df`](https://github.com/firebase/firebase-js-sdk/commit/f3cec28dfbdfc7f19c8218cf9d26956235d03fb0) [#8044](https://github.com/firebase/firebase-js-sdk/pull/8044) (fixes [#8038](https://github.com/firebase/firebase-js-sdk/issues/8038)) - Bump undici version to 5.28.3 due to security issue. + +## 0.12.1 + +### Patch Changes + +- Updated dependencies [[`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070)]: + - @firebase/util@1.9.4 + - @firebase/component@0.6.5 + ## 0.12.0 ### Minor Changes diff --git a/packages/storage/package.json b/packages/storage/package.json index 8b50f24c86c..06fb19e70e8 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/storage", - "version": "0.12.0", + "version": "0.12.4", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -46,19 +46,19 @@ }, "license": "Apache-2.0", "dependencies": { - "@firebase/util": "1.9.3", - "@firebase/component": "0.6.4", - "undici": "5.26.5", + "@firebase/util": "1.9.5", + "@firebase/component": "0.6.6", + "undici": "5.28.4", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" }, "devDependencies": { - "@firebase/app": "0.9.25", - "@firebase/auth": "1.5.1", + "@firebase/app": "0.10.2", + "@firebase/auth": "1.7.2", "rollup": "2.79.1", - "@rollup/plugin-alias": "3.1.9", + "@rollup/plugin-alias": "5.1.0", "@rollup/plugin-json": "4.1.0", "rollup-plugin-typescript2": "0.31.2", "typescript": "4.7.4" @@ -66,7 +66,7 @@ "repository": { "directory": "packages/storage", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/template-types/CHANGELOG.md b/packages/template-types/CHANGELOG.md index 7864623b902..a5cd7dbd623 100644 --- a/packages/template-types/CHANGELOG.md +++ b/packages/template-types/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/template-types +## 0.2.1 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.2.0 ### Minor Changes diff --git a/packages/template-types/package.json b/packages/template-types/package.json index beeb4970974..1d469f2a706 100644 --- a/packages/template-types/package.json +++ b/packages/template-types/package.json @@ -1,7 +1,7 @@ { "name": "@firebase/template-types", "private": true, - "version": "0.2.0", + "version": "0.2.1", "description": "@firebase/template Types", "author": "Firebase (https://firebase.google.com/)", "license": "Apache-2.0", @@ -15,7 +15,7 @@ "repository": { "directory": "packages/template-types", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/template/CHANGELOG.md b/packages/template/CHANGELOG.md index 17ead013a04..34b95d37436 100644 --- a/packages/template/CHANGELOG.md +++ b/packages/template/CHANGELOG.md @@ -1,5 +1,14 @@ # @firebase/template +## 0.2.3 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +- Updated dependencies [[`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0)]: + - @firebase/template-types@0.2.1 + ## 0.2.2 ### Patch Changes diff --git a/packages/template/package.json b/packages/template/package.json index d3d3c139dd7..1a64332087d 100644 --- a/packages/template/package.json +++ b/packages/template/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/template", - "version": "0.2.2", + "version": "0.2.3", "private": true, "description": "A template package for new firebase packages", "author": "Firebase (https://firebase.google.com/)", @@ -44,12 +44,12 @@ "@firebase/app-types": "0.x" }, "dependencies": { - "@firebase/template-types": "0.2.0", + "@firebase/template-types": "0.2.1", "tslib": "^2.1.0" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/app": "0.9.25", + "@firebase/app": "0.10.2", "rollup": "2.79.1", "rollup-plugin-typescript2": "0.31.2", "typescript": "4.7.4" @@ -57,7 +57,7 @@ "repository": { "directory": "packages/template", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/util/CHANGELOG.md b/packages/util/CHANGELOG.md index 6c4ccc28f02..c71a115e02d 100644 --- a/packages/util/CHANGELOG.md +++ b/packages/util/CHANGELOG.md @@ -1,5 +1,17 @@ # @firebase/util +## 1.9.5 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + +## 1.9.4 + +### Patch Changes + +- [`434f8418c`](https://github.com/firebase/firebase-js-sdk/commit/434f8418c3db3ae98489a8461c437c248c039070) [#7963](https://github.com/firebase/firebase-js-sdk/pull/7963) (fixes [#7962](https://github.com/firebase/firebase-js-sdk/issues/7962)) - Fix isSafari() throwing on React Native + ## 1.9.3 ### Patch Changes diff --git a/packages/util/package.json b/packages/util/package.json index 80e3b6e9ed8..2863555aea2 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@firebase/util", - "version": "1.9.3", + "version": "1.9.5", "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "dist/index.node.cjs.js", @@ -53,7 +53,7 @@ "repository": { "directory": "packages/util", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/packages/util/src/environment.ts b/packages/util/src/environment.ts index 04bbd92165d..f2afaede0f1 100644 --- a/packages/util/src/environment.ts +++ b/packages/util/src/environment.ts @@ -138,6 +138,7 @@ export function isNodeSdk(): boolean { export function isSafari(): boolean { return ( !isNode() && + !!navigator.userAgent && navigator.userAgent.includes('Safari') && !navigator.userAgent.includes('Chrome') ); diff --git a/packages/vertexai/.eslintrc.js b/packages/vertexai/.eslintrc.js new file mode 100644 index 00000000000..1e8712b0633 --- /dev/null +++ b/packages/vertexai/.eslintrc.js @@ -0,0 +1,35 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const path = require('path'); + +module.exports = { + extends: '../../config/.eslintrc.js', + parserOptions: { + project: 'tsconfig.json', + // to make vscode-eslint work with monorepo + // https://github.com/typescript-eslint/typescript-eslint/issues/251#issuecomment-463943250 + tsconfigRootDir: __dirname + }, + rules: { + 'import/no-extraneous-dependencies': [ + 'error', + { + 'packageDir': [path.resolve(__dirname, '../../'), __dirname] + } + ] + } +}; diff --git a/packages/vertexai/CHANGELOG.md b/packages/vertexai/CHANGELOG.md new file mode 100644 index 00000000000..3cb406f1c23 --- /dev/null +++ b/packages/vertexai/CHANGELOG.md @@ -0,0 +1,2 @@ +# @firebase/vertexai + diff --git a/packages/vertexai/README.md b/packages/vertexai/README.md new file mode 100644 index 00000000000..b559a1e739e --- /dev/null +++ b/packages/vertexai/README.md @@ -0,0 +1,5 @@ +# @firebase/vertexai + +This is the Firebase Vertex AI component of the Firebase JS SDK. + +**This package is not intended for direct usage, and should only be used via the officially supported [firebase](https://www.npmjs.com/package/firebase) package.** diff --git a/packages/vertexai/api-extractor.json b/packages/vertexai/api-extractor.json new file mode 100644 index 00000000000..8a3c6cb251e --- /dev/null +++ b/packages/vertexai/api-extractor.json @@ -0,0 +1,10 @@ +{ + "extends": "../../config/api-extractor.json", + // Point it to your entry point d.ts file. + "mainEntryPointFilePath": "/dist/src/index.d.ts", + "dtsRollup": { + "enabled": true, + "untrimmedFilePath": "/dist/.d.ts", + "publicTrimmedFilePath": "/dist/-public.d.ts" + } +} \ No newline at end of file diff --git a/packages/vertexai/karma.conf.js b/packages/vertexai/karma.conf.js new file mode 100644 index 00000000000..3fe2a2f9633 --- /dev/null +++ b/packages/vertexai/karma.conf.js @@ -0,0 +1,35 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const karmaBase = require('../../config/karma.base'); + +const files = [`src/**/*.test.ts`]; + +module.exports = function (config) { + const karmaConfig = { + ...karmaBase, + // files to load into karma + files, + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['mocha'] + }; + + config.set(karmaConfig); +}; + +module.exports.files = files; diff --git a/packages/vertexai/package.json b/packages/vertexai/package.json new file mode 100644 index 00000000000..ce5ba1323df --- /dev/null +++ b/packages/vertexai/package.json @@ -0,0 +1,77 @@ +{ + "name": "@firebase/vertexai-preview", + "version": "0.0.0", + "description": "A Firebase SDK for VertexAI (preview)", + "author": "Firebase (https://firebase.google.com/)", + "engines": { + "node": ">=18.0.0" + }, + "main": "dist/index.cjs.js", + "browser": "dist/esm/index.esm2017.js", + "module": "dist/esm/index.esm2017.js", + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "node": { + "require": "./dist/index.cjs.js", + "import": "./dist/esm/index.esm2017.js" + }, + "browser": { + "require": "./dist/index.cjs.js", + "import": "./dist/esm/index.esm2017.js" + }, + "default": "./dist/esm/index.esm2017.js" + }, + "./package.json": "./package.json" + }, + "files": [ + "dist" + ], + "scripts": { + "lint": "eslint -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'", + "lint:fix": "eslint --fix -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'", + "build": "rollup -c && yarn api-report", + "build:deps": "lerna run --scope @firebase/vertexai --include-dependencies build", + "dev": "rollup -c -w", + "testsetup": "yarn ts-node ./test-utils/convert-mocks.ts", + "test": "run-p --npm-path npm lint test:browser", + "test:ci": "yarn testsetup && node ../../scripts/run_tests_in_ci.js -s test", + "test:browser": "yarn testsetup && karma start --single-run", + "api-report": "api-extractor run --local --verbose" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + }, + "dependencies": { + "@firebase/app-check-interop-types": "0.3.1", + "@firebase/component": "0.6.6", + "@firebase/logger": "0.4.1", + "@firebase/util": "1.9.5", + "tslib": "^2.1.0" + }, + "license": "Apache-2.0", + "devDependencies": { + "@firebase/app": "0.10.2", + "@rollup/plugin-json": "4.1.0", + "rollup": "2.79.1", + "rollup-plugin-replace": "2.2.0", + "rollup-plugin-typescript2": "0.31.2", + "typescript": "4.7.4" + }, + "repository": { + "directory": "packages/vertexai", + "type": "git", + "url": "git+https://github.com/firebase/firebase-js-sdk.git" + }, + "bugs": { + "url": "https://github.com/firebase/firebase-js-sdk/issues" + }, + "typings": "dist/src/index.d.ts", + "nyc": { + "extension": [ + ".ts" + ], + "reportDir": "./coverage/node" + } +} \ No newline at end of file diff --git a/packages/vertexai/rollup.config.js b/packages/vertexai/rollup.config.js new file mode 100644 index 00000000000..6e99c03e913 --- /dev/null +++ b/packages/vertexai/rollup.config.js @@ -0,0 +1,102 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import json from '@rollup/plugin-json'; +import typescriptPlugin from 'rollup-plugin-typescript2'; +import replace from 'rollup-plugin-replace'; +import typescript from 'typescript'; +import pkg from './package.json'; +import { generateBuildTargetReplaceConfig } from '../../scripts/build/rollup_replace_build_target'; +import { emitModulePackageFile } from '../../scripts/build/rollup_emit_module_package_file'; + +const deps = Object.keys( + Object.assign({}, pkg.peerDependencies, pkg.dependencies) +); + +const es5BuildPlugins = [ + typescriptPlugin({ + typescript + }), + json() +]; + +const es2017BuildPlugins = [ + typescriptPlugin({ + typescript, + tsconfigOverride: { + compilerOptions: { + target: 'es2017' + } + } + }), + json() +]; + +const browserBuilds = [ + { + input: 'src/index.ts', + output: { + file: pkg.module, + format: 'es', + sourcemap: true + }, + plugins: [ + ...es2017BuildPlugins, + replace({ + ...generateBuildTargetReplaceConfig('esm', 2017), + __PACKAGE_VERSION__: pkg.version + }), + emitModulePackageFile() + ], + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + }, + { + input: 'src/index.ts', + output: { + file: './dist/index.cjs.js', + format: 'cjs', + sourcemap: true + }, + plugins: [ + ...es2017BuildPlugins, + replace({ + ...generateBuildTargetReplaceConfig('cjs', 2017), + __PACKAGE_VERSION__: pkg.version + }) + ], + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + } +]; + +// const nodeBuilds = [ +// { +// input: 'index.node.ts', +// output: [{ file: pkg.main, format: 'cjs', sourcemap: true }], +// plugins: es2017BuildPlugins, +// external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) +// }, +// { +// input: 'index.node.ts', +// output: [ +// { file: pkg.exports['.'].node.import, format: 'es', sourcemap: true } +// ], +// plugins: [...es2017BuildPlugins, emitModulePackageFile()], +// external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) +// } +// ]; + +export default [...browserBuilds]; diff --git a/packages/vertexai/src/api.test.ts b/packages/vertexai/src/api.test.ts new file mode 100644 index 00000000000..5c25cce7ef9 --- /dev/null +++ b/packages/vertexai/src/api.test.ts @@ -0,0 +1,65 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ModelParams } from './types'; +import { getGenerativeModel } from './api'; +import { expect } from 'chai'; +import { VertexAI } from './public-types'; +import { GenerativeModel } from './models/generative-model'; +import { VertexError } from './errors'; + +const fakeVertexAI: VertexAI = { + app: { + name: 'DEFAULT', + automaticDataCollectionEnabled: true, + options: { + apiKey: 'key', + projectId: 'my-project' + } + }, + location: 'us-central1' +}; + +describe('Top level API', () => { + it('getGenerativeModel throws if no model is provided', () => { + expect(() => getGenerativeModel(fakeVertexAI, {} as ModelParams)).to.throw( + VertexError.NO_MODEL + ); + }); + it('getGenerativeModel throws if no apiKey is provided', () => { + const fakeVertexNoApiKey = { + ...fakeVertexAI, + app: { options: { projectId: 'my-project' } } + } as VertexAI; + expect(() => + getGenerativeModel(fakeVertexNoApiKey, { model: 'my-model' }) + ).to.throw(VertexError.NO_API_KEY); + }); + it('getGenerativeModel throws if no projectId is provided', () => { + const fakeVertexNoProject = { + ...fakeVertexAI, + app: { options: { apiKey: 'my-key' } } + } as VertexAI; + expect(() => + getGenerativeModel(fakeVertexNoProject, { model: 'my-model' }) + ).to.throw(VertexError.NO_PROJECT_ID); + }); + it('getGenerativeModel gets a GenerativeModel', () => { + const genModel = getGenerativeModel(fakeVertexAI, { model: 'my-model' }); + expect(genModel).to.be.an.instanceOf(GenerativeModel); + expect(genModel.model).to.equal('publishers/google/models/my-model'); + }); +}); diff --git a/packages/vertexai/src/api.ts b/packages/vertexai/src/api.ts new file mode 100644 index 00000000000..5b9620969b8 --- /dev/null +++ b/packages/vertexai/src/api.ts @@ -0,0 +1,73 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FirebaseApp, getApp, _getProvider } from '@firebase/app'; +import { Provider } from '@firebase/component'; +import { getModularInstance } from '@firebase/util'; +import { DEFAULT_LOCATION, VERTEX_TYPE } from './constants'; +import { VertexAIService } from './service'; +import { VertexAI, VertexAIOptions } from './public-types'; +import { ERROR_FACTORY, VertexError } from './errors'; +import { ModelParams, RequestOptions } from './types'; +import { GenerativeModel } from './models/generative-model'; + +export { ChatSession } from './methods/chat-session'; + +export { GenerativeModel }; + +declare module '@firebase/component' { + interface NameServiceMapping { + [VERTEX_TYPE]: VertexAIService; + } +} + +/** + * Returns a {@link VertexAI} instance for the given app. + * + * @public + * + * @param app - The {@link @firebase/app#FirebaseApp} to use. + */ +export function getVertexAI( + app: FirebaseApp = getApp(), + options?: VertexAIOptions +): VertexAI { + app = getModularInstance(app); + // Dependencies + const vertexProvider: Provider<'vertexAI'> = _getProvider(app, VERTEX_TYPE); + + return vertexProvider.getImmediate({ + identifier: options?.location || DEFAULT_LOCATION + }); +} + +/** + * Returns a {@link GenerativeModel} class with methods for inference + * and other functionality. + * + * @public + */ +export function getGenerativeModel( + vertexAI: VertexAI, + modelParams: ModelParams, + requestOptions?: RequestOptions +): GenerativeModel { + if (!modelParams.model) { + throw ERROR_FACTORY.create(VertexError.NO_MODEL); + } + return new GenerativeModel(vertexAI, modelParams, requestOptions); +} diff --git a/packages/vertexai/src/constants.ts b/packages/vertexai/src/constants.ts new file mode 100644 index 00000000000..97f6d813abc --- /dev/null +++ b/packages/vertexai/src/constants.ts @@ -0,0 +1,30 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { version } from '../package.json'; + +export const VERTEX_TYPE = 'vertexAI'; + +export const DEFAULT_LOCATION = 'us-central1'; + +export const DEFAULT_BASE_URL = 'https://firebaseml.googleapis.com'; + +export const DEFAULT_API_VERSION = 'v2beta'; + +export const PACKAGE_VERSION = version; + +export const LANGUAGE_TAG = 'gl-js'; diff --git a/packages/vertexai/src/errors.ts b/packages/vertexai/src/errors.ts new file mode 100644 index 00000000000..c0b9d83aaeb --- /dev/null +++ b/packages/vertexai/src/errors.ts @@ -0,0 +1,63 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ErrorFactory, ErrorMap } from '@firebase/util'; +import { GenerateContentResponse } from './types'; + +export const enum VertexError { + FETCH_ERROR = 'fetch-error', + INVALID_CONTENT = 'invalid-content', + NO_API_KEY = 'no-api-key', + NO_MODEL = 'no-model', + NO_PROJECT_ID = 'no-project-id', + PARSE_FAILED = 'parse-failed', + RESPONSE_ERROR = 'response-error' +} + +const ERRORS: ErrorMap = { + [VertexError.FETCH_ERROR]: `Error fetching from {$url}: {$message}`, + [VertexError.INVALID_CONTENT]: `Content formatting error: {$message}`, + [VertexError.NO_API_KEY]: + `The "apiKey" field is empty in the local Firebase config. Firebase VertexAI requires this field to` + + `contain a valid API key.`, + [VertexError.NO_PROJECT_ID]: + `The "projectId" field is empty in the local Firebase config. Firebase VertexAI requires this field to` + + `contain a valid project ID.`, + [VertexError.NO_MODEL]: + `Must provide a model name. ` + + `Example: getGenerativeModel({ model: 'my-model-name' })`, + [VertexError.PARSE_FAILED]: `Parsing failed: {$message}`, + [VertexError.RESPONSE_ERROR]: + `Response error: {$message}. Response body stored in ` + + `error.customData.response` +}; + +interface ErrorParams { + [VertexError.FETCH_ERROR]: { url: string; message: string }; + [VertexError.INVALID_CONTENT]: { message: string }; + [VertexError.PARSE_FAILED]: { message: string }; + [VertexError.RESPONSE_ERROR]: { + message: string; + response: GenerateContentResponse; + }; +} + +export const ERROR_FACTORY = new ErrorFactory( + 'vertexAI', + 'VertexAI', + ERRORS +); diff --git a/packages/vertexai/src/index.ts b/packages/vertexai/src/index.ts new file mode 100644 index 00000000000..b4c78b0731c --- /dev/null +++ b/packages/vertexai/src/index.ts @@ -0,0 +1,59 @@ +/** + * The Vertex AI For Firebase Web SDK. + * + * @packageDocumentation + */ + +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { registerVersion, _registerComponent } from '@firebase/app'; +import { VertexAIService } from './service'; +import { VERTEX_TYPE } from './constants'; +import { Component, ComponentType } from '@firebase/component'; +import { name, version } from '../package.json'; + +declare global { + interface Window { + [key: string]: unknown; + } +} + +function registerVertex(): void { + _registerComponent( + new Component( + VERTEX_TYPE, + (container, { instanceIdentifier: location }) => { + // getImmediate for FirebaseApp will always succeed + const app = container.getProvider('app').getImmediate(); + const auth = container.getProvider('auth-internal'); + const appCheckProvider = container.getProvider('app-check-internal'); + return new VertexAIService(app, auth, appCheckProvider, { location }); + }, + ComponentType.PUBLIC + ).setMultipleInstances(true) + ); + + registerVersion(name, version); + // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation + registerVersion(name, version, '__BUILD_TARGET__'); +} + +registerVertex(); + +export * from './api'; +export * from './public-types'; diff --git a/packages/vertexai/src/methods/chat-session-helpers.test.ts b/packages/vertexai/src/methods/chat-session-helpers.test.ts new file mode 100644 index 00000000000..feab9fc3b05 --- /dev/null +++ b/packages/vertexai/src/methods/chat-session-helpers.test.ts @@ -0,0 +1,157 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { validateChatHistory } from './chat-session-helpers'; +import { expect } from 'chai'; +import { Content } from '../types'; +import { FirebaseError } from '@firebase/util'; + +describe('chat-session-helpers', () => { + describe('validateChatHistory', () => { + const TCS: Array<{ history: Content[]; isValid: boolean }> = [ + { + history: [{ role: 'user', parts: [{ text: 'hi' }] }], + isValid: true + }, + { + history: [ + { + role: 'user', + parts: [ + { text: 'hi' }, + { inlineData: { mimeType: 'image/jpeg', data: 'base64==' } } + ] + } + ], + isValid: true + }, + { + history: [ + { role: 'user', parts: [{ text: 'hi' }] }, + { role: 'model', parts: [{ text: 'hi' }, { text: 'hi' }] } + ], + isValid: true + }, + { + history: [ + { role: 'user', parts: [{ text: 'hi' }] }, + { + role: 'model', + parts: [{ functionCall: { name: 'greet', args: { name: 'user' } } }] + } + ], + isValid: true + }, + { + history: [ + { role: 'user', parts: [{ text: 'hi' }] }, + { + role: 'model', + parts: [{ functionCall: { name: 'greet', args: { name: 'user' } } }] + }, + { + role: 'function', + parts: [ + { + functionResponse: { name: 'greet', response: { name: 'user' } } + } + ] + } + ], + isValid: true + }, + { + history: [ + { role: 'user', parts: [{ text: 'hi' }] }, + { + role: 'model', + parts: [{ functionCall: { name: 'greet', args: { name: 'user' } } }] + }, + { + role: 'function', + parts: [ + { + functionResponse: { name: 'greet', response: { name: 'user' } } + } + ] + }, + { + role: 'model', + parts: [{ text: 'hi name' }] + } + ], + isValid: true + }, + { + //@ts-expect-error + history: [{ role: 'user', parts: '' }], + isValid: false + }, + { + //@ts-expect-error + history: [{ role: 'user' }], + isValid: false + }, + { + history: [{ role: 'user', parts: [] }], + isValid: false + }, + { + history: [{ role: 'model', parts: [{ text: 'hi' }] }], + isValid: false + }, + { + history: [ + { + role: 'function', + parts: [ + { + functionResponse: { name: 'greet', response: { name: 'user' } } + } + ] + } + ], + isValid: false + }, + { + history: [ + { role: 'user', parts: [{ text: 'hi' }] }, + { role: 'user', parts: [{ text: 'hi' }] } + ], + isValid: false + }, + { + history: [ + { role: 'user', parts: [{ text: 'hi' }] }, + { role: 'model', parts: [{ text: 'hi' }] }, + { role: 'model', parts: [{ text: 'hi' }] } + ], + isValid: false + } + ]; + TCS.forEach((tc, index) => { + it(`case ${index}`, () => { + const fn = (): void => validateChatHistory(tc.history); + if (tc.isValid) { + expect(fn).to.not.throw(); + } else { + expect(fn).to.throw(FirebaseError); + } + }); + }); + }); +}); diff --git a/packages/vertexai/src/methods/chat-session-helpers.ts b/packages/vertexai/src/methods/chat-session-helpers.ts new file mode 100644 index 00000000000..0ac00ad0a1c --- /dev/null +++ b/packages/vertexai/src/methods/chat-session-helpers.ts @@ -0,0 +1,112 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Content, POSSIBLE_ROLES, Part, Role } from '../types'; +import { ERROR_FACTORY, VertexError } from '../errors'; + +// https://ai.google.dev/api/rest/v1beta/Content#part + +const VALID_PART_FIELDS: Array = [ + 'text', + 'inlineData', + 'functionCall', + 'functionResponse' +]; + +const VALID_PARTS_PER_ROLE: { [key in Role]: Array } = { + user: ['text', 'inlineData'], + function: ['functionResponse'], + model: ['text', 'functionCall'], + // System instructions shouldn't be in history anyway. + system: ['text'] +}; + +const VALID_PREVIOUS_CONTENT_ROLES: { [key in Role]: Role[] } = { + user: ['model'], + function: ['model'], + model: ['user', 'function'], + // System instructions shouldn't be in history. + system: [] +}; + +export function validateChatHistory(history: Content[]): void { + let prevContent: Content | null = null; + for (const currContent of history) { + const { role, parts } = currContent; + if (!prevContent && role !== 'user') { + throw ERROR_FACTORY.create(VertexError.INVALID_CONTENT, { + message: `First content should be with role 'user', got ${role}` + }); + } + if (!POSSIBLE_ROLES.includes(role)) { + throw ERROR_FACTORY.create(VertexError.INVALID_CONTENT, { + message: `Each item should include role field. Got ${role} but valid roles are: ${JSON.stringify( + POSSIBLE_ROLES + )}` + }); + } + + if (!Array.isArray(parts)) { + throw ERROR_FACTORY.create(VertexError.INVALID_CONTENT, { + message: "Content should have 'parts' property with an array of Parts" + }); + } + + if (parts.length === 0) { + throw ERROR_FACTORY.create(VertexError.INVALID_CONTENT, { + message: 'Each Content should have at least one part' + }); + } + + const countFields: Record = { + text: 0, + inlineData: 0, + functionCall: 0, + functionResponse: 0 + }; + + for (const part of parts) { + for (const key of VALID_PART_FIELDS) { + if (key in part) { + countFields[key] += 1; + } + } + } + const validParts = VALID_PARTS_PER_ROLE[role]; + for (const key of VALID_PART_FIELDS) { + if (!validParts.includes(key) && countFields[key] > 0) { + throw ERROR_FACTORY.create(VertexError.INVALID_CONTENT, { + message: `Content with role '${role}' can't contain '${key}' part` + }); + } + } + + if (prevContent) { + const validPreviousContentRoles = VALID_PREVIOUS_CONTENT_ROLES[role]; + if (!validPreviousContentRoles.includes(prevContent.role)) { + throw ERROR_FACTORY.create(VertexError.INVALID_CONTENT, { + message: `Content with role '${role}' can't follow '${ + prevContent.role + }'. Valid previous roles: ${JSON.stringify( + VALID_PREVIOUS_CONTENT_ROLES + )}` + }); + } + } + prevContent = currContent; + } +} diff --git a/packages/vertexai/src/methods/chat-session.test.ts b/packages/vertexai/src/methods/chat-session.test.ts new file mode 100644 index 00000000000..c8c92e046b9 --- /dev/null +++ b/packages/vertexai/src/methods/chat-session.test.ts @@ -0,0 +1,97 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect, use } from 'chai'; +import { match, restore, stub, useFakeTimers } from 'sinon'; +import sinonChai from 'sinon-chai'; +import chaiAsPromised from 'chai-as-promised'; +import * as generateContentMethods from './generate-content'; +import { GenerateContentStreamResult } from '../types'; +import { ChatSession } from './chat-session'; +import { ApiSettings } from '../types/internal'; + +use(sinonChai); +use(chaiAsPromised); + +const fakeApiSettings: ApiSettings = { + apiKey: 'key', + project: 'my-project', + location: 'us-central1' +}; + +describe('ChatSession', () => { + afterEach(() => { + restore(); + }); + describe('sendMessage()', () => { + it('generateContent errors should be catchable', async () => { + const generateContentStub = stub( + generateContentMethods, + 'generateContent' + ).rejects('generateContent failed'); + const chatSession = new ChatSession(fakeApiSettings, 'a-model'); + await expect(chatSession.sendMessage('hello')).to.be.rejected; + expect(generateContentStub).to.be.calledWith( + fakeApiSettings, + 'a-model', + match.any + ); + }); + }); + describe('sendMessageStream()', () => { + it('generateContentStream errors should be catchable', async () => { + const clock = useFakeTimers(); + const consoleStub = stub(console, 'error'); + const generateContentStreamStub = stub( + generateContentMethods, + 'generateContentStream' + ).rejects('generateContentStream failed'); + const chatSession = new ChatSession(fakeApiSettings, 'a-model'); + await expect(chatSession.sendMessageStream('hello')).to.be.rejected; + expect(generateContentStreamStub).to.be.calledWith( + fakeApiSettings, + 'a-model', + match.any + ); + await clock.runAllAsync(); + expect(consoleStub).to.not.be.called; + clock.restore(); + }); + it('downstream sendPromise errors should log but not throw', async () => { + const clock = useFakeTimers(); + const consoleStub = stub(console, 'error'); + // make response undefined so that response.candidates errors + const generateContentStreamStub = stub( + generateContentMethods, + 'generateContentStream' + ).resolves({} as unknown as GenerateContentStreamResult); + const chatSession = new ChatSession(fakeApiSettings, 'a-model'); + await chatSession.sendMessageStream('hello'); + expect(generateContentStreamStub).to.be.calledWith( + fakeApiSettings, + 'a-model', + match.any + ); + await clock.runAllAsync(); + expect(consoleStub.args[0][0].toString()).to.include( + // Firefox has different wording when a property is undefined + 'undefined' + ); + clock.restore(); + }); + }); +}); diff --git a/packages/vertexai/src/methods/chat-session.ts b/packages/vertexai/src/methods/chat-session.ts new file mode 100644 index 00000000000..c685d84908a --- /dev/null +++ b/packages/vertexai/src/methods/chat-session.ts @@ -0,0 +1,190 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + Content, + GenerateContentRequest, + GenerateContentResult, + GenerateContentStreamResult, + Part, + RequestOptions, + StartChatParams +} from '../types'; +import { formatNewContent } from '../requests/request-helpers'; +import { formatBlockErrorMessage } from '../requests/response-helpers'; +import { validateChatHistory } from './chat-session-helpers'; +import { generateContent, generateContentStream } from './generate-content'; +import { ApiSettings } from '../types/internal'; + +/** + * Do not log a message for this error. + */ +const SILENT_ERROR = 'SILENT_ERROR'; + +/** + * ChatSession class that enables sending chat messages and stores + * history of sent and received messages so far. + * + * @public + */ +export class ChatSession { + private _apiSettings: ApiSettings; + private _history: Content[] = []; + private _sendPromise: Promise = Promise.resolve(); + + constructor( + apiSettings: ApiSettings, + public model: string, + public params?: StartChatParams, + public requestOptions?: RequestOptions + ) { + this._apiSettings = apiSettings; + if (params?.history) { + validateChatHistory(params.history); + this._history = params.history; + } + } + + /** + * Gets the chat history so far. Blocked prompts are not added to history. + * Blocked candidates are not added to history, nor are the prompts that + * generated them. + */ + async getHistory(): Promise { + await this._sendPromise; + return this._history; + } + + /** + * Sends a chat message and receives a non-streaming + * {@link GenerateContentResult} + */ + async sendMessage( + request: string | Array + ): Promise { + await this._sendPromise; + const newContent = formatNewContent(request); + const generateContentRequest: GenerateContentRequest = { + safetySettings: this.params?.safetySettings, + generationConfig: this.params?.generationConfig, + tools: this.params?.tools, + toolConfig: this.params?.toolConfig, + systemInstruction: this.params?.systemInstruction, + contents: [...this._history, newContent] + }; + let finalResult = {} as GenerateContentResult; + // Add onto the chain. + this._sendPromise = this._sendPromise + .then(() => + generateContent( + this._apiSettings, + this.model, + generateContentRequest, + this.requestOptions + ) + ) + .then(result => { + if ( + result.response.candidates && + result.response.candidates.length > 0 + ) { + this._history.push(newContent); + const responseContent: Content = { + parts: result.response.candidates?.[0].content.parts || [], + // Response seems to come back without a role set. + role: result.response.candidates?.[0].content.role || 'model' + }; + this._history.push(responseContent); + } else { + const blockErrorMessage = formatBlockErrorMessage(result.response); + if (blockErrorMessage) { + console.warn( + `sendMessage() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.` + ); + } + } + finalResult = result; + }); + await this._sendPromise; + return finalResult; + } + + /** + * Sends a chat message and receives the response as a + * {@link GenerateContentStreamResult} containing an iterable stream + * and a response promise. + */ + async sendMessageStream( + request: string | Array + ): Promise { + await this._sendPromise; + const newContent = formatNewContent(request); + const generateContentRequest: GenerateContentRequest = { + safetySettings: this.params?.safetySettings, + generationConfig: this.params?.generationConfig, + tools: this.params?.tools, + toolConfig: this.params?.toolConfig, + systemInstruction: this.params?.systemInstruction, + contents: [...this._history, newContent] + }; + const streamPromise = generateContentStream( + this._apiSettings, + this.model, + generateContentRequest, + this.requestOptions + ); + + // Add onto the chain. + this._sendPromise = this._sendPromise + .then(() => streamPromise) + // This must be handled to avoid unhandled rejection, but jump + // to the final catch block with a label to not log this error. + .catch(_ignored => { + throw new Error(SILENT_ERROR); + }) + .then(streamResult => streamResult.response) + .then(response => { + if (response.candidates && response.candidates.length > 0) { + this._history.push(newContent); + const responseContent = { ...response.candidates[0].content }; + // Response seems to come back without a role set. + if (!responseContent.role) { + responseContent.role = 'model'; + } + this._history.push(responseContent); + } else { + const blockErrorMessage = formatBlockErrorMessage(response); + if (blockErrorMessage) { + console.warn( + `sendMessageStream() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.` + ); + } + } + }) + .catch(e => { + // Errors in streamPromise are already catchable by the user as + // streamPromise is returned. + // Avoid duplicating the error message in logs. + if (e.message !== SILENT_ERROR) { + // Users do not have access to _sendPromise to catch errors + // downstream from streamPromise, so they should not throw. + console.error(e); + } + }); + return streamPromise; + } +} diff --git a/packages/vertexai/src/methods/count-tokens.ts b/packages/vertexai/src/methods/count-tokens.ts new file mode 100644 index 00000000000..c9d43a5b6fd --- /dev/null +++ b/packages/vertexai/src/methods/count-tokens.ts @@ -0,0 +1,41 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + CountTokensRequest, + CountTokensResponse, + RequestOptions +} from '../types'; +import { Task, makeRequest } from '../requests/request'; +import { ApiSettings } from '../types/internal'; + +export async function countTokens( + apiSettings: ApiSettings, + model: string, + params: CountTokensRequest, + requestOptions?: RequestOptions +): Promise { + const response = await makeRequest( + model, + Task.COUNT_TOKENS, + apiSettings, + false, + JSON.stringify(params), + requestOptions + ); + return response.json(); +} diff --git a/packages/vertexai/src/methods/generate-content.test.ts b/packages/vertexai/src/methods/generate-content.test.ts new file mode 100644 index 00000000000..5503c172c96 --- /dev/null +++ b/packages/vertexai/src/methods/generate-content.test.ts @@ -0,0 +1,219 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect, use } from 'chai'; +import { match, restore, stub } from 'sinon'; +import sinonChai from 'sinon-chai'; +import chaiAsPromised from 'chai-as-promised'; +import { getMockResponse } from '../../test-utils/mock-response'; +import * as request from '../requests/request'; +import { generateContent } from './generate-content'; +import { + GenerateContentRequest, + HarmBlockMethod, + HarmBlockThreshold, + HarmCategory +} from '../types'; +import { ApiSettings } from '../types/internal'; +import { Task } from '../requests/request'; + +use(sinonChai); +use(chaiAsPromised); + +const fakeApiSettings: ApiSettings = { + apiKey: 'key', + project: 'my-project', + location: 'us-central1' +}; + +const fakeRequestParams: GenerateContentRequest = { + contents: [{ parts: [{ text: 'hello' }], role: 'user' }], + generationConfig: { + topK: 16 + }, + safetySettings: [ + { + category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, + threshold: HarmBlockThreshold.BLOCK_LOW_AND_ABOVE, + method: HarmBlockMethod.SEVERITY + } + ] +}; + +describe('generateContent()', () => { + afterEach(() => { + restore(); + }); + it('short response', async () => { + const mockResponse = getMockResponse( + 'unary-success-basic-reply-short.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const result = await generateContent( + fakeApiSettings, + 'model', + fakeRequestParams + ); + expect(result.response.text()).to.include('Helena'); + expect(makeRequestStub).to.be.calledWith( + 'model', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + match((value: string) => { + return value.includes('contents'); + }), + undefined + ); + }); + it('long response', async () => { + const mockResponse = getMockResponse('unary-success-basic-reply-long.json'); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const result = await generateContent( + fakeApiSettings, + 'model', + fakeRequestParams + ); + expect(result.response.text()).to.include('Use Freshly Ground Coffee'); + expect(result.response.text()).to.include('30 minutes of brewing'); + expect(makeRequestStub).to.be.calledWith( + 'model', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + match.any + ); + }); + it('citations', async () => { + const mockResponse = getMockResponse('unary-success-citations.json'); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const result = await generateContent( + fakeApiSettings, + 'model', + fakeRequestParams + ); + expect(result.response.text()).to.include('Quantum mechanics is'); + expect( + result.response.candidates?.[0].citationMetadata?.citations.length + ).to.equal(1); + expect(makeRequestStub).to.be.calledWith( + 'model', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + match.any + ); + }); + it('blocked prompt', async () => { + const mockResponse = getMockResponse( + 'unary-failure-prompt-blocked-safety.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const result = await generateContent( + fakeApiSettings, + 'model', + fakeRequestParams + ); + expect(result.response.text).to.throw('SAFETY'); + expect(makeRequestStub).to.be.calledWith( + 'model', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + match.any + ); + }); + it('finishReason safety', async () => { + const mockResponse = getMockResponse( + 'unary-failure-finish-reason-safety.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const result = await generateContent( + fakeApiSettings, + 'model', + fakeRequestParams + ); + expect(result.response.text).to.throw('SAFETY'); + expect(makeRequestStub).to.be.calledWith( + 'model', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + match.any + ); + }); + it('empty content', async () => { + const mockResponse = getMockResponse('unary-failure-empty-content.json'); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const result = await generateContent( + fakeApiSettings, + 'model', + fakeRequestParams + ); + expect(result.response.text()).to.equal(''); + expect(makeRequestStub).to.be.calledWith( + 'model', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + match.any + ); + }); + it('unknown enum - should ignore', async () => { + const mockResponse = getMockResponse('unary-unknown-enum.json'); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + const result = await generateContent( + fakeApiSettings, + 'model', + fakeRequestParams + ); + expect(result.response.text()).to.include('30 minutes of brewing'); + expect(makeRequestStub).to.be.calledWith( + 'model', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + match.any + ); + }); + it('image rejected (400)', async () => { + const mockResponse = getMockResponse('unary-failure-image-rejected.json'); + const mockFetch = stub(globalThis, 'fetch').resolves({ + ok: false, + status: 400, + json: mockResponse.json + } as Response); + await expect( + generateContent(fakeApiSettings, 'model', fakeRequestParams) + ).to.be.rejectedWith(/400.*invalid argument/); + expect(mockFetch).to.be.called; + }); +}); diff --git a/packages/vertexai/src/methods/generate-content.ts b/packages/vertexai/src/methods/generate-content.ts new file mode 100644 index 00000000000..2dee91f12e8 --- /dev/null +++ b/packages/vertexai/src/methods/generate-content.ts @@ -0,0 +1,66 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + GenerateContentRequest, + GenerateContentResponse, + GenerateContentResult, + GenerateContentStreamResult, + RequestOptions +} from '../types'; +import { Task, makeRequest } from '../requests/request'; +import { addHelpers } from '../requests/response-helpers'; +import { processStream } from '../requests/stream-reader'; +import { ApiSettings } from '../types/internal'; + +export async function generateContentStream( + apiSettings: ApiSettings, + model: string, + params: GenerateContentRequest, + requestOptions?: RequestOptions +): Promise { + const response = await makeRequest( + model, + Task.STREAM_GENERATE_CONTENT, + apiSettings, + /* stream */ true, + JSON.stringify(params), + requestOptions + ); + return processStream(response); +} + +export async function generateContent( + apiSettings: ApiSettings, + model: string, + params: GenerateContentRequest, + requestOptions?: RequestOptions +): Promise { + const response = await makeRequest( + model, + Task.GENERATE_CONTENT, + apiSettings, + /* stream */ false, + JSON.stringify(params), + requestOptions + ); + const responseJson: GenerateContentResponse = await response.json(); + const enhancedResponse = addHelpers(responseJson); + return { + response: enhancedResponse + }; +} diff --git a/packages/vertexai/src/models/generative-model.test.ts b/packages/vertexai/src/models/generative-model.test.ts new file mode 100644 index 00000000000..7b0287492da --- /dev/null +++ b/packages/vertexai/src/models/generative-model.test.ts @@ -0,0 +1,265 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { use, expect } from 'chai'; +import { GenerativeModel } from './generative-model'; +import { FunctionCallingMode, VertexAI } from '../public-types'; +import * as request from '../requests/request'; +import { match, restore, stub } from 'sinon'; +import { getMockResponse } from '../../test-utils/mock-response'; +import sinonChai from 'sinon-chai'; + +use(sinonChai); + +const fakeVertexAI: VertexAI = { + app: { + name: 'DEFAULT', + automaticDataCollectionEnabled: true, + options: { + apiKey: 'key', + projectId: 'my-project' + } + }, + location: 'us-central1' +}; + +describe('GenerativeModel', () => { + it('handles plain model name', () => { + const genModel = new GenerativeModel(fakeVertexAI, { model: 'my-model' }); + expect(genModel.model).to.equal('publishers/google/models/my-model'); + }); + it('handles models/ prefixed model name', () => { + const genModel = new GenerativeModel(fakeVertexAI, { + model: 'models/my-model' + }); + expect(genModel.model).to.equal('publishers/google/models/my-model'); + }); + it('handles full model name', () => { + const genModel = new GenerativeModel(fakeVertexAI, { + model: 'publishers/google/models/my-model' + }); + expect(genModel.model).to.equal('publishers/google/models/my-model'); + }); + it('handles prefixed tuned model name', () => { + const genModel = new GenerativeModel(fakeVertexAI, { + model: 'tunedModels/my-model' + }); + expect(genModel.model).to.equal('tunedModels/my-model'); + }); + it('passes params through to generateContent', async () => { + const genModel = new GenerativeModel(fakeVertexAI, { + model: 'my-model', + tools: [{ functionDeclarations: [{ name: 'myfunc' }] }], + toolConfig: { functionCallingConfig: { mode: FunctionCallingMode.NONE } }, + systemInstruction: { role: 'system', parts: [{ text: 'be friendly' }] } + }); + expect(genModel.tools?.length).to.equal(1); + expect(genModel.toolConfig?.functionCallingConfig.mode).to.equal( + FunctionCallingMode.NONE + ); + expect(genModel.systemInstruction?.parts[0].text).to.equal('be friendly'); + const mockResponse = getMockResponse( + 'unary-success-basic-reply-short.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + await genModel.generateContent('hello'); + expect(makeRequestStub).to.be.calledWith( + 'publishers/google/models/my-model', + request.Task.GENERATE_CONTENT, + match.any, + false, + match((value: string) => { + return ( + value.includes('myfunc') && + value.includes(FunctionCallingMode.NONE) && + value.includes('be friendly') + ); + }), + {} + ); + restore(); + }); + it('passes text-only systemInstruction through to generateContent', async () => { + const genModel = new GenerativeModel(fakeVertexAI, { + model: 'my-model', + systemInstruction: 'be friendly' + }); + expect(genModel.systemInstruction?.parts[0].text).to.equal('be friendly'); + const mockResponse = getMockResponse( + 'unary-success-basic-reply-short.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + await genModel.generateContent('hello'); + expect(makeRequestStub).to.be.calledWith( + 'publishers/google/models/my-model', + request.Task.GENERATE_CONTENT, + match.any, + false, + match((value: string) => { + return value.includes('be friendly'); + }), + {} + ); + restore(); + }); + it('generateContent overrides model values', async () => { + const genModel = new GenerativeModel(fakeVertexAI, { + model: 'my-model', + tools: [{ functionDeclarations: [{ name: 'myfunc' }] }], + toolConfig: { functionCallingConfig: { mode: FunctionCallingMode.NONE } }, + systemInstruction: { role: 'system', parts: [{ text: 'be friendly' }] } + }); + expect(genModel.tools?.length).to.equal(1); + expect(genModel.toolConfig?.functionCallingConfig.mode).to.equal( + FunctionCallingMode.NONE + ); + expect(genModel.systemInstruction?.parts[0].text).to.equal('be friendly'); + const mockResponse = getMockResponse( + 'unary-success-basic-reply-short.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + await genModel.generateContent({ + contents: [{ role: 'user', parts: [{ text: 'hello' }] }], + tools: [{ functionDeclarations: [{ name: 'otherfunc' }] }], + toolConfig: { functionCallingConfig: { mode: FunctionCallingMode.AUTO } }, + systemInstruction: { role: 'system', parts: [{ text: 'be formal' }] } + }); + expect(makeRequestStub).to.be.calledWith( + 'publishers/google/models/my-model', + request.Task.GENERATE_CONTENT, + match.any, + false, + match((value: string) => { + return ( + value.includes('otherfunc') && + value.includes(FunctionCallingMode.AUTO) && + value.includes('be formal') + ); + }), + {} + ); + restore(); + }); + it('passes params through to chat.sendMessage', async () => { + const genModel = new GenerativeModel(fakeVertexAI, { + model: 'my-model', + tools: [{ functionDeclarations: [{ name: 'myfunc' }] }], + toolConfig: { functionCallingConfig: { mode: FunctionCallingMode.NONE } }, + systemInstruction: { role: 'system', parts: [{ text: 'be friendly' }] } + }); + expect(genModel.tools?.length).to.equal(1); + expect(genModel.toolConfig?.functionCallingConfig.mode).to.equal( + FunctionCallingMode.NONE + ); + expect(genModel.systemInstruction?.parts[0].text).to.equal('be friendly'); + const mockResponse = getMockResponse( + 'unary-success-basic-reply-short.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + await genModel.startChat().sendMessage('hello'); + expect(makeRequestStub).to.be.calledWith( + 'publishers/google/models/my-model', + request.Task.GENERATE_CONTENT, + match.any, + false, + match((value: string) => { + return ( + value.includes('myfunc') && + value.includes(FunctionCallingMode.NONE) && + value.includes('be friendly') + ); + }), + {} + ); + restore(); + }); + it('passes text-only systemInstruction through to chat.sendMessage', async () => { + const genModel = new GenerativeModel(fakeVertexAI, { + model: 'my-model', + systemInstruction: 'be friendly' + }); + expect(genModel.systemInstruction?.parts[0].text).to.equal('be friendly'); + const mockResponse = getMockResponse( + 'unary-success-basic-reply-short.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + await genModel.startChat().sendMessage('hello'); + expect(makeRequestStub).to.be.calledWith( + 'publishers/google/models/my-model', + request.Task.GENERATE_CONTENT, + match.any, + false, + match((value: string) => { + return value.includes('be friendly'); + }), + {} + ); + restore(); + }); + it('startChat overrides model values', async () => { + const genModel = new GenerativeModel(fakeVertexAI, { + model: 'my-model', + tools: [{ functionDeclarations: [{ name: 'myfunc' }] }], + toolConfig: { functionCallingConfig: { mode: FunctionCallingMode.NONE } }, + systemInstruction: { role: 'system', parts: [{ text: 'be friendly' }] } + }); + expect(genModel.tools?.length).to.equal(1); + expect(genModel.toolConfig?.functionCallingConfig.mode).to.equal( + FunctionCallingMode.NONE + ); + expect(genModel.systemInstruction?.parts[0].text).to.equal('be friendly'); + const mockResponse = getMockResponse( + 'unary-success-basic-reply-short.json' + ); + const makeRequestStub = stub(request, 'makeRequest').resolves( + mockResponse as Response + ); + await genModel + .startChat({ + tools: [{ functionDeclarations: [{ name: 'otherfunc' }] }], + toolConfig: { + functionCallingConfig: { mode: FunctionCallingMode.AUTO } + }, + systemInstruction: { role: 'system', parts: [{ text: 'be formal' }] } + }) + .sendMessage('hello'); + expect(makeRequestStub).to.be.calledWith( + 'publishers/google/models/my-model', + request.Task.GENERATE_CONTENT, + match.any, + false, + match((value: string) => { + return ( + value.includes('otherfunc') && + value.includes(FunctionCallingMode.AUTO) && + value.includes('be formal') + ); + }), + {} + ); + restore(); + }); +}); diff --git a/packages/vertexai/src/models/generative-model.ts b/packages/vertexai/src/models/generative-model.ts new file mode 100644 index 00000000000..efd6719661b --- /dev/null +++ b/packages/vertexai/src/models/generative-model.ts @@ -0,0 +1,185 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + generateContent, + generateContentStream +} from '../methods/generate-content'; +import { + Content, + CountTokensRequest, + CountTokensResponse, + GenerateContentRequest, + GenerateContentResult, + GenerateContentStreamResult, + GenerationConfig, + ModelParams, + Part, + RequestOptions, + SafetySetting, + StartChatParams, + Tool, + ToolConfig +} from '../types'; +import { ChatSession } from '../methods/chat-session'; +import { countTokens } from '../methods/count-tokens'; +import { + formatGenerateContentInput, + formatSystemInstruction +} from '../requests/request-helpers'; +import { VertexAI } from '../public-types'; +import { ERROR_FACTORY, VertexError } from '../errors'; +import { ApiSettings } from '../types/internal'; +import { VertexAIService } from '../service'; + +/** + * Class for generative model APIs. + * @public + */ +export class GenerativeModel { + private _apiSettings: ApiSettings; + model: string; + generationConfig: GenerationConfig; + safetySettings: SafetySetting[]; + requestOptions?: RequestOptions; + tools?: Tool[]; + toolConfig?: ToolConfig; + systemInstruction?: Content; + + constructor( + vertexAI: VertexAI, + modelParams: ModelParams, + requestOptions?: RequestOptions + ) { + if (!vertexAI.app?.options?.apiKey) { + throw ERROR_FACTORY.create(VertexError.NO_API_KEY); + } else if (!vertexAI.app?.options?.projectId) { + throw ERROR_FACTORY.create(VertexError.NO_PROJECT_ID); + } else { + this._apiSettings = { + apiKey: vertexAI.app.options.apiKey, + project: vertexAI.app.options.projectId, + location: vertexAI.location + }; + if ((vertexAI as VertexAIService).appCheck) { + this._apiSettings.getAppCheckToken = () => + (vertexAI as VertexAIService).appCheck!.getToken(); + } + + if ((vertexAI as VertexAIService).auth) { + this._apiSettings.getAuthToken = () => + (vertexAI as VertexAIService).auth!.getToken(); + } + } + if (modelParams.model.includes('/')) { + if (modelParams.model.startsWith('models/')) { + // Add "publishers/google" if the user is only passing in 'models/model-name'. + this.model = `publishers/google/${modelParams.model}`; + } else { + // Any other custom format (e.g. tuned models) must be passed in correctly. + this.model = modelParams.model; + } + } else { + // If path is not included, assume it's a non-tuned model. + this.model = `publishers/google/models/${modelParams.model}`; + } + this.generationConfig = modelParams.generationConfig || {}; + this.safetySettings = modelParams.safetySettings || []; + this.tools = modelParams.tools; + this.toolConfig = modelParams.toolConfig; + this.systemInstruction = formatSystemInstruction( + modelParams.systemInstruction + ); + this.requestOptions = requestOptions || {}; + } + + /** + * Makes a single non-streaming call to the model + * and returns an object containing a single {@link GenerateContentResponse}. + */ + async generateContent( + request: GenerateContentRequest | string | Array + ): Promise { + const formattedParams = formatGenerateContentInput(request); + return generateContent( + this._apiSettings, + this.model, + { + generationConfig: this.generationConfig, + safetySettings: this.safetySettings, + tools: this.tools, + toolConfig: this.toolConfig, + systemInstruction: this.systemInstruction, + ...formattedParams + }, + this.requestOptions + ); + } + + /** + * Makes a single streaming call to the model + * and returns an object containing an iterable stream that iterates + * over all chunks in the streaming response as well as + * a promise that returns the final aggregated response. + */ + async generateContentStream( + request: GenerateContentRequest | string | Array + ): Promise { + const formattedParams = formatGenerateContentInput(request); + return generateContentStream( + this._apiSettings, + this.model, + { + generationConfig: this.generationConfig, + safetySettings: this.safetySettings, + tools: this.tools, + toolConfig: this.toolConfig, + systemInstruction: this.systemInstruction, + ...formattedParams + }, + this.requestOptions + ); + } + + /** + * Gets a new {@link ChatSession} instance which can be used for + * multi-turn chats. + */ + startChat(startChatParams?: StartChatParams): ChatSession { + return new ChatSession( + this._apiSettings, + this.model, + { + tools: this.tools, + toolConfig: this.toolConfig, + systemInstruction: this.systemInstruction, + ...startChatParams + }, + this.requestOptions + ); + } + + /** + * Counts the tokens in the provided request. + */ + async countTokens( + request: CountTokensRequest | string | Array + ): Promise { + const formattedParams = formatGenerateContentInput(request); + return countTokens(this._apiSettings, this.model, formattedParams); + } +} diff --git a/packages/vertexai/src/public-types.ts b/packages/vertexai/src/public-types.ts new file mode 100644 index 00000000000..5577bc69c85 --- /dev/null +++ b/packages/vertexai/src/public-types.ts @@ -0,0 +1,40 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FirebaseApp } from '@firebase/app'; + +export * from './types'; + +/** + * An instance of the Vertex AI for Firebase SDK. + * @public + */ +export interface VertexAI { + /** + * The {@link @firebase/app#FirebaseApp} this {@link VertexAI} instance is associated with. + */ + app: FirebaseApp; + location: string; +} + +/** + * Options when initializing the Vertex AI for Firebase SDK. + * @public + */ +export interface VertexAIOptions { + location?: string; +} diff --git a/packages/vertexai/src/requests/request-helpers.test.ts b/packages/vertexai/src/requests/request-helpers.test.ts new file mode 100644 index 00000000000..76b2f0ca1bf --- /dev/null +++ b/packages/vertexai/src/requests/request-helpers.test.ts @@ -0,0 +1,202 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect, use } from 'chai'; +import sinonChai from 'sinon-chai'; +import { Content } from '../types'; +import { formatGenerateContentInput } from './request-helpers'; + +use(sinonChai); + +describe('request formatting methods', () => { + describe('formatGenerateContentInput', () => { + it('formats a text string into a request', () => { + const result = formatGenerateContentInput('some text content'); + expect(result).to.deep.equal({ + contents: [ + { + role: 'user', + parts: [{ text: 'some text content' }] + } + ] + }); + }); + it('formats an array of strings into a request', () => { + const result = formatGenerateContentInput(['txt1', 'txt2']); + expect(result).to.deep.equal({ + contents: [ + { + role: 'user', + parts: [{ text: 'txt1' }, { text: 'txt2' }] + } + ] + }); + }); + it('formats an array of Parts into a request', () => { + const result = formatGenerateContentInput([ + { text: 'txt1' }, + { text: 'txtB' } + ]); + expect(result).to.deep.equal({ + contents: [ + { + role: 'user', + parts: [{ text: 'txt1' }, { text: 'txtB' }] + } + ] + }); + }); + it('formats a mixed array into a request', () => { + const result = formatGenerateContentInput(['txtA', { text: 'txtB' }]); + expect(result).to.deep.equal({ + contents: [ + { + role: 'user', + parts: [{ text: 'txtA' }, { text: 'txtB' }] + } + ] + }); + }); + it('preserves other properties of request', () => { + const result = formatGenerateContentInput({ + contents: [ + { + role: 'user', + parts: [{ text: 'txtA' }] + } + ], + generationConfig: { topK: 100 } + }); + expect(result).to.deep.equal({ + contents: [ + { + role: 'user', + parts: [{ text: 'txtA' }] + } + ], + generationConfig: { topK: 100 } + }); + }); + it('formats systemInstructions if provided as text', () => { + const result = formatGenerateContentInput({ + contents: [ + { + role: 'user', + parts: [{ text: 'txtA' }] + } + ], + systemInstruction: 'be excited' + }); + expect(result).to.deep.equal({ + contents: [ + { + role: 'user', + parts: [{ text: 'txtA' }] + } + ], + systemInstruction: { role: 'system', parts: [{ text: 'be excited' }] } + }); + }); + it('formats systemInstructions if provided as Part', () => { + const result = formatGenerateContentInput({ + contents: [ + { + role: 'user', + parts: [{ text: 'txtA' }] + } + ], + systemInstruction: { text: 'be excited' } + }); + expect(result).to.deep.equal({ + contents: [ + { + role: 'user', + parts: [{ text: 'txtA' }] + } + ], + systemInstruction: { role: 'system', parts: [{ text: 'be excited' }] } + }); + }); + it('formats systemInstructions if provided as Content (no role)', () => { + const result = formatGenerateContentInput({ + contents: [ + { + role: 'user', + parts: [{ text: 'txtA' }] + } + ], + systemInstruction: { parts: [{ text: 'be excited' }] } as Content + }); + expect(result).to.deep.equal({ + contents: [ + { + role: 'user', + parts: [{ text: 'txtA' }] + } + ], + systemInstruction: { role: 'system', parts: [{ text: 'be excited' }] } + }); + }); + it('passes thru systemInstructions if provided as Content', () => { + const result = formatGenerateContentInput({ + contents: [ + { + role: 'user', + parts: [{ text: 'txtA' }] + } + ], + systemInstruction: { role: 'system', parts: [{ text: 'be excited' }] } + }); + expect(result).to.deep.equal({ + contents: [ + { + role: 'user', + parts: [{ text: 'txtA' }] + } + ], + systemInstruction: { role: 'system', parts: [{ text: 'be excited' }] } + }); + }), + it('formats fileData as part if provided as part', () => { + const result = formatGenerateContentInput([ + 'What is this?', + { + fileData: { + mimeType: 'image/jpeg', + fileUri: 'gs://sample.appspot.com/image.jpeg' + } + } + ]); + expect(result).to.be.deep.equal({ + contents: [ + { + role: 'user', + parts: [ + { text: 'What is this?' }, + { + fileData: { + mimeType: 'image/jpeg', + fileUri: 'gs://sample.appspot.com/image.jpeg' + } + } + ] + } + ] + }); + }); + }); +}); diff --git a/packages/vertexai/src/requests/request-helpers.ts b/packages/vertexai/src/requests/request-helpers.ts new file mode 100644 index 00000000000..0b7ce4ed4d2 --- /dev/null +++ b/packages/vertexai/src/requests/request-helpers.ts @@ -0,0 +1,120 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Content, GenerateContentRequest, Part } from '../types'; +import { ERROR_FACTORY, VertexError } from '../errors'; + +export function formatSystemInstruction( + input?: string | Part | Content +): Content | undefined { + // null or undefined + if (input == null) { + return undefined; + } else if (typeof input === 'string') { + return { role: 'system', parts: [{ text: input }] } as Content; + } else if ((input as Part).text) { + return { role: 'system', parts: [input as Part] }; + } else if ((input as Content).parts) { + if (!(input as Content).role) { + return { role: 'system', parts: (input as Content).parts }; + } else { + return input as Content; + } + } +} + +export function formatNewContent( + request: string | Array +): Content { + let newParts: Part[] = []; + if (typeof request === 'string') { + newParts = [{ text: request }]; + } else { + for (const partOrString of request) { + if (typeof partOrString === 'string') { + newParts.push({ text: partOrString }); + } else { + newParts.push(partOrString); + } + } + } + return assignRoleToPartsAndValidateSendMessageRequest(newParts); +} + +/** + * When multiple Part types (i.e. FunctionResponsePart and TextPart) are + * passed in a single Part array, we may need to assign different roles to each + * part. Currently only FunctionResponsePart requires a role other than 'user'. + * @private + * @param parts Array of parts to pass to the model + * @returns Array of content items + */ +function assignRoleToPartsAndValidateSendMessageRequest( + parts: Part[] +): Content { + const userContent: Content = { role: 'user', parts: [] }; + const functionContent: Content = { role: 'function', parts: [] }; + let hasUserContent = false; + let hasFunctionContent = false; + for (const part of parts) { + if ('functionResponse' in part) { + functionContent.parts.push(part); + hasFunctionContent = true; + } else { + userContent.parts.push(part); + hasUserContent = true; + } + } + + if (hasUserContent && hasFunctionContent) { + throw ERROR_FACTORY.create(VertexError.INVALID_CONTENT, { + message: + 'Within a single message, FunctionResponse cannot be mixed with other type of part in the request for sending chat message.' + }); + } + + if (!hasUserContent && !hasFunctionContent) { + throw ERROR_FACTORY.create(VertexError.INVALID_CONTENT, { + message: 'No content is provided for sending chat message.' + }); + } + + if (hasUserContent) { + return userContent; + } + + return functionContent; +} + +export function formatGenerateContentInput( + params: GenerateContentRequest | string | Array +): GenerateContentRequest { + let formattedRequest: GenerateContentRequest; + if ((params as GenerateContentRequest).contents) { + formattedRequest = params as GenerateContentRequest; + } else { + // Array or string + const content = formatNewContent(params as string | Array); + formattedRequest = { contents: [content] }; + } + if ((params as GenerateContentRequest).systemInstruction) { + formattedRequest.systemInstruction = formatSystemInstruction( + (params as GenerateContentRequest).systemInstruction + ); + } + return formattedRequest; +} diff --git a/packages/vertexai/src/requests/request.test.ts b/packages/vertexai/src/requests/request.test.ts new file mode 100644 index 00000000000..d27c4e41252 --- /dev/null +++ b/packages/vertexai/src/requests/request.test.ts @@ -0,0 +1,318 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect, use } from 'chai'; +import { restore, stub } from 'sinon'; +import sinonChai from 'sinon-chai'; +import chaiAsPromised from 'chai-as-promised'; +import { RequestUrl, Task, getHeaders, makeRequest } from './request'; +import { ApiSettings } from '../types/internal'; +import { DEFAULT_API_VERSION } from '../constants'; + +use(sinonChai); +use(chaiAsPromised); + +const fakeApiSettings: ApiSettings = { + apiKey: 'key', + project: 'my-project', + location: 'us-central1' +}; + +describe('request methods', () => { + afterEach(() => { + restore(); + }); + describe('RequestUrl', () => { + it('stream', async () => { + const url = new RequestUrl( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + true, + {} + ); + expect(url.toString()).to.include('models/model-name:generateContent'); + expect(url.toString()).to.not.include(fakeApiSettings); + expect(url.toString()).to.include('alt=sse'); + }); + it('non-stream', async () => { + const url = new RequestUrl( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + {} + ); + expect(url.toString()).to.include('models/model-name:generateContent'); + expect(url.toString()).to.not.include(fakeApiSettings); + expect(url.toString()).to.not.include('alt=sse'); + }); + it('default apiVersion', async () => { + const url = new RequestUrl( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + {} + ); + expect(url.toString()).to.include(DEFAULT_API_VERSION); + }); + it('custom baseUrl', async () => { + const url = new RequestUrl( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + { baseUrl: 'https://my.special.endpoint' } + ); + expect(url.toString()).to.include('https://my.special.endpoint'); + }); + it('non-stream - tunedModels/', async () => { + const url = new RequestUrl( + 'tunedModels/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + {} + ); + expect(url.toString()).to.include( + 'tunedModels/model-name:generateContent' + ); + expect(url.toString()).to.not.include(fakeApiSettings); + expect(url.toString()).to.not.include('alt=sse'); + }); + }); + describe('getHeaders', () => { + const fakeApiSettings: ApiSettings = { + apiKey: 'key', + project: 'myproject', + location: 'moon', + getAuthToken: () => Promise.resolve({ accessToken: 'authtoken' }), + getAppCheckToken: () => Promise.resolve({ token: 'appchecktoken' }) + }; + const fakeUrl = new RequestUrl( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + true, + {} + ); + it('adds client headers', async () => { + const headers = await getHeaders(fakeUrl); + expect(headers.get('x-goog-api-client')).to.match( + /gl-js\/[0-9\.]+ fire\/[0-9\.]+/ + ); + }); + it('adds api key', async () => { + const headers = await getHeaders(fakeUrl); + expect(headers.get('x-goog-api-key')).to.equal('key'); + }); + it('adds app check token if it exists', async () => { + const headers = await getHeaders(fakeUrl); + expect(headers.get('X-Firebase-AppCheck')).to.equal('appchecktoken'); + }); + it('ignores app check token header if no appcheck service', async () => { + const fakeUrl = new RequestUrl( + 'models/model-name', + Task.GENERATE_CONTENT, + { + apiKey: 'key', + project: 'myproject', + location: 'moon' + }, + true, + {} + ); + const headers = await getHeaders(fakeUrl); + expect(headers.has('X-Firebase-AppCheck')).to.be.false; + }); + it('ignores app check token header if returned token was undefined', async () => { + const fakeUrl = new RequestUrl( + 'models/model-name', + Task.GENERATE_CONTENT, + { + apiKey: 'key', + project: 'myproject', + location: 'moon', + //@ts-ignore + getAppCheckToken: () => Promise.resolve() + }, + true, + {} + ); + const headers = await getHeaders(fakeUrl); + expect(headers.has('X-Firebase-AppCheck')).to.be.false; + }); + it('ignores app check token header if returned token had error', async () => { + const fakeUrl = new RequestUrl( + 'models/model-name', + Task.GENERATE_CONTENT, + { + apiKey: 'key', + project: 'myproject', + location: 'moon', + getAppCheckToken: () => + Promise.resolve({ token: 'token', error: Error('oops') }) + }, + true, + {} + ); + const headers = await getHeaders(fakeUrl); + expect(headers.has('X-Firebase-AppCheck')).to.be.false; + }); + it('adds auth token if it exists', async () => { + const headers = await getHeaders(fakeUrl); + expect(headers.get('Authorization')).to.equal('Firebase authtoken'); + }); + it('ignores auth token header if no auth service', async () => { + const fakeUrl = new RequestUrl( + 'models/model-name', + Task.GENERATE_CONTENT, + { + apiKey: 'key', + project: 'myproject', + location: 'moon' + }, + true, + {} + ); + const headers = await getHeaders(fakeUrl); + expect(headers.has('Authorization')).to.be.false; + }); + it('ignores auth token header if returned token was undefined', async () => { + const fakeUrl = new RequestUrl( + 'models/model-name', + Task.GENERATE_CONTENT, + { + apiKey: 'key', + project: 'myproject', + location: 'moon', + //@ts-ignore + getAppCheckToken: () => Promise.resolve() + }, + true, + {} + ); + const headers = await getHeaders(fakeUrl); + expect(headers.has('Authorization')).to.be.false; + }); + }); + describe('makeRequest', () => { + it('no error', async () => { + const fetchStub = stub(globalThis, 'fetch').resolves({ + ok: true + } as Response); + const response = await makeRequest( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + '' + ); + expect(fetchStub).to.be.calledOnce; + expect(response.ok).to.be.true; + }); + it('error with timeout', async () => { + const fetchStub = stub(globalThis, 'fetch').resolves({ + ok: false, + status: 500, + statusText: 'AbortError' + } as Response); + + await expect( + makeRequest( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + '', + { + timeout: 0 + } + ) + ).to.be.rejectedWith('500 AbortError'); + expect(fetchStub).to.be.calledOnce; + }); + it('Network error, no response.json()', async () => { + const fetchStub = stub(globalThis, 'fetch').resolves({ + ok: false, + status: 500, + statusText: 'Server Error' + } as Response); + await expect( + makeRequest( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + '' + ) + ).to.be.rejectedWith(/500 Server Error/); + expect(fetchStub).to.be.calledOnce; + }); + it('Network error, includes response.json()', async () => { + const fetchStub = stub(globalThis, 'fetch').resolves({ + ok: false, + status: 500, + statusText: 'Server Error', + json: () => Promise.resolve({ error: { message: 'extra info' } }) + } as Response); + await expect( + makeRequest( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + '' + ) + ).to.be.rejectedWith(/500 Server Error.*extra info/); + expect(fetchStub).to.be.calledOnce; + }); + it('Network error, includes response.json() and details', async () => { + const fetchStub = stub(globalThis, 'fetch').resolves({ + ok: false, + status: 500, + statusText: 'Server Error', + json: () => + Promise.resolve({ + error: { + message: 'extra info', + details: [ + { + '@type': 'type.googleapis.com/google.rpc.DebugInfo', + detail: + '[ORIGINAL ERROR] generic::invalid_argument: invalid status photos.thumbnailer.Status.Code::5: Source image 0 too short' + } + ] + } + }) + } as Response); + await expect( + makeRequest( + 'models/model-name', + Task.GENERATE_CONTENT, + fakeApiSettings, + false, + '' + ) + ).to.be.rejectedWith( + /500 Server Error.*extra info.*generic::invalid_argument/ + ); + expect(fetchStub).to.be.calledOnce; + }); + }); +}); diff --git a/packages/vertexai/src/requests/request.ts b/packages/vertexai/src/requests/request.ts new file mode 100644 index 00000000000..ca78c16a383 --- /dev/null +++ b/packages/vertexai/src/requests/request.ts @@ -0,0 +1,180 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { RequestOptions } from '../types'; +import { ERROR_FACTORY, VertexError } from '../errors'; +import { ApiSettings } from '../types/internal'; +import { + DEFAULT_API_VERSION, + DEFAULT_BASE_URL, + LANGUAGE_TAG, + PACKAGE_VERSION +} from '../constants'; + +export enum Task { + GENERATE_CONTENT = 'generateContent', + STREAM_GENERATE_CONTENT = 'streamGenerateContent', + COUNT_TOKENS = 'countTokens' +} + +export class RequestUrl { + constructor( + public model: string, + public task: Task, + public apiSettings: ApiSettings, + public stream: boolean, + public requestOptions?: RequestOptions + ) {} + toString(): string { + // TODO: allow user-set option if that feature becomes available + const apiVersion = DEFAULT_API_VERSION; + const baseUrl = this.requestOptions?.baseUrl || DEFAULT_BASE_URL; + let url = `${baseUrl}/${apiVersion}`; + url += `/projects/${this.apiSettings.project}`; + url += `/locations/${this.apiSettings.location}`; + url += `/${this.model}`; + url += `:${this.task}`; + if (this.stream) { + url += '?alt=sse'; + } + return url; + } + + /** + * If the model needs to be passed to the backend, it needs to + * include project and location path. + */ + get fullModelString(): string { + let modelString = `projects/${this.apiSettings.project}`; + modelString += `/locations/${this.apiSettings.location}`; + modelString += `/${this.model}`; + return modelString; + } +} + +/** + * Log language and "fire/version" to x-goog-api-client + */ +function getClientHeaders(): string { + const loggingTags = []; + loggingTags.push(`${LANGUAGE_TAG}/${PACKAGE_VERSION}`); + loggingTags.push(`fire/${PACKAGE_VERSION}`); + return loggingTags.join(' '); +} + +export async function getHeaders(url: RequestUrl): Promise { + const headers = new Headers(); + headers.append('Content-Type', 'application/json'); + headers.append('x-goog-api-client', getClientHeaders()); + headers.append('x-goog-api-key', url.apiSettings.apiKey); + if (url.apiSettings.getAppCheckToken) { + const appCheckToken = await url.apiSettings.getAppCheckToken(); + if (appCheckToken && !appCheckToken.error) { + headers.append('X-Firebase-AppCheck', appCheckToken.token); + } + } + + if (url.apiSettings.getAuthToken) { + const authToken = await url.apiSettings.getAuthToken(); + if (authToken) { + headers.append('Authorization', `Firebase ${authToken.accessToken}`); + } + } + + return headers; +} + +export async function constructRequest( + model: string, + task: Task, + apiSettings: ApiSettings, + stream: boolean, + body: string, + requestOptions?: RequestOptions +): Promise<{ url: string; fetchOptions: RequestInit }> { + const url = new RequestUrl(model, task, apiSettings, stream, requestOptions); + return { + url: url.toString(), + fetchOptions: { + ...buildFetchOptions(requestOptions), + method: 'POST', + headers: await getHeaders(url), + body + } + }; +} + +export async function makeRequest( + model: string, + task: Task, + apiSettings: ApiSettings, + stream: boolean, + body: string, + requestOptions?: RequestOptions +): Promise { + const url = new RequestUrl(model, task, apiSettings, stream, requestOptions); + let response; + try { + const request = await constructRequest( + model, + task, + apiSettings, + stream, + body, + requestOptions + ); + response = await fetch(request.url, request.fetchOptions); + if (!response.ok) { + let message = ''; + try { + const json = await response.json(); + message = json.error.message; + if (json.error.details) { + message += ` ${JSON.stringify(json.error.details)}`; + } + } catch (e) { + // ignored + } + throw new Error(`[${response.status} ${response.statusText}] ${message}`); + } + } catch (caughtError) { + const e = caughtError as Error; + const err = ERROR_FACTORY.create(VertexError.FETCH_ERROR, { + url: url.toString(), + message: e.message + }); + err.stack = e.stack; + throw err; + } + return response; +} + +/** + * Generates the request options to be passed to the fetch API. + * @param requestOptions - The user-defined request options. + * @returns The generated request options. + */ +function buildFetchOptions(requestOptions?: RequestOptions): RequestInit { + const fetchOptions = {} as RequestInit; + if (requestOptions?.timeout && requestOptions?.timeout >= 0) { + const abortController = new AbortController(); + const signal = abortController.signal; + setTimeout(() => abortController.abort(), requestOptions.timeout); + fetchOptions.signal = signal; + } + return fetchOptions; +} diff --git a/packages/vertexai/src/requests/response-helpers.test.ts b/packages/vertexai/src/requests/response-helpers.test.ts new file mode 100644 index 00000000000..91a60d2cfce --- /dev/null +++ b/packages/vertexai/src/requests/response-helpers.test.ts @@ -0,0 +1,249 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { addHelpers, formatBlockErrorMessage } from './response-helpers'; +import { expect, use } from 'chai'; +import { restore } from 'sinon'; +import sinonChai from 'sinon-chai'; +import { + BlockReason, + Content, + FinishReason, + GenerateContentResponse +} from '../types'; + +use(sinonChai); + +const fakeResponseText: GenerateContentResponse = { + candidates: [ + { + index: 0, + content: { + role: 'model', + parts: [{ text: 'Some text' }, { text: ' and some more text' }] + } + } + ] +}; + +const functionCallPart1 = { + functionCall: { + name: 'find_theaters', + args: { + location: 'Mountain View, CA', + movie: 'Barbie' + } + } +}; + +const functionCallPart2 = { + functionCall: { + name: 'find_times', + args: { + location: 'Mountain View, CA', + movie: 'Barbie', + time: '20:00' + } + } +}; + +const fakeResponseFunctionCall: GenerateContentResponse = { + candidates: [ + { + index: 0, + content: { + role: 'model', + parts: [functionCallPart1] + } + } + ] +}; + +const fakeResponseFunctionCalls: GenerateContentResponse = { + candidates: [ + { + index: 0, + content: { + role: 'model', + parts: [functionCallPart1, functionCallPart2] + } + } + ] +}; + +const fakeResponseMixed1: GenerateContentResponse = { + candidates: [ + { + index: 0, + content: { + role: 'model', + parts: [{ text: 'some text' }, functionCallPart2] + } + } + ] +}; + +const fakeResponseMixed2: GenerateContentResponse = { + candidates: [ + { + index: 0, + content: { + role: 'model', + parts: [functionCallPart1, { text: 'some text' }] + } + } + ] +}; + +const fakeResponseMixed3: GenerateContentResponse = { + candidates: [ + { + index: 0, + content: { + role: 'model', + parts: [ + { text: 'some text' }, + functionCallPart1, + { text: ' and more text' } + ] + } + } + ] +}; + +const badFakeResponse: GenerateContentResponse = { + promptFeedback: { + blockReason: BlockReason.SAFETY, + safetyRatings: [] + } +}; + +describe('response-helpers methods', () => { + afterEach(() => { + restore(); + }); + describe('addHelpers', () => { + it('good response text', async () => { + const enhancedResponse = addHelpers(fakeResponseText); + expect(enhancedResponse.text()).to.equal('Some text and some more text'); + expect(enhancedResponse.functionCalls()).to.be.undefined; + }); + it('good response functionCall', async () => { + const enhancedResponse = addHelpers(fakeResponseFunctionCall); + expect(enhancedResponse.text()).to.equal(''); + expect(enhancedResponse.functionCalls()).to.deep.equal([ + functionCallPart1.functionCall + ]); + }); + it('good response functionCalls', async () => { + const enhancedResponse = addHelpers(fakeResponseFunctionCalls); + expect(enhancedResponse.text()).to.equal(''); + expect(enhancedResponse.functionCalls()).to.deep.equal([ + functionCallPart1.functionCall, + functionCallPart2.functionCall + ]); + }); + it('good response text/functionCall', async () => { + const enhancedResponse = addHelpers(fakeResponseMixed1); + expect(enhancedResponse.functionCalls()).to.deep.equal([ + functionCallPart2.functionCall + ]); + expect(enhancedResponse.text()).to.equal('some text'); + }); + it('good response functionCall/text', async () => { + const enhancedResponse = addHelpers(fakeResponseMixed2); + expect(enhancedResponse.functionCalls()).to.deep.equal([ + functionCallPart1.functionCall + ]); + expect(enhancedResponse.text()).to.equal('some text'); + }); + it('good response text/functionCall/text', async () => { + const enhancedResponse = addHelpers(fakeResponseMixed3); + expect(enhancedResponse.functionCalls()).to.deep.equal([ + functionCallPart1.functionCall + ]); + expect(enhancedResponse.text()).to.equal('some text and more text'); + }); + it('bad response safety', async () => { + const enhancedResponse = addHelpers(badFakeResponse); + expect(enhancedResponse.text).to.throw('SAFETY'); + }); + }); + describe('getBlockString', () => { + it('has no promptFeedback or bad finishReason', async () => { + const message = formatBlockErrorMessage({ + candidates: [ + { + index: 0, + finishReason: FinishReason.STOP, + finishMessage: 'this was fine', + content: {} as Content + } + ] + }); + expect(message).to.equal(''); + }); + it('has promptFeedback and blockReason only', async () => { + const message = formatBlockErrorMessage({ + promptFeedback: { + blockReason: BlockReason.SAFETY, + safetyRatings: [] + } + }); + expect(message).to.include('Response was blocked due to SAFETY'); + }); + it('has promptFeedback with blockReason and blockMessage', async () => { + const message = formatBlockErrorMessage({ + promptFeedback: { + blockReason: BlockReason.SAFETY, + blockReasonMessage: 'safety reasons', + safetyRatings: [] + } + }); + expect(message).to.include( + 'Response was blocked due to SAFETY: safety reasons' + ); + }); + it('has bad finishReason only', async () => { + const message = formatBlockErrorMessage({ + candidates: [ + { + index: 0, + finishReason: FinishReason.SAFETY, + content: {} as Content + } + ] + }); + expect(message).to.include('Candidate was blocked due to SAFETY'); + }); + it('has finishReason and finishMessage', async () => { + const message = formatBlockErrorMessage({ + candidates: [ + { + index: 0, + finishReason: FinishReason.SAFETY, + finishMessage: 'unsafe candidate', + content: {} as Content + } + ] + }); + expect(message).to.include( + 'Candidate was blocked due to SAFETY: unsafe candidate' + ); + }); + }); +}); diff --git a/packages/vertexai/src/requests/response-helpers.ts b/packages/vertexai/src/requests/response-helpers.ts new file mode 100644 index 00000000000..dc49123420f --- /dev/null +++ b/packages/vertexai/src/requests/response-helpers.ts @@ -0,0 +1,161 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + EnhancedGenerateContentResponse, + FinishReason, + FunctionCall, + GenerateContentCandidate, + GenerateContentResponse +} from '../types'; +import { ERROR_FACTORY, VertexError } from '../errors'; + +/** + * Adds convenience helper methods to a response object, including stream + * chunks (as long as each chunk is a complete GenerateContentResponse JSON). + */ +export function addHelpers( + response: GenerateContentResponse +): EnhancedGenerateContentResponse { + (response as EnhancedGenerateContentResponse).text = () => { + if (response.candidates && response.candidates.length > 0) { + if (response.candidates.length > 1) { + console.warn( + `This response had ${response.candidates.length} ` + + `candidates. Returning text from the first candidate only. ` + + `Access response.candidates directly to use the other candidates.` + ); + } + if (hadBadFinishReason(response.candidates[0])) { + throw ERROR_FACTORY.create(VertexError.RESPONSE_ERROR, { + message: `${formatBlockErrorMessage(response)}`, + response + }); + } + return getText(response); + } else if (response.promptFeedback) { + throw ERROR_FACTORY.create(VertexError.RESPONSE_ERROR, { + message: `Text not available. ${formatBlockErrorMessage(response)}`, + response + }); + } + return ''; + }; + (response as EnhancedGenerateContentResponse).functionCalls = () => { + if (response.candidates && response.candidates.length > 0) { + if (response.candidates.length > 1) { + console.warn( + `This response had ${response.candidates.length} ` + + `candidates. Returning function calls from the first candidate only. ` + + `Access response.candidates directly to use the other candidates.` + ); + } + if (hadBadFinishReason(response.candidates[0])) { + throw ERROR_FACTORY.create(VertexError.RESPONSE_ERROR, { + message: `${formatBlockErrorMessage(response)}`, + response + }); + } + return getFunctionCalls(response); + } else if (response.promptFeedback) { + throw ERROR_FACTORY.create(VertexError.RESPONSE_ERROR, { + message: `Function call not available. ${formatBlockErrorMessage( + response + )}`, + response + }); + } + return undefined; + }; + return response as EnhancedGenerateContentResponse; +} + +/** + * Returns all text found in all parts of first candidate. + */ +export function getText(response: GenerateContentResponse): string { + const textStrings = []; + if (response.candidates?.[0].content?.parts) { + for (const part of response.candidates?.[0].content?.parts) { + if (part.text) { + textStrings.push(part.text); + } + } + } + if (textStrings.length > 0) { + return textStrings.join(''); + } else { + return ''; + } +} + +/** + * Returns {@link FunctionCall}s associated with first candidate. + */ +export function getFunctionCalls( + response: GenerateContentResponse +): FunctionCall[] | undefined { + const functionCalls: FunctionCall[] = []; + if (response.candidates?.[0].content?.parts) { + for (const part of response.candidates?.[0].content?.parts) { + if (part.functionCall) { + functionCalls.push(part.functionCall); + } + } + } + if (functionCalls.length > 0) { + return functionCalls; + } else { + return undefined; + } +} + +const badFinishReasons = [FinishReason.RECITATION, FinishReason.SAFETY]; + +function hadBadFinishReason(candidate: GenerateContentCandidate): boolean { + return ( + !!candidate.finishReason && + badFinishReasons.includes(candidate.finishReason) + ); +} + +export function formatBlockErrorMessage( + response: GenerateContentResponse +): string { + let message = ''; + if ( + (!response.candidates || response.candidates.length === 0) && + response.promptFeedback + ) { + message += 'Response was blocked'; + if (response.promptFeedback?.blockReason) { + message += ` due to ${response.promptFeedback.blockReason}`; + } + if (response.promptFeedback?.blockReasonMessage) { + message += `: ${response.promptFeedback.blockReasonMessage}`; + } + } else if (response.candidates?.[0]) { + const firstCandidate = response.candidates[0]; + if (hadBadFinishReason(firstCandidate)) { + message += `Candidate was blocked due to ${firstCandidate.finishReason}`; + if (firstCandidate.finishMessage) { + message += `: ${firstCandidate.finishMessage}`; + } + } + } + return message; +} diff --git a/packages/vertexai/src/requests/stream-reader.test.ts b/packages/vertexai/src/requests/stream-reader.test.ts new file mode 100644 index 00000000000..ae6d9fd33e4 --- /dev/null +++ b/packages/vertexai/src/requests/stream-reader.test.ts @@ -0,0 +1,404 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + aggregateResponses, + getResponseStream, + processStream +} from './stream-reader'; +import { expect, use } from 'chai'; +import { restore } from 'sinon'; +import sinonChai from 'sinon-chai'; +import { + getChunkedStream, + getMockResponseStreaming +} from '../../test-utils/mock-response'; +import { + BlockReason, + FinishReason, + GenerateContentResponse, + HarmCategory, + HarmProbability, + SafetyRating +} from '../types'; + +use(sinonChai); + +describe('getResponseStream', () => { + afterEach(() => { + restore(); + }); + it('two lines', async () => { + const src = [{ text: 'A' }, { text: 'B' }]; + const inputStream = getChunkedStream( + src + .map(v => JSON.stringify(v)) + .map(v => 'data: ' + v + '\r\n\r\n') + .join('') + ).pipeThrough(new TextDecoderStream('utf8', { fatal: true })); + const responseStream = getResponseStream<{ text: string }>(inputStream); + const reader = responseStream.getReader(); + const responses: Array<{ text: string }> = []; + while (true) { + const { done, value } = await reader.read(); + if (done) { + break; + } + responses.push(value); + } + expect(responses).to.deep.equal(src); + }); +}); + +describe('processStream', () => { + afterEach(() => { + restore(); + }); + it('streaming response - short', async () => { + const fakeResponse = getMockResponseStreaming( + 'streaming-success-basic-reply-short.txt' + ); + const result = processStream(fakeResponse as Response); + for await (const response of result.stream) { + expect(response.text()).to.not.be.empty; + } + const aggregatedResponse = await result.response; + expect(aggregatedResponse.text()).to.include('Cheyenne'); + }); + it('streaming response - long', async () => { + const fakeResponse = getMockResponseStreaming( + 'streaming-success-basic-reply-long.txt' + ); + const result = processStream(fakeResponse as Response); + for await (const response of result.stream) { + expect(response.text()).to.not.be.empty; + } + const aggregatedResponse = await result.response; + expect(aggregatedResponse.text()).to.include('**Cats:**'); + expect(aggregatedResponse.text()).to.include('to their owners.'); + }); + it('streaming response - long - big chunk', async () => { + const fakeResponse = getMockResponseStreaming( + 'streaming-success-basic-reply-long.txt', + 1e6 + ); + const result = processStream(fakeResponse as Response); + for await (const response of result.stream) { + expect(response.text()).to.not.be.empty; + } + const aggregatedResponse = await result.response; + expect(aggregatedResponse.text()).to.include('**Cats:**'); + expect(aggregatedResponse.text()).to.include('to their owners.'); + }); + it('streaming response - utf8', async () => { + const fakeResponse = getMockResponseStreaming('streaming-success-utf8.txt'); + const result = processStream(fakeResponse as Response); + for await (const response of result.stream) { + expect(response.text()).to.not.be.empty; + } + const aggregatedResponse = await result.response; + expect(aggregatedResponse.text()).to.include('秋风瑟瑟,叶落纷纷'); + expect(aggregatedResponse.text()).to.include('家人围坐在一起'); + }); + it('streaming response - functioncall', async () => { + const fakeResponse = getMockResponseStreaming( + 'streaming-success-function-call-short.txt' + ); + const result = processStream(fakeResponse as Response); + for await (const response of result.stream) { + expect(response.text()).to.be.empty; + expect(response.functionCalls()).to.be.deep.equal([ + { + name: 'getTemperature', + args: { city: 'San Jose' } + } + ]); + } + const aggregatedResponse = await result.response; + expect(aggregatedResponse.text()).to.be.empty; + expect(aggregatedResponse.functionCalls()).to.be.deep.equal([ + { + name: 'getTemperature', + args: { city: 'San Jose' } + } + ]); + }); + it('candidate had finishReason', async () => { + const fakeResponse = getMockResponseStreaming( + 'streaming-failure-finish-reason-safety.txt' + ); + const result = processStream(fakeResponse as Response); + const aggregatedResponse = await result.response; + expect(aggregatedResponse.candidates?.[0].finishReason).to.equal('SAFETY'); + expect(aggregatedResponse.text).to.throw('SAFETY'); + for await (const response of result.stream) { + expect(response.text).to.throw('SAFETY'); + } + }); + it('prompt was blocked', async () => { + const fakeResponse = getMockResponseStreaming( + 'streaming-failure-prompt-blocked-safety.txt' + ); + const result = processStream(fakeResponse as Response); + const aggregatedResponse = await result.response; + expect(aggregatedResponse.text).to.throw('SAFETY'); + expect(aggregatedResponse.promptFeedback?.blockReason).to.equal('SAFETY'); + for await (const response of result.stream) { + expect(response.text).to.throw('SAFETY'); + } + }); + it('empty content', async () => { + const fakeResponse = getMockResponseStreaming( + 'streaming-failure-empty-content.txt' + ); + const result = processStream(fakeResponse as Response); + const aggregatedResponse = await result.response; + expect(aggregatedResponse.text()).to.equal(''); + for await (const response of result.stream) { + expect(response.text()).to.equal(''); + } + }); + it('unknown enum - should ignore', async () => { + const fakeResponse = getMockResponseStreaming('streaming-unknown-enum.txt'); + const result = processStream(fakeResponse as Response); + const aggregatedResponse = await result.response; + expect(aggregatedResponse.text()).to.include('Cats'); + for await (const response of result.stream) { + expect(response.text()).to.not.be.empty; + } + }); + it('recitation ending with a missing content field', async () => { + const fakeResponse = getMockResponseStreaming( + 'streaming-failure-recitation-no-content.txt' + ); + const result = processStream(fakeResponse as Response); + const aggregatedResponse = await result.response; + expect(aggregatedResponse.text).to.throw('RECITATION'); + expect(aggregatedResponse.candidates?.[0].content.parts[0].text).to.include( + 'Copyrighted text goes here' + ); + for await (const response of result.stream) { + if (response.candidates?.[0].finishReason !== FinishReason.RECITATION) { + expect(response.text()).to.not.be.empty; + } else { + expect(response.text).to.throw('RECITATION'); + } + } + }); + it('handles citations', async () => { + const fakeResponse = getMockResponseStreaming( + 'streaming-success-citations.txt' + ); + const result = processStream(fakeResponse as Response); + const aggregatedResponse = await result.response; + expect(aggregatedResponse.text()).to.include('Quantum mechanics is'); + expect( + aggregatedResponse.candidates?.[0].citationMetadata?.citations.length + ).to.equal(2); + let foundCitationMetadata = false; + for await (const response of result.stream) { + expect(response.text()).to.not.be.empty; + if (response.candidates?.[0].citationMetadata) { + foundCitationMetadata = true; + } + } + expect(foundCitationMetadata).to.be.true; + }); +}); + +describe('aggregateResponses', () => { + it('handles no candidates, and promptFeedback', () => { + const responsesToAggregate: GenerateContentResponse[] = [ + { + promptFeedback: { + blockReason: BlockReason.SAFETY, + safetyRatings: [ + { + category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, + probability: HarmProbability.LOW + } as SafetyRating + ] + } + } + ]; + const response = aggregateResponses(responsesToAggregate); + expect(response.candidates).to.not.exist; + expect(response.promptFeedback?.blockReason).to.equal(BlockReason.SAFETY); + }); + describe('multiple responses, has candidates', () => { + let response: GenerateContentResponse; + before(() => { + const responsesToAggregate: GenerateContentResponse[] = [ + { + candidates: [ + { + index: 0, + content: { + role: 'user', + parts: [{ text: 'hello.' }] + }, + finishReason: FinishReason.STOP, + finishMessage: 'something', + safetyRatings: [ + { + category: HarmCategory.HARM_CATEGORY_HARASSMENT, + probability: HarmProbability.NEGLIGIBLE + } as SafetyRating + ] + } + ], + promptFeedback: { + blockReason: BlockReason.SAFETY, + safetyRatings: [ + { + category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, + probability: HarmProbability.LOW + } as SafetyRating + ] + } + }, + { + candidates: [ + { + index: 0, + content: { + role: 'user', + parts: [{ text: 'angry stuff' }] + }, + finishReason: FinishReason.STOP, + finishMessage: 'something', + safetyRatings: [ + { + category: HarmCategory.HARM_CATEGORY_HARASSMENT, + probability: HarmProbability.NEGLIGIBLE + } as SafetyRating + ], + citationMetadata: { + citations: [ + { + startIndex: 0, + endIndex: 20, + uri: 'sourceurl', + license: '' + } + ] + } + } + ], + promptFeedback: { + blockReason: BlockReason.OTHER, + safetyRatings: [ + { + category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, + probability: HarmProbability.HIGH + } as SafetyRating + ] + } + }, + { + candidates: [ + { + index: 0, + content: { + role: 'user', + parts: [{ text: '...more stuff' }] + }, + finishReason: FinishReason.MAX_TOKENS, + finishMessage: 'too many tokens', + safetyRatings: [ + { + category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, + probability: HarmProbability.MEDIUM + } as SafetyRating + ], + citationMetadata: { + citations: [ + { + startIndex: 0, + endIndex: 20, + uri: 'sourceurl', + license: '' + }, + { + startIndex: 150, + endIndex: 155, + uri: 'sourceurl', + license: '' + } + ] + } + } + ], + promptFeedback: { + blockReason: BlockReason.OTHER, + safetyRatings: [ + { + category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, + probability: HarmProbability.HIGH + } as SafetyRating + ] + } + } + ]; + response = aggregateResponses(responsesToAggregate); + }); + + it('aggregates text across responses', () => { + expect(response.candidates?.length).to.equal(1); + expect( + response.candidates?.[0].content.parts.map(({ text }) => text) + ).to.deep.equal(['hello.', 'angry stuff', '...more stuff']); + }); + + it("takes the last response's promptFeedback", () => { + expect(response.promptFeedback?.blockReason).to.equal(BlockReason.OTHER); + }); + + it("takes the last response's finishReason", () => { + expect(response.candidates?.[0].finishReason).to.equal( + FinishReason.MAX_TOKENS + ); + }); + + it("takes the last response's finishMessage", () => { + expect(response.candidates?.[0].finishMessage).to.equal( + 'too many tokens' + ); + }); + + it("takes the last response's candidate safetyRatings", () => { + expect(response.candidates?.[0].safetyRatings?.[0].category).to.equal( + HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT + ); + expect(response.candidates?.[0].safetyRatings?.[0].probability).to.equal( + HarmProbability.MEDIUM + ); + }); + + it('collects all citations into one array', () => { + expect( + response.candidates?.[0].citationMetadata?.citations.length + ).to.equal(2); + expect( + response.candidates?.[0].citationMetadata?.citations[0].startIndex + ).to.equal(0); + expect( + response.candidates?.[0].citationMetadata?.citations[1].startIndex + ).to.equal(150); + }); + }); +}); diff --git a/packages/vertexai/src/requests/stream-reader.ts b/packages/vertexai/src/requests/stream-reader.ts new file mode 100644 index 00000000000..0c070cfe0f2 --- /dev/null +++ b/packages/vertexai/src/requests/stream-reader.ts @@ -0,0 +1,195 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + EnhancedGenerateContentResponse, + GenerateContentCandidate, + GenerateContentResponse, + GenerateContentStreamResult, + Part +} from '../types'; +import { ERROR_FACTORY, VertexError } from '../errors'; +import { addHelpers } from './response-helpers'; + +const responseLineRE = /^data\: (.*)(?:\n\n|\r\r|\r\n\r\n)/; + +/** + * Process a response.body stream from the backend and return an + * iterator that provides one complete GenerateContentResponse at a time + * and a promise that resolves with a single aggregated + * GenerateContentResponse. + * + * @param response - Response from a fetch call + */ +export function processStream(response: Response): GenerateContentStreamResult { + const inputStream = response.body!.pipeThrough( + new TextDecoderStream('utf8', { fatal: true }) + ); + const responseStream = + getResponseStream(inputStream); + const [stream1, stream2] = responseStream.tee(); + return { + stream: generateResponseSequence(stream1), + response: getResponsePromise(stream2) + }; +} + +async function getResponsePromise( + stream: ReadableStream +): Promise { + const allResponses: GenerateContentResponse[] = []; + const reader = stream.getReader(); + while (true) { + const { done, value } = await reader.read(); + if (done) { + return addHelpers(aggregateResponses(allResponses)); + } + allResponses.push(value); + } +} + +async function* generateResponseSequence( + stream: ReadableStream +): AsyncGenerator { + const reader = stream.getReader(); + while (true) { + const { value, done } = await reader.read(); + if (done) { + break; + } + yield addHelpers(value); + } +} + +/** + * Reads a raw stream from the fetch response and join incomplete + * chunks, returning a new stream that provides a single complete + * GenerateContentResponse in each iteration. + */ +export function getResponseStream( + inputStream: ReadableStream +): ReadableStream { + const reader = inputStream.getReader(); + const stream = new ReadableStream({ + start(controller) { + let currentText = ''; + return pump(); + function pump(): Promise<(() => Promise) | undefined> { + return reader.read().then(({ value, done }) => { + if (done) { + if (currentText.trim()) { + controller.error( + ERROR_FACTORY.create(VertexError.PARSE_FAILED, { + message: 'Failed to parse stream' + }) + ); + return; + } + controller.close(); + return; + } + + currentText += value; + let match = currentText.match(responseLineRE); + let parsedResponse: T; + while (match) { + try { + parsedResponse = JSON.parse(match[1]); + } catch (e) { + controller.error( + ERROR_FACTORY.create(VertexError.PARSE_FAILED, { + message: `Error parsing JSON response: "${match[1]}"` + }) + ); + return; + } + controller.enqueue(parsedResponse); + currentText = currentText.substring(match[0].length); + match = currentText.match(responseLineRE); + } + return pump(); + }); + } + } + }); + return stream; +} + +/** + * Aggregates an array of `GenerateContentResponse`s into a single + * GenerateContentResponse. + */ +export function aggregateResponses( + responses: GenerateContentResponse[] +): GenerateContentResponse { + const lastResponse = responses[responses.length - 1]; + const aggregatedResponse: GenerateContentResponse = { + promptFeedback: lastResponse?.promptFeedback + }; + for (const response of responses) { + if (response.candidates) { + for (const candidate of response.candidates) { + const i = candidate.index; + if (!aggregatedResponse.candidates) { + aggregatedResponse.candidates = []; + } + if (!aggregatedResponse.candidates[i]) { + aggregatedResponse.candidates[i] = { + index: candidate.index + } as GenerateContentCandidate; + } + // Keep overwriting, the last one will be final + aggregatedResponse.candidates[i].citationMetadata = + candidate.citationMetadata; + aggregatedResponse.candidates[i].finishReason = candidate.finishReason; + aggregatedResponse.candidates[i].finishMessage = + candidate.finishMessage; + aggregatedResponse.candidates[i].safetyRatings = + candidate.safetyRatings; + + /** + * Candidates should always have content and parts, but this handles + * possible malformed responses. + */ + if (candidate.content && candidate.content.parts) { + if (!aggregatedResponse.candidates[i].content) { + aggregatedResponse.candidates[i].content = { + role: candidate.content.role || 'user', + parts: [] + }; + } + const newPart: Partial = {}; + for (const part of candidate.content.parts) { + if (part.text) { + newPart.text = part.text; + } + if (part.functionCall) { + newPart.functionCall = part.functionCall; + } + if (Object.keys(newPart).length === 0) { + newPart.text = ''; + } + aggregatedResponse.candidates[i].content.parts.push( + newPart as Part + ); + } + } + } + } + } + return aggregatedResponse; +} diff --git a/packages/vertexai/src/service.test.ts b/packages/vertexai/src/service.test.ts new file mode 100644 index 00000000000..d3487e9bdd2 --- /dev/null +++ b/packages/vertexai/src/service.test.ts @@ -0,0 +1,44 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { DEFAULT_LOCATION } from './constants'; +import { VertexAIService } from './service'; +import { expect } from 'chai'; + +const fakeApp = { + name: 'DEFAULT', + automaticDataCollectionEnabled: true, + options: { + apiKey: 'key', + projectId: 'my-project' + } +}; + +describe('VertexAIService', () => { + it('uses default location if not specified', () => { + const vertexAI = new VertexAIService(fakeApp); + expect(vertexAI.location).to.equal(DEFAULT_LOCATION); + }); + it('uses custom location if specified', () => { + const vertexAI = new VertexAIService( + fakeApp, + /* authProvider */ undefined, + /* appCheckProvider */ undefined, + { location: 'somewhere' } + ); + expect(vertexAI.location).to.equal('somewhere'); + }); +}); diff --git a/packages/vertexai/src/service.ts b/packages/vertexai/src/service.ts new file mode 100644 index 00000000000..05b2d559e58 --- /dev/null +++ b/packages/vertexai/src/service.ts @@ -0,0 +1,52 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FirebaseApp, _FirebaseService } from '@firebase/app'; +import { VertexAI, VertexAIOptions } from './public-types'; +import { + AppCheckInternalComponentName, + FirebaseAppCheckInternal +} from '@firebase/app-check-interop-types'; +import { Provider } from '@firebase/component'; +import { + FirebaseAuthInternal, + FirebaseAuthInternalName +} from '@firebase/auth-interop-types'; +import { DEFAULT_LOCATION } from './constants'; + +export class VertexAIService implements VertexAI, _FirebaseService { + auth: FirebaseAuthInternal | null; + appCheck: FirebaseAppCheckInternal | null; + location: string; + + constructor( + public app: FirebaseApp, + authProvider?: Provider, + appCheckProvider?: Provider, + public options?: VertexAIOptions + ) { + const appCheck = appCheckProvider?.getImmediate({ optional: true }); + const auth = authProvider?.getImmediate({ optional: true }); + this.auth = auth || null; + this.appCheck = appCheck || null; + this.location = this.options?.location || DEFAULT_LOCATION; + } + + _delete(): Promise { + return Promise.resolve(); + } +} diff --git a/packages/vertexai/src/types/content.ts b/packages/vertexai/src/types/content.ts new file mode 100644 index 00000000000..ad2906671e4 --- /dev/null +++ b/packages/vertexai/src/types/content.ts @@ -0,0 +1,162 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Role } from './enums'; + +/** + * Content type for both prompts and response candidates. + * @public + */ +export interface Content { + role: Role; + parts: Part[]; +} + +/** + * Content part - includes text, image/video, or function call/response + * part types. + * @public + */ +export type Part = + | TextPart + | InlineDataPart + | FunctionCallPart + | FunctionResponsePart + | FileDataPart; + +/** + * Content part interface if the part represents a text string. + * @public + */ +export interface TextPart { + text: string; + inlineData?: never; + functionCall?: never; + functionResponse?: never; +} + +/** + * Content part interface if the part represents an image. + * @public + */ +export interface InlineDataPart { + text?: never; + inlineData: GenerativeContentBlob; + functionCall?: never; + functionResponse?: never; + /** + * Applicable if `inlineData` is a video. + */ + videoMetadata?: VideoMetadata; +} + +/** + * Describes the input video content. + * @public + */ +export interface VideoMetadata { + /** + * The start offset of the video in + * protobuf {@link https://cloud.google.com/ruby/docs/reference/google-cloud-workflows-v1/latest/Google-Protobuf-Duration#json-mapping | Duration} format. + */ + startOffset: string; + /** + * The end offset of the video in + * protobuf {@link https://cloud.google.com/ruby/docs/reference/google-cloud-workflows-v1/latest/Google-Protobuf-Duration#json-mapping | Duration} format. + */ + endOffset: string; +} + +/** + * Content part interface if the part represents a {@link FunctionCall}. + * @public + */ +export interface FunctionCallPart { + text?: never; + inlineData?: never; + functionCall: FunctionCall; + functionResponse?: never; +} + +/** + * Content part interface if the part represents {@link FunctionResponse}. + * @public + */ +export interface FunctionResponsePart { + text?: never; + inlineData?: never; + functionCall?: never; + functionResponse: FunctionResponse; +} + +/** + * Content part interface if the part represents {@link FileData} + * @public + */ +export interface FileDataPart { + text?: never; + inlineData?: never; + functionCall?: never; + functionResponse?: never; + fileData: FileData; +} + +/** + * A predicted {@link FunctionCall} returned from the model + * that contains a string representing the {@link FunctionDeclaration.name} + * and a structured JSON object containing the parameters and their values. + * @public + */ +export interface FunctionCall { + name: string; + args: object; +} + +/** + * The result output from a {@link FunctionCall} that contains a string + * representing the {@link FunctionDeclaration.name} + * and a structured JSON object containing any output + * from the function is used as context to the model. + * This should contain the result of a {@link FunctionCall} + * made based on model prediction. + * @public + */ +export interface FunctionResponse { + name: string; + response: object; +} + +/** + * Interface for sending an image. + * @public + */ +export interface GenerativeContentBlob { + mimeType: string; + /** + * Image as a base64 string. + */ + data: string; +} + +/** + * Data pointing to a file uploaded on Google Cloud Storage. + * @public + */ +export interface FileData { + mimeType: string; + fileUri: string; +} diff --git a/packages/vertexai/src/types/enums.ts b/packages/vertexai/src/types/enums.ts new file mode 100644 index 00000000000..2f3f655e8f0 --- /dev/null +++ b/packages/vertexai/src/types/enums.ts @@ -0,0 +1,154 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Role is the producer of the content. + * @public + */ +export type Role = (typeof POSSIBLE_ROLES)[number]; + +/** + * Possible roles. + * @public + */ +export const POSSIBLE_ROLES = ['user', 'model', 'function', 'system'] as const; + +/** + * Harm categories that would cause prompts or candidates to be blocked. + * @public + */ +export enum HarmCategory { + HARM_CATEGORY_UNSPECIFIED = 'HARM_CATEGORY_UNSPECIFIED', + HARM_CATEGORY_HATE_SPEECH = 'HARM_CATEGORY_HATE_SPEECH', + HARM_CATEGORY_SEXUALLY_EXPLICIT = 'HARM_CATEGORY_SEXUALLY_EXPLICIT', + HARM_CATEGORY_HARASSMENT = 'HARM_CATEGORY_HARASSMENT', + HARM_CATEGORY_DANGEROUS_CONTENT = 'HARM_CATEGORY_DANGEROUS_CONTENT' +} + +/** + * Threshold above which a prompt or candidate will be blocked. + * @public + */ +export enum HarmBlockThreshold { + // Threshold is unspecified. + HARM_BLOCK_THRESHOLD_UNSPECIFIED = 'HARM_BLOCK_THRESHOLD_UNSPECIFIED', + // Content with NEGLIGIBLE will be allowed. + BLOCK_LOW_AND_ABOVE = 'BLOCK_LOW_AND_ABOVE', + // Content with NEGLIGIBLE and LOW will be allowed. + BLOCK_MEDIUM_AND_ABOVE = 'BLOCK_MEDIUM_AND_ABOVE', + // Content with NEGLIGIBLE, LOW, and MEDIUM will be allowed. + BLOCK_ONLY_HIGH = 'BLOCK_ONLY_HIGH', + // All content will be allowed. + BLOCK_NONE = 'BLOCK_NONE' +} + +/** + * @public + */ +export enum HarmBlockMethod { + // The harm block method is unspecified. + HARM_BLOCK_METHOD_UNSPECIFIED = 'HARM_BLOCK_METHOD_UNSPECIFIED', + // The harm block method uses both probability and severity scores. + SEVERITY = 'SEVERITY', + // The harm block method uses the probability score. + PROBABILITY = 'PROBABILITY' +} + +/** + * Probability that a prompt or candidate matches a harm category. + * @public + */ +export enum HarmProbability { + // Probability is unspecified. + HARM_PROBABILITY_UNSPECIFIED = 'HARM_PROBABILITY_UNSPECIFIED', + // Content has a negligible chance of being unsafe. + NEGLIGIBLE = 'NEGLIGIBLE', + // Content has a low chance of being unsafe. + LOW = 'LOW', + // Content has a medium chance of being unsafe. + MEDIUM = 'MEDIUM', + // Content has a high chance of being unsafe. + HIGH = 'HIGH' +} + +/** + * Harm severity levels. + * @public + */ +export enum HarmSeverity { + // Harm severity unspecified. + HARM_SEVERITY_UNSPECIFIED = 'HARM_SEVERITY_UNSPECIFIED', + // Negligible level of harm severity. + HARM_SEVERITY_NEGLIGIBLE = 'HARM_SEVERITY_NEGLIGIBLE', + // Low level of harm severity. + HARM_SEVERITY_LOW = 'HARM_SEVERITY_LOW', + // Medium level of harm severity. + HARM_SEVERITY_MEDIUM = 'HARM_SEVERITY_MEDIUM', + // High level of harm severity. + HARM_SEVERITY_HIGH = 'HARM_SEVERITY_HIGH' +} + +/** + * Reason that a prompt was blocked. + * @public + */ +export enum BlockReason { + // A blocked reason was not specified. + BLOCKED_REASON_UNSPECIFIED = 'BLOCKED_REASON_UNSPECIFIED', + // Content was blocked by safety settings. + SAFETY = 'SAFETY', + // Content was blocked, but the reason is uncategorized. + OTHER = 'OTHER' +} + +/** + * Reason that a candidate finished. + * @public + */ +export enum FinishReason { + // Default value. This value is unused. + FINISH_REASON_UNSPECIFIED = 'FINISH_REASON_UNSPECIFIED', + // Natural stop point of the model or provided stop sequence. + STOP = 'STOP', + // The maximum number of tokens as specified in the request was reached. + MAX_TOKENS = 'MAX_TOKENS', + // The candidate content was flagged for safety reasons. + SAFETY = 'SAFETY', + // The candidate content was flagged for recitation reasons. + RECITATION = 'RECITATION', + // Unknown reason. + OTHER = 'OTHER' +} + +/** + * @public + */ +export enum FunctionCallingMode { + // Unspecified function calling mode. This value should not be used. + MODE_UNSPECIFIED = 'MODE_UNSPECIFIED', + // Default model behavior, model decides to predict either a function call + // or a natural language repspose. + AUTO = 'AUTO', + // Model is constrained to always predicting a function call only. + // If "allowed_function_names" is set, the predicted function call will be + // limited to any one of "allowed_function_names", else the predicted + // function call will be any one of the provided "function_declarations". + ANY = 'ANY', + // Model will not predict any function call. Model behavior is same as when + // not passing any function declarations. + NONE = 'NONE' +} diff --git a/packages/vertexai/src/types/index.ts b/packages/vertexai/src/types/index.ts new file mode 100644 index 00000000000..3782a66cc36 --- /dev/null +++ b/packages/vertexai/src/types/index.ts @@ -0,0 +1,21 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './content'; +export * from './enums'; +export * from './requests'; +export * from './responses'; diff --git a/packages/vertexai/src/types/internal.ts b/packages/vertexai/src/types/internal.ts new file mode 100644 index 00000000000..8271175feff --- /dev/null +++ b/packages/vertexai/src/types/internal.ts @@ -0,0 +1,27 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AppCheckTokenResult } from '@firebase/app-check-interop-types'; +import { FirebaseAuthTokenData } from '@firebase/auth-interop-types'; + +export interface ApiSettings { + apiKey: string; + project: string; + location: string; + getAuthToken?: () => Promise; + getAppCheckToken?: () => Promise; +} diff --git a/packages/vertexai/src/types/requests.ts b/packages/vertexai/src/types/requests.ts new file mode 100644 index 00000000000..5da8f05b6bb --- /dev/null +++ b/packages/vertexai/src/types/requests.ts @@ -0,0 +1,260 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Content, Part } from './content'; +import { + FunctionCallingMode, + HarmBlockMethod, + HarmBlockThreshold, + HarmCategory +} from './enums'; + +/** + * Base parameters for a number of methods. + * @public + */ +export interface BaseParams { + safetySettings?: SafetySetting[]; + generationConfig?: GenerationConfig; +} + +/** + * Params passed to {@link getGenerativeModel}. + * @public + */ +export interface ModelParams extends BaseParams { + model: string; + tools?: Tool[]; + toolConfig?: ToolConfig; + systemInstruction?: string | Part | Content; +} + +/** + * Request sent through {@link GenerativeModel.generateContent} + * @public + */ +export interface GenerateContentRequest extends BaseParams { + contents: Content[]; + tools?: Tool[]; + toolConfig?: ToolConfig; + systemInstruction?: string | Part | Content; +} + +/** + * Safety setting that can be sent as part of request parameters. + * @public + */ +export interface SafetySetting { + category: HarmCategory; + threshold: HarmBlockThreshold; + method: HarmBlockMethod; +} + +/** + * Config options for content-related requests + * @public + */ +export interface GenerationConfig { + candidateCount?: number; + stopSequences?: string[]; + maxOutputTokens?: number; + temperature?: number; + topP?: number; + topK?: number; + presencePenalty?: number; + frequencyPenalty?: number; + /** + * Output response mimetype of the generated candidate text. + * Supported mimetype: + * `text/plain`: (default) Text output. + * `application/json`: JSON response in the candidates. + * The model needs to be prompted to output the appropriate response type, + * otherwise the behavior is undefined. + * This is a preview feature. + */ + responseMimeType?: string; +} + +/** + * Params for {@link GenerativeModel.startChat}. + * @public + */ +export interface StartChatParams extends BaseParams { + history?: Content[]; + tools?: Tool[]; + toolConfig?: ToolConfig; + systemInstruction?: string | Part | Content; +} + +/** + * Params for calling {@link GenerativeModel.countTokens} + * @public + */ +export interface CountTokensRequest { + contents: Content[]; +} + +/** + * Params passed to {@link getGenerativeModel}. + * @public + */ +export interface RequestOptions { + /** + * Request timeout in milliseconds. + */ + timeout?: number; + /** + * Base url for endpoint. Defaults to https://firebaseml.googleapis.com + */ + baseUrl?: string; +} + +/** + * Defines a tool that model can call to access external knowledge. + * @public + */ +export declare type Tool = FunctionDeclarationsTool; + +/** + * Structured representation of a function declaration as defined by the + * {@link https://spec.openapis.org/oas/v3.0.3 | OpenAPI 3.0 specification}. + * Included + * in this declaration are the function name and parameters. This + * `FunctionDeclaration` is a representation of a block of code that can be used + * as a Tool by the model and executed by the client. + * @public + */ +export declare interface FunctionDeclaration { + /** + * The name of the function to call. Must start with a letter or an + * underscore. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with + * a max length of 64. + */ + name: string; + /** + * Optional. Description and purpose of the function. Model uses it to decide + * how and whether to call the function. + */ + description?: string; + /** + * Optional. Describes the parameters to this function in JSON Schema Object + * format. Reflects the Open API 3.03 Parameter Object. Parameter names are + * case sensitive. For a function with no parameters, this can be left unset. + */ + parameters?: FunctionDeclarationSchema; +} + +/** + * A `FunctionDeclarationsTool` is a piece of code that enables the system to + * interact with external systems to perform an action, or set of actions, + * outside of knowledge and scope of the model. + * @public + */ +export declare interface FunctionDeclarationsTool { + /** + * Optional. One or more function declarations + * to be passed to the model along with the current user query. Model may + * decide to call a subset of these functions by populating + * {@link FunctionCall} in the response. User should + * provide a {@link FunctionResponse} for each + * function call in the next turn. Based on the function responses, the model will + * generate the final response back to the user. Maximum 64 function + * declarations can be provided. + */ + functionDeclarations?: FunctionDeclaration[]; +} + +/** + * Contains the list of OpenAPI data types + * as defined by https://swagger.io/docs/specification/data-models/data-types/ + * @public + */ +export enum FunctionDeclarationSchemaType { + /** String type. */ + STRING = 'STRING', + /** Number type. */ + NUMBER = 'NUMBER', + /** Integer type. */ + INTEGER = 'INTEGER', + /** Boolean type. */ + BOOLEAN = 'BOOLEAN', + /** Array type. */ + ARRAY = 'ARRAY', + /** Object type. */ + OBJECT = 'OBJECT' +} + +/** + * Schema for parameters passed to {@link FunctionDeclaration.parameters}. + * @public + */ +export interface FunctionDeclarationSchema { + /** The type of the parameter. */ + type: FunctionDeclarationSchemaType; + /** The format of the parameter. */ + properties: { [k: string]: FunctionDeclarationSchemaProperty }; + /** Optional. Description of the parameter. */ + description?: string; + /** Optional. Array of required parameters. */ + required?: string[]; +} + +/** + * Schema is used to define the format of input/output data. + * Represents a select subset of an OpenAPI 3.0 schema object. + * More fields may be added in the future as needed. + * @public + */ +export interface FunctionDeclarationSchemaProperty { + /** + * Optional. The type of the property. {@link + * FunctionDeclarationSchemaType}. + */ + type?: FunctionDeclarationSchemaType; + /** Optional. The format of the property. */ + format?: string; + /** Optional. The description of the property. */ + description?: string; + /** Optional. Whether the property is nullable. */ + nullable?: boolean; + /** Optional. The items of the property. {@link FunctionDeclarationSchema} */ + items?: FunctionDeclarationSchema; + /** Optional. The enum of the property. */ + enum?: string[]; + /** Optional. Map of {@link FunctionDeclarationSchema}. */ + properties?: { [k: string]: FunctionDeclarationSchema }; + /** Optional. Array of required property. */ + required?: string[]; + /** Optional. The example of the property. */ + example?: unknown; +} + +/** + * Tool config. This config is shared for all tools provided in the request. + * @public + */ +export interface ToolConfig { + functionCallingConfig: FunctionCallingConfig; +} + +/** + * @public + */ +export interface FunctionCallingConfig { + mode?: FunctionCallingMode; + allowedFunctionNames?: string[]; +} diff --git a/packages/vertexai/src/types/responses.ts b/packages/vertexai/src/types/responses.ts new file mode 100644 index 00000000000..0a4557fb055 --- /dev/null +++ b/packages/vertexai/src/types/responses.ts @@ -0,0 +1,216 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Content, FunctionCall } from './content'; +import { + BlockReason, + FinishReason, + HarmCategory, + HarmProbability, + HarmSeverity +} from './enums'; + +/** + * Result object returned from {@link GenerativeModel.generateContent} call. + * + * @public + */ +export interface GenerateContentResult { + response: EnhancedGenerateContentResponse; +} + +/** + * Result object returned from {@link GenerativeModel.generateContentStream} call. + * Iterate over `stream` to get chunks as they come in and/or + * use the `response` promise to get the aggregated response when + * the stream is done. + * + * @public + */ +export interface GenerateContentStreamResult { + stream: AsyncGenerator; + response: Promise; +} + +/** + * Response object wrapped with helper methods. + * + * @public + */ +export interface EnhancedGenerateContentResponse + extends GenerateContentResponse { + /** + * Returns the text string from the response, if available. + * Throws if the prompt or candidate was blocked. + */ + text: () => string; + functionCalls: () => FunctionCall[] | undefined; +} + +/** + * Individual response from {@link GenerativeModel.generateContent} and + * {@link GenerativeModel.generateContentStream}. + * `generateContentStream()` will return one in each chunk until + * the stream is done. + * @public + */ +export interface GenerateContentResponse { + candidates?: GenerateContentCandidate[]; + promptFeedback?: PromptFeedback; + usageMetadata?: UsageMetadata; +} + +/** + * Usage metadata about a {@link GenerateContentResponse}. + * + * @public + */ +export interface UsageMetadata { + promptTokenCount: number; + candidatesTokenCount: number; + totalTokenCount: number; +} + +/** + * If the prompt was blocked, this will be populated with `blockReason` and + * the relevant `safetyRatings`. + * @public + */ +export interface PromptFeedback { + blockReason: BlockReason; + safetyRatings: SafetyRating[]; + blockReasonMessage?: string; +} + +/** + * A candidate returned as part of a {@link GenerateContentResponse}. + * @public + */ +export interface GenerateContentCandidate { + index: number; + content: Content; + finishReason?: FinishReason; + finishMessage?: string; + safetyRatings?: SafetyRating[]; + citationMetadata?: CitationMetadata; + groundingMetadata?: GroundingMetadata; +} + +/** + * Citation metadata that may be found on a {@link GenerateContentCandidate}. + * @public + */ +export interface CitationMetadata { + citations: Citation[]; +} + +/** + * A single citation. + * @public + */ +export interface Citation { + startIndex?: number; + endIndex?: number; + uri?: string; + license?: string; + title?: string; + publicationDate?: Date; +} + +/** + * Metadata returned to client when grounding is enabled. + * @public + */ +export interface GroundingMetadata { + webSearchQueries?: string[]; + retrievalQueries?: string[]; + groundingAttributions: GroundingAttribution[]; +} + +/** + * @public + */ +export interface GroundingAttribution { + segment: Segment; + confidenceScore?: number; + web?: WebAttribution; + retrievedContext?: RetrievedContextAttribution; +} + +/** + * @public + */ +export interface Segment { + partIndex: number; + startIndex: number; + endIndex: number; +} + +/** + * @public + */ +export interface WebAttribution { + uri: string; + title: string; +} + +/** + * @public + */ +export interface RetrievedContextAttribution { + uri: string; + title: string; +} + +/** + * Protobuf google.type.Date + * @public + */ +export interface Date { + year: number; + month: number; + day: number; +} + +/** + * A safety rating associated with a {@link GenerateContentCandidate} + * @public + */ +export interface SafetyRating { + category: HarmCategory; + probability: HarmProbability; + severity: HarmSeverity; + probabilityScore: number; + severityScore: number; + blocked: boolean; +} + +/** + * Response from calling {@link GenerativeModel.countTokens}. + * @public + */ +export interface CountTokensResponse { + /** + * The total number of tokens counted across all instances from the request. + */ + totalTokens: number; + /** + * The total number of billable characters counted across all instances + * from the request. + */ + totalBillableCharacters?: number; +} diff --git a/packages/vertexai/test-utils/base64cat.ts b/packages/vertexai/test-utils/base64cat.ts new file mode 100644 index 00000000000..45325a1bf55 --- /dev/null +++ b/packages/vertexai/test-utils/base64cat.ts @@ -0,0 +1,19 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const base64Cat = + 'iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAABJWlDQ1BrQ0dDb2xvclNwYWNlQWRvYmVSR0IxOTk4AAAokWNgYFJILCjIYRJgYMjNKykKcndSiIiMUmB/zsDNwAnE2gwGicnFBY4BAT4MQACjUcG3awyMIPqyLsgsTHm8gCsltTgZSP8B4uzkgqISBgbGDCBbubykAMTuAbJFkrLB7AUgdhHQgUD2FhA7HcI+AVYDYd8BqwkJcgayPwDZfElgNhPILr50CFsAxIbaCwKCjin5SakKIN9rGFpaWmiS6AeCoCS1ogREO+cXVBZlpmeUKDgCQypVwTMvWU9HwcjAyJiBARTuENWfA8HhySh2BiGGAAixORIMDP5LGRhY/iDETHoZGBboMDDwT0WIqRkyMAjoMzDsm5NcWlQGNYaRCWgnIT4AXxVKdgMmGHwAAAFQZVhJZk1NACoAAAAIAAkBDgACAAAARwAAAHoBEgADAAAAAQABAAABGgAFAAAAAQAAAMIBGwAFAAAAAQAAAMoBKAADAAAAAQACAAABMQACAAAACwAAANIBMgACAAAAFAAAAN6CmAACAAAAEwAAAPKHaQAEAAAAAQAAAQYAAAAAUGhvdG9ncmFwaCBmcm9tIFdhbHRlciBDaGFuZG9oYTogVGhlIENhdCBQaG90b2dyYXBoZXIgKEFwZXJ0dXJlLCAyMDE1KQAAAAABLAAAAAEAAAEsAAAAAVBob3RvU2NhcGUAADIwMTU6MDY6MTggMTE6MTM6NTMAwqkgV2FsdGVyIENoYW5kb2hhAAAABJAAAAcAAAAEMDIyMZAEAAIAAAAUAAABPKACAAQAAAABAAABAKADAAQAAAABAAABAAAAAAAyMDE1OjA0OjAxIDE1OjE3OjAzALUWG8IAAAAJcEhZcwAALiMAAC4jAXilP3YAADtdaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA2LjAuMCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczp4bXBSaWdodHM9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9yaWdodHMvIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgICAgICAgICB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIKICAgICAgICAgICAgeG1sbnM6eHdudj0iaHR0cDovL25zLnhpbmV0LmNvbS9ucy94aW5ldHNjaGVtYSMiCiAgICAgICAgICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyI+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvdGlmZjwvZGM6Zm9ybWF0PgogICAgICAgICA8ZGM6ZGVzY3JpcHRpb24+CiAgICAgICAgICAgIDxyZGY6QWx0PgogICAgICAgICAgICAgICA8cmRmOmxpIHhtbDpsYW5nPSJ4LWRlZmF1bHQiPlBob3RvZ3JhcGggZnJvbSBXYWx0ZXIgQ2hhbmRvaGE6IFRoZSBDYXQgUGhvdG9ncmFwaGVyIChBcGVydHVyZSwgMjAxNSk8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6QWx0PgogICAgICAgICA8L2RjOmRlc2NyaXB0aW9uPgogICAgICAgICA8ZGM6cmlnaHRzPgogICAgICAgICAgICA8cmRmOkFsdD4KICAgICAgICAgICAgICAgPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij7CqSBXYWx0ZXIgQ2hhbmRvaGE8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6QWx0PgogICAgICAgICA8L2RjOnJpZ2h0cz4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6Q29tcHJlc3Npb24+MTwvdGlmZjpDb21wcmVzc2lvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+MzAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4zMDA8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4zMDU3PC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6RXhpZlZlcnNpb24+MDIyMTwvZXhpZjpFeGlmVmVyc2lvbj4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT42NTUzNTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MjE3MzwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDx4bXBSaWdodHM6TWFya2VkPlRydWU8L3htcFJpZ2h0czpNYXJrZWQ+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGhvdG9TY2FwZTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOlJhdGluZz4xPC94bXA6UmF0aW5nPgogICAgICAgICA8eG1wOk1ldGFkYXRhRGF0ZT4yMDE1LTA2LTE4VDExOjEzOjUzLTA0OjAwPC94bXA6TWV0YWRhdGFEYXRlPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAxNS0wNC0wMVQxNToxNzowMy0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TGFiZWw+QXBwcm92ZWQ8L3htcDpMYWJlbD4KICAgICAgICAgPHhtcDpNb2RpZnlEYXRlPjIwMTUtMDYtMThUMTE6MTM6NTMtMDQ6MDA8L3htcDpNb2RpZnlEYXRlPgogICAgICAgICA8eG1wTU06SGlzdG9yeT4KICAgICAgICAgICAgPHJkZjpTZXE+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ1M1LjEgTWFjaW50b3NoPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA0LTAxVDE1OjE3OjAzLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOkQ2NDkzMDk2MzgyNzY4MTE4NzFGRDg0Mjk3MDE2Mjk3PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPmNyZWF0ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgKE1hY2ludG9zaCk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpjaGFuZ2VkPi88L3N0RXZ0OmNoYW5nZWQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTUtMDQtMDFUMTg6NTg6MDEtMDQ6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6YTI2NDlkMWMtM2YzNy00YzVlLWFmNGMtN2MxMDg1ZTc4Yjc5PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jb252ZXJ0ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnBhcmFtZXRlcnM+ZnJvbSBpbWFnZS90aWZmIHRvIGltYWdlL2Vwc2Y8L3N0RXZ0OnBhcmFtZXRlcnM+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5kZXJpdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpwYXJhbWV0ZXJzPmNvbnZlcnRlZCBmcm9tIGltYWdlL3RpZmYgdG8gaW1hZ2UvZXBzZjwvc3RFdnQ6cGFyYW1ldGVycz4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgKE1hY2ludG9zaCk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpjaGFuZ2VkPi88L3N0RXZ0OmNoYW5nZWQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTUtMDQtMDFUMTg6NTg6MDEtMDQ6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6OGEwOTVhMjMtNTBlMS00ZDA3LWI0YjctNGNhNDA4YzVlODcyPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA0LTAxVDE5OjQ0OjQ2LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjlkYzRhZDAyLTgwMzItNDMyZS05YjhlLTk1YThlMTQ1YzJkMDwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+Y29udmVydGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpwYXJhbWV0ZXJzPmZyb20gaW1hZ2UvZXBzZiB0byBpbWFnZS90aWZmPC9zdEV2dDpwYXJhbWV0ZXJzPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+ZGVyaXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6cGFyYW1ldGVycz5jb252ZXJ0ZWQgZnJvbSBpbWFnZS9lcHNmIHRvIGltYWdlL3RpZmY8L3N0RXZ0OnBhcmFtZXRlcnM+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA0LTAxVDE5OjQ0OjQ2LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjRkZTAwN2U3LTk5MWUtNDc5MS1hOTZkLTE5ZmVhMDllNWI4NTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAoTWFjaW50b3NoKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxNS0wNC0wMVQyMDo0Njo1Ni0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDowMjMyZmIxZC1jYjQ0LTQwOGYtYWE2MC04N2U3MDYyMGNhYmM8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+c2F2ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93czwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxNS0wNC0xOVQwMDoxODozMy0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDpCOUM3OENGNDQ2RTZFNDExOTRFQzkzQjJERjdGRjg2NTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+Y29udmVydGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpwYXJhbWV0ZXJzPmZyb20gaW1hZ2UvdGlmZiB0byBhcHBsaWNhdGlvbi92bmQuYWRvYmUucGhvdG9zaG9wPC9zdEV2dDpwYXJhbWV0ZXJzPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+ZGVyaXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6cGFyYW1ldGVycz5jb252ZXJ0ZWQgZnJvbSBpbWFnZS90aWZmIHRvIGFwcGxpY2F0aW9uL3ZuZC5hZG9iZS5waG90b3Nob3A8L3N0RXZ0OnBhcmFtZXRlcnM+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENTNS4xIFdpbmRvd3M8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpjaGFuZ2VkPi88L3N0RXZ0OmNoYW5nZWQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTUtMDQtMTlUMDA6MTg6MzMtMDQ6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6QkFDNzhDRjQ0NkU2RTQxMTk0RUM5M0IyREY3RkY4NjU8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+c2F2ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93czwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxNS0wNC0xOVQxMjo0Mjo1OC0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDowNUZDQzI0NUIxRTZFNDExQjVCMEU3QTI0NTYyMUZGNjwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDUzUuMSBXaW5kb3dzPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA0LTE5VDEyOjQzOjMwLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjA4RkNDMjQ1QjFFNkU0MTFCNUIwRTdBMjQ1NjIxRkY2PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jb252ZXJ0ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnBhcmFtZXRlcnM+ZnJvbSBhcHBsaWNhdGlvbi92bmQuYWRvYmUucGhvdG9zaG9wIHRvIGltYWdlL3RpZmY8L3N0RXZ0OnBhcmFtZXRlcnM+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5kZXJpdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpwYXJhbWV0ZXJzPmNvbnZlcnRlZCBmcm9tIGFwcGxpY2F0aW9uL3ZuZC5hZG9iZS5waG90b3Nob3AgdG8gaW1hZ2UvdGlmZjwvc3RFdnQ6cGFyYW1ldGVycz4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93czwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxNS0wNC0xOVQxMjo0MzozMC0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDowOUZDQzI0NUIxRTZFNDExQjVCMEU3QTI0NTYyMUZGNjwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE0IChNYWNpbnRvc2gpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA0LTIxVDEwOjQ4OjM1LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOmUzODZlNjQ4LWZmNjYtNDA5NC04NWEyLWY2NjgxZTRiM2I4Mjwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIEJyaWRnZSBDQyAoTWFjaW50b3NoKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+L21ldGFkYXRhPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA0LTIzVDIxOjEwOjQ2LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOmIwZmJjMzZkLThhMjgtNDU4NC05NTlkLTk5NjFmZDEyMDA5Mjwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE0IChNYWNpbnRvc2gpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA0LTIzVDIyOjIyOjIzLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOmM1MzNhNjRlLTk0OTktNDMzOS05MjM4LThhOGY0Nzc3NzQ3YTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE0IChNYWNpbnRvc2gpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA0LTIzVDIyOjIzOjQyLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOmRiMjlmZTVlLWQ2ZDAtNDBjZi04Y2RkLTBkYTU2NDgwMTU2YTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDYW1lcmEgUmF3IDguODwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+L21ldGFkYXRhPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA0LTIzVDIyOjMyOjMwLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOmRkMzFmNTVlLTUyMzctNDA5ZC1hMTk2LTdhM2Q1ZTIwMTM0Mjwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDYW1lcmEgUmF3IDguOCAoTWFjaW50b3NoKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+L21ldGFkYXRhPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA0LTIzVDIyOjMzOjM3LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOmUzNjExZWQ3LTI4YmYtNGE5MS1hZDA5LWVhNjc3M2U4Y2YyOTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAoTWFjaW50b3NoKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxNS0wNC0yOFQxMDowMTo1MS0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDo1MDViZDMzYS03ZDJiLTRiNzQtOTU1My0xNjIzYjE4MzExMmM8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+c2F2ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ1M2IChXaW5kb3dzKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxNS0wNi0xOFQxMDowMjo1OS0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDpFMzBDRTVCOUMyMTVFNTExQkVDQkU3RTMxNDVCODA4NTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDYW1lcmEgUmF3IDguMjwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+L21ldGFkYXRhPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA2LTE4VDEwOjA0OjQ1LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOkE4MUY0NUYxQzIxNUU1MTE4OTE4RkI0OTg3NjBDNzI5PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENhbWVyYSBSYXcgOC4yIChXaW5kb3dzKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+L21ldGFkYXRhPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA2LTE4VDEwOjA1OjU1LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjMzNTk0ZDkyLWNlMmYtNGE0Ny1iNTFmLTRmOTUzNjVmNWJkNTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDUzYgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE1LTA2LTE4VDExOjEyLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjA3QUE3MDVFQ0MxNUU1MTE5NjEwQjRCN0U1NjM5OEUwPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpjaGFuZ2VkPi88L3N0RXZ0OmNoYW5nZWQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTUtMDYtMThUMTE6MTM6NTMtMDQ6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6MTFBQTcwNUVDQzE1RTUxMTk2MTBCNEI3RTU2Mzk4RTA8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+c2F2ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC94bXBNTTpIaXN0b3J5PgogICAgICAgICA8eG1wTU06T3JpZ2luYWxEb2N1bWVudElEPnhtcC5kaWQ6RDY0OTMwOTYzODI3NjgxMTg3MUZEODQyOTcwMTYyOTc8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkRlcml2ZWRGcm9tIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgPHN0UmVmOm9yaWdpbmFsRG9jdW1lbnRJRD54bXAuZGlkOkQ2NDkzMDk2MzgyNzY4MTE4NzFGRDg0Mjk3MDE2Mjk3PC9zdFJlZjpvcmlnaW5hbERvY3VtZW50SUQ+CiAgICAgICAgICAgIDxzdFJlZjppbnN0YW5jZUlEPnhtcC5paWQ6MDhGQ0MyNDVCMUU2RTQxMUI1QjBFN0EyNDU2MjFGRjY8L3N0UmVmOmluc3RhbmNlSUQ+CiAgICAgICAgICAgIDxzdFJlZjpkb2N1bWVudElEPnhtcC5kaWQ6RDY0OTMwOTYzODI3NjgxMTg3MUZEODQyOTcwMTYyOTc8L3N0UmVmOmRvY3VtZW50SUQ+CiAgICAgICAgIDwveG1wTU06RGVyaXZlZEZyb20+CiAgICAgICAg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'; diff --git a/packages/vertexai/test-utils/cat.jpeg b/packages/vertexai/test-utils/cat.jpeg new file mode 100644 index 00000000000..2c21763bad2 Binary files /dev/null and b/packages/vertexai/test-utils/cat.jpeg differ diff --git a/packages/vertexai/test-utils/cat.png b/packages/vertexai/test-utils/cat.png new file mode 100644 index 00000000000..edcddfacc92 Binary files /dev/null and b/packages/vertexai/test-utils/cat.png differ diff --git a/packages/vertexai/test-utils/convert-mocks.ts b/packages/vertexai/test-utils/convert-mocks.ts new file mode 100644 index 00000000000..0731df9da36 --- /dev/null +++ b/packages/vertexai/test-utils/convert-mocks.ts @@ -0,0 +1,53 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Converts mock text files into a js file that karma can read without + * using fs. + */ + +// eslint-disable-next-line @typescript-eslint/no-require-imports +const fs = require('fs'); +// eslint-disable-next-line @typescript-eslint/no-require-imports +const { join } = require('path'); + +const mockResponseDir = join(__dirname, 'mock-responses'); + +async function main(): Promise { + const list = fs.readdirSync(mockResponseDir); + const lookup: Record = {}; + // eslint-disable-next-line guard-for-in + for (const fileName of list) { + const fullText = fs.readFileSync(join(mockResponseDir, fileName), 'utf-8'); + lookup[fileName] = fullText; + } + let fileText = `// Generated from mocks text files.`; + + fileText += '\n\n'; + fileText += `export const mocksLookup: Record = ${JSON.stringify( + lookup, + null, + 2 + )}`; + fileText += ';\n'; + fs.writeFileSync(join(__dirname, 'mocks-lookup.ts'), fileText, 'utf-8'); +} + +main().catch(e => { + console.error(e); + process.exit(1); +}); diff --git a/packages/vertexai/test-utils/mock-response.ts b/packages/vertexai/test-utils/mock-response.ts new file mode 100644 index 00000000000..8332d9eb36e --- /dev/null +++ b/packages/vertexai/test-utils/mock-response.ts @@ -0,0 +1,65 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { mocksLookup } from './mocks-lookup'; + +/** + * Mock native Response.body + * Streams contents of json file in 20 character chunks + */ +export function getChunkedStream( + input: string, + chunkLength = 20 +): ReadableStream { + const encoder = new TextEncoder(); + let currentChunkStart = 0; + + const stream = new ReadableStream({ + start(controller) { + while (currentChunkStart < input.length) { + const substring = input.slice( + currentChunkStart, + currentChunkStart + chunkLength + ); + currentChunkStart += chunkLength; + const chunk = encoder.encode(substring); + controller.enqueue(chunk); + } + controller.close(); + } + }); + + return stream; +} +export function getMockResponseStreaming( + filename: string, + chunkLength: number = 20 +): Partial { + const fullText = mocksLookup[filename]; + + return { + body: getChunkedStream(fullText, chunkLength) + }; +} + +export function getMockResponse(filename: string): Partial { + const fullText = mocksLookup[filename]; + return { + ok: true, + json: () => Promise.resolve(JSON.parse(fullText)) + }; +} diff --git a/packages/vertexai/test-utils/mock-responses/streaming-failure-empty-content.txt b/packages/vertexai/test-utils/mock-responses/streaming-failure-empty-content.txt new file mode 100644 index 00000000000..112a84ada1f --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/streaming-failure-empty-content.txt @@ -0,0 +1,2 @@ +data: {"candidates": [{"content": {},"index": 0}],"promptFeedback": {"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}} + diff --git a/packages/vertexai/test-utils/mock-responses/streaming-failure-finish-reason-safety.txt b/packages/vertexai/test-utils/mock-responses/streaming-failure-finish-reason-safety.txt new file mode 100644 index 00000000000..b73c75cf505 --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/streaming-failure-finish-reason-safety.txt @@ -0,0 +1,2 @@ +data: {"candidates": [{"content": {"parts": [{"text": "No"}]},"finishReason": "SAFETY","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "HIGH"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}],"promptFeedback": {"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}} + diff --git a/packages/vertexai/test-utils/mock-responses/streaming-failure-prompt-blocked-safety.txt b/packages/vertexai/test-utils/mock-responses/streaming-failure-prompt-blocked-safety.txt new file mode 100644 index 00000000000..58c914af08e --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/streaming-failure-prompt-blocked-safety.txt @@ -0,0 +1,2 @@ +data: {"promptFeedback": {"blockReason": "SAFETY","safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "HIGH"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}} + diff --git a/packages/vertexai/test-utils/mock-responses/streaming-failure-recitation-no-content.txt b/packages/vertexai/test-utils/mock-responses/streaming-failure-recitation-no-content.txt new file mode 100644 index 00000000000..05a296d60f0 --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/streaming-failure-recitation-no-content.txt @@ -0,0 +1,6 @@ +data: {"candidates": [{"content": {"parts": [{"text": "Copyrighted text goes here"}],"role": "model"},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}],"promptFeedback": {"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}} + +data: {"candidates": [{"content": {"parts": [{"text": "More copyrighted text"}],"role": "model"},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "LOW"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}],"citationMetadata": {"citations": [{"startIndex": 30,"endIndex": 179,"uri": "https://www.example.com","license": ""}]}}]} + +data: {"candidates": [{"finishReason": "RECITATION","index": 0}]} + diff --git a/packages/vertexai/test-utils/mock-responses/streaming-success-basic-reply-long.txt b/packages/vertexai/test-utils/mock-responses/streaming-success-basic-reply-long.txt new file mode 100644 index 00000000000..fe662e6ffff --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/streaming-success-basic-reply-long.txt @@ -0,0 +1,12 @@ +data: {"candidates": [{"content": {"parts": [{"text": "**Cats:**\n\n- **Physical Characteristics:**\n - Size: Cats come"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}],"promptFeedback": {"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}} + +data: {"candidates": [{"content": {"parts": [{"text": " in a wide range of sizes, from small breeds like the Singapura to large breeds like the Maine Coon.\n - Fur: Cats have soft, furry coats"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} + +data: {"candidates": [{"content": {"parts": [{"text": " that can vary in length and texture depending on the breed.\n - Eyes: Cats have large, expressive eyes that can be various colors, including green, blue, yellow, and hazel.\n - Ears: Cats have pointed, erect ears that are sensitive to sound.\n - Tail: Cats have long"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} + +data: {"candidates": [{"content": {"parts": [{"text": ", flexible tails that they use for balance and communication.\n\n- **Behavior and Personality:**\n - Independent: Cats are often described as independent animals that enjoy spending time alone.\n - Affectionate: Despite their independent nature, cats can be very affectionate and form strong bonds with their owners.\n - Playful: Cats are naturally playful and enjoy engaging in activities such as chasing toys, climbing, and pouncing.\n - Curious: Cats are curious creatures that love to explore their surroundings.\n - Vocal: Cats communicate through a variety of vocalizations, including meows, purrs, hisses, and grow"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} + +data: {"candidates": [{"content": {"parts": [{"text": "ls.\n\n- **Health and Care:**\n - Diet: Cats are obligate carnivores, meaning they require animal-based protein for optimal health.\n - Grooming: Cats spend a significant amount of time grooming themselves to keep their fur clean and free of mats.\n - Exercise: Cats need regular exercise to stay healthy and active. This can be achieved through play sessions or access to outdoor space.\n - Veterinary Care: Regular veterinary checkups are essential for maintaining a cat's health and detecting any potential health issues early on.\n\n**Dogs:**\n\n- **Physical Characteristics:**\n - Size: Dogs come in a wide range of sizes, from small breeds like the Chihuahua to giant breeds like the Great Dane.\n - Fur: Dogs have fur coats that can vary in length, texture, and color depending on the breed.\n - Eyes: Dogs have expressive eyes that can be various colors, including brown, blue, green, and hazel.\n - Ears: Dogs have floppy or erect ears that are sensitive to sound.\n - Tail: Dogs have long, wagging tails that they use for communication and expressing emotions.\n\n- **Behavior and Personality:**\n - Loyal: Dogs are known for their loyalty and"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} + +data: {"candidates": [{"content": {"parts": [{"text": " devotion to their owners.\n - Friendly: Dogs are generally friendly and outgoing animals that enjoy interacting with people and other animals.\n - Playful: Dogs are playful and energetic creatures that love to engage in activities such as fetching, running, and playing with toys.\n - Trainable: Dogs are highly trainable and can learn a variety of commands and tricks.\n - Vocal: Dogs communicate through a variety of vocalizations, including barking, howling, whining, and growling.\n\n- **Health and Care:**\n - Diet: Dogs are omnivores and can eat a variety of foods, including meat, vegetables, and grains.\n - Grooming: Dogs require regular grooming to keep their fur clean and free of mats. The frequency of grooming depends on the breed and coat type.\n - Exercise: Dogs need regular exercise to stay healthy and active. The amount of exercise required varies depending on the breed and age of the dog.\n - Veterinary Care: Regular veterinary checkups are essential for maintaining a dog's health and detecting any potential health issues early on."}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} + diff --git a/packages/vertexai/test-utils/mock-responses/streaming-success-basic-reply-short.txt b/packages/vertexai/test-utils/mock-responses/streaming-success-basic-reply-short.txt new file mode 100644 index 00000000000..a7f5476954e --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/streaming-success-basic-reply-short.txt @@ -0,0 +1,2 @@ +data: {"candidates": [{"content": {"parts": [{"text": "Cheyenne"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}],"promptFeedback": {"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}} + diff --git a/packages/vertexai/test-utils/mock-responses/streaming-success-citations.txt b/packages/vertexai/test-utils/mock-responses/streaming-success-citations.txt new file mode 100644 index 00000000000..56c8bae95e9 --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/streaming-success-citations.txt @@ -0,0 +1,12 @@ +data: {"candidates": [{"content": {"parts": [{"text": "1. **Definition:**\nQuantum mechanics is a fundamental theory in physics that provides"}],"role": "model"},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}],"promptFeedback": {"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}} + +data: {"candidates": [{"content": {"parts": [{"text": " the foundation for understanding the physical properties of nature at the scale of atoms and subatomic particles. It is based on the idea that energy, momentum, angular momentum"}],"role": "model"},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} + +data: {"candidates": [{"content": {"parts": [{"text": ", and other quantities are quantized, meaning they can exist only in discrete values. \n\n2. **Key Concepts:**\n - **Wave-particle Duality:** Particles such as electrons and photons can exhibit both wave-like and particle-like behaviors. \n - **Uncertainty Principle:** Proposed by Werner"}],"role": "model"},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} + +data: {"candidates": [{"content": {"parts": [{"text": " Heisenberg, it states that the more precisely the position of a particle is known, the less precisely its momentum can be known, and vice versa. \n - **Superposition:** A quantum system can exist in multiple states simultaneously until it is observed or measured, at which point it \"collapses\" into a single state.\n - **Quantum Entanglement:** Two or more particles can become correlated in such a way that the state of one particle cannot be described independently of the other, even when they are separated by large distances. \n\n3. **Applications:**\n - **Quantum Computing:** It explores the use of quantum"}],"role": "model"},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}],"citationMetadata": {"citations": [{"startIndex": 574,"endIndex": 705,"uri": "https://www.example.com","license": ""},{"startIndex": 899,"endIndex": 1026,"uri": "https://www.example.com","license": ""}]}}]} + +data: {"candidates": [{"content": {"parts": [{"text": "-mechanical phenomena to perform complex calculations and solve problems that are intractable for classical computers. \n - **Quantum Cryptography:** Utilizes the principles of quantum mechanics to develop secure communication channels. \n - **Quantum Imaging:** Employs quantum effects to enhance the resolution and sensitivity of imaging techniques in fields such as microscopy and medical imaging. \n - **Quantum Sensors:** Leverages quantum properties to develop highly sensitive sensors for detecting magnetic fields, accelerations, and other physical quantities. \n\n4. **Learning Resources:**\n - **Books:**\n - \"Quantum Mechanics for Mathematicians\" by James Glimm and Arthur Jaffe\n - \"Principles of Quantum Mechanics\" by R. Shankar\n - \"Quantum Mechanics: Concepts and Applications\" by Nouredine Zettili\n - **Online Courses:**\n - \"Quantum Mechanics I\" by MIT OpenCourseWare\n - \"Quantum Mechanics for Everyone\" by Coursera\n - \"Quantum Mechanics\" by Stanford Online\n - **Documentaries and Videos:**\n - \"Quantum Mechanics: The Strangest Theory\" (BBC Documentary)\n - \"Quantum Mechanics Explained Simply\" by Veritasium (YouTube Channel)\n - \"What is Quantum Mechanics?\" by Minute"}],"role": "model"},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}],"citationMetadata": {"citations": [{"startIndex": 574,"endIndex": 705,"uri": "https://www.example.com","license": ""},{"startIndex": 899,"endIndex": 1026,"uri": "https://www.example.com","license": ""}]}}]} + +data: {"candidates": [{"content": {"parts": [{"text": "Physics (YouTube Channel)"}],"role": "model"},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}],"citationMetadata": {"citations": [{"startIndex": 574,"endIndex": 705,"uri": "https://www.example.com","license": ""},{"startIndex": 899,"endIndex": 1026,"uri": "https://www.example.com","license": ""}]}}]} + diff --git a/packages/vertexai/test-utils/mock-responses/streaming-success-function-call-short.txt b/packages/vertexai/test-utils/mock-responses/streaming-success-function-call-short.txt new file mode 100644 index 00000000000..ad6cb050da5 --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/streaming-success-function-call-short.txt @@ -0,0 +1,2 @@ +data: {"candidates": [{"content": {"parts": [{ "functionCall": { "name": "getTemperature", "args": { "city": "San Jose" } } }]}, "finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}],"promptFeedback": {"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}} + diff --git a/packages/vertexai/test-utils/mock-responses/streaming-success-utf8.txt b/packages/vertexai/test-utils/mock-responses/streaming-success-utf8.txt new file mode 100644 index 00000000000..a7531ab2580 --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/streaming-success-utf8.txt @@ -0,0 +1,8 @@ +data: { "candidates": [ { "content": { "parts": [ { "text": "秋风瑟瑟,叶落纷纷,\n西风残照,寒" } ], "role": "model" }, "finishReason": "STOP", "index": 0, "safetyRatings": [ { "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_HATE_SPEECH", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_HARASSMENT", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_DANGEROUS_CONTENT", "probability": "NEGLIGIBLE" } ] } ], "promptFeedback": { "safetyRatings": [ { "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_HATE_SPEECH", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_HARASSMENT", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_DANGEROUS_CONTENT", "probability": "NEGLIGIBLE" } ] } } + +data: { "candidates": [ { "content": { "parts": [ { "text": "霜渐浓。\n枫叶红了,菊花黄了,\n秋雨绵绵,秋意浓浓。\n\n秋夜漫漫,思" } ], "role": "model" }, "finishReason": "STOP", "index": 0, "safetyRatings": [ { "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_HATE_SPEECH", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_HARASSMENT", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_DANGEROUS_CONTENT", "probability": "NEGLIGIBLE" } ] } ] } + +data: { "candidates": [ { "content": { "parts": [ { "text": "绪万千,\n明月当空,星星眨眼。\n思念远方的亲人,\n祝愿他们幸福安康。\n\n秋天是收获的季节,\n人们忙着收割庄稼,\n为一年的辛劳画上圆满的句号。\n秋天也是团圆的季节" } ], "role": "model" }, "finishReason": "STOP", "index": 0, "safetyRatings": [ { "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_HATE_SPEECH", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_HARASSMENT", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_DANGEROUS_CONTENT", "probability": "NEGLIGIBLE" } ] } ] } + +data: { "candidates": [ { "content": { "parts": [ { "text": ",\n一家人围坐在一起,\n分享丰收的喜悦,共度美好时光。\n\n秋天是一个美丽的季节,\n它有着独特的韵味,\n让人沉醉其中,流连忘返。\n让我们一起欣赏秋天的美景,\n感受秋天的气息,领悟秋天的哲理。" } ], "role": "model" }, "finishReason": "STOP", "index": 0, "safetyRatings": [ { "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_HATE_SPEECH", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_HARASSMENT", "probability": "NEGLIGIBLE" }, { "category": "HARM_CATEGORY_DANGEROUS_CONTENT", "probability": "NEGLIGIBLE" } ] } ] } + diff --git a/packages/vertexai/test-utils/mock-responses/streaming-unknown-enum.txt b/packages/vertexai/test-utils/mock-responses/streaming-unknown-enum.txt new file mode 100644 index 00000000000..70210e56739 --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/streaming-unknown-enum.txt @@ -0,0 +1,12 @@ +data: {"candidates": [{"content": {"parts": [{"text": "**Cats:**\n\n- **Physical Characteristics:**\n - Size: Cats come"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}],"promptFeedback": {"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}} + +data: {"candidates": [{"content": {"parts": [{"text": " in a wide range of sizes, from small breeds like the Singapura to large breeds like the Maine Coon.\n - Fur: Cats have soft, furry coats"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} + +data: {"candidates": [{"content": {"parts": [{"text": " that can vary in length and texture depending on the breed.\n - Eyes: Cats have large, expressive eyes that can be various colors, including green, blue, yellow, and hazel.\n - Ears: Cats have pointed, erect ears that are sensitive to sound.\n - Tail: Cats have long"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} + +data: {"candidates": [{"content": {"parts": [{"text": ", flexible tails that they use for balance and communication.\n\n- **Behavior and Personality:**\n - Independent: Cats are often described as independent animals that enjoy spending time alone.\n - Affectionate: Despite their independent nature, cats can be very affectionate and form strong bonds with their owners.\n - Playful: Cats are naturally playful and enjoy engaging in activities such as chasing toys, climbing, and pouncing.\n - Curious: Cats are curious creatures that love to explore their surroundings.\n - Vocal: Cats communicate through a variety of vocalizations, including meows, purrs, hisses, and grow"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} + +data: {"candidates": [{"content": {"parts": [{"text": "ls.\n\n- **Health and Care:**\n - Diet: Cats are obligate carnivores, meaning they require animal-based protein for optimal health.\n - Grooming: Cats spend a significant amount of time grooming themselves to keep their fur clean and free of mats.\n - Exercise: Cats need regular exercise to stay healthy and active. This can be achieved through play sessions or access to outdoor space.\n - Veterinary Care: Regular veterinary checkups are essential for maintaining a cat's health and detecting any potential health issues early on.\n\n**Dogs:**\n\n- **Physical Characteristics:**\n - Size: Dogs come in a wide range of sizes, from small breeds like the Chihuahua to giant breeds like the Great Dane.\n - Fur: Dogs have fur coats that can vary in length, texture, and color depending on the breed.\n - Eyes: Dogs have expressive eyes that can be various colors, including brown, blue, green, and hazel.\n - Ears: Dogs have floppy or erect ears that are sensitive to sound.\n - Tail: Dogs have long, wagging tails that they use for communication and expressing emotions.\n\n- **Behavior and Personality:**\n - Loyal: Dogs are known for their loyalty and"}]},"finishReason": "STOP","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT","probability": "NEGLIGIBLE"}]}]} + +data: {"candidates": [{"content": {"parts": [{"text": " devotion to their owners.\n - Friendly: Dogs are generally friendly and outgoing animals that enjoy interacting with people and other animals.\n - Playful: Dogs are playful and energetic creatures that love to engage in activities such as fetching, running, and playing with toys.\n - Trainable: Dogs are highly trainable and can learn a variety of commands and tricks.\n - Vocal: Dogs communicate through a variety of vocalizations, including barking, howling, whining, and growling.\n\n- **Health and Care:**\n - Diet: Dogs are omnivores and can eat a variety of foods, including meat, vegetables, and grains.\n - Grooming: Dogs require regular grooming to keep their fur clean and free of mats. The frequency of grooming depends on the breed and coat type.\n - Exercise: Dogs need regular exercise to stay healthy and active. The amount of exercise required varies depending on the breed and age of the dog.\n - Veterinary Care: Regular veterinary checkups are essential for maintaining a dog's health and detecting any potential health issues early on."}]},"finishReason": "FAKE_ENUM","index": 0,"safetyRatings": [{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HATE_SPEECH","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_HARASSMENT","probability": "NEGLIGIBLE"},{"category": "HARM_CATEGORY_DANGEROUS_CONTENT_NEW_ENUM","probability": "NEGLIGIBLE_UNKNOWN_ENUM"}]}]} + diff --git a/packages/vertexai/test-utils/mock-responses/unary-failure-empty-content.json b/packages/vertexai/test-utils/mock-responses/unary-failure-empty-content.json new file mode 100644 index 00000000000..4e1889660f2 --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/unary-failure-empty-content.json @@ -0,0 +1,28 @@ +{ + "candidates": [ + { + "content": {}, + "index": 0 + } + ], + "promptFeedback": { + "safetyRatings": [ + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HARASSMENT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "probability": "NEGLIGIBLE" + } + ] + } +} diff --git a/packages/vertexai/test-utils/mock-responses/unary-failure-finish-reason-safety.json b/packages/vertexai/test-utils/mock-responses/unary-failure-finish-reason-safety.json new file mode 100644 index 00000000000..6e1e20f734b --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/unary-failure-finish-reason-safety.json @@ -0,0 +1,53 @@ +{ + "candidates": [ + { + "content": { + "parts": [ + { + "text": "No" + } + ] + }, + "finishReason": "SAFETY", + "index": 0, + "safetyRatings": [ + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "probability": "HIGH" + }, + { + "category": "HARM_CATEGORY_HARASSMENT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "probability": "NEGLIGIBLE" + } + ] + } + ], + "promptFeedback": { + "safetyRatings": [ + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HARASSMENT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "probability": "NEGLIGIBLE" + } + ] + } +} diff --git a/packages/vertexai/test-utils/mock-responses/unary-failure-image-rejected.json b/packages/vertexai/test-utils/mock-responses/unary-failure-image-rejected.json new file mode 100644 index 00000000000..9dacdc71e7a --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/unary-failure-image-rejected.json @@ -0,0 +1,13 @@ +{ + "error": { + "code": 400, + "message": "Request contains an invalid argument.", + "status": "INVALID_ARGUMENT", + "details": [ + { + "@type": "type.googleapis.com/google.rpc.DebugInfo", + "detail": "[ORIGINAL ERROR] generic::invalid_argument: invalid status photos.thumbnailer.Status.Code::5: Source image 0 too short" + } + ] + } +} diff --git a/packages/vertexai/test-utils/mock-responses/unary-failure-prompt-blocked-safety.json b/packages/vertexai/test-utils/mock-responses/unary-failure-prompt-blocked-safety.json new file mode 100644 index 00000000000..9d2abbb23d6 --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/unary-failure-prompt-blocked-safety.json @@ -0,0 +1,23 @@ +{ + "promptFeedback": { + "blockReason": "SAFETY", + "safetyRatings": [ + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "probability": "HIGH" + }, + { + "category": "HARM_CATEGORY_HARASSMENT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "probability": "NEGLIGIBLE" + } + ] + } +} diff --git a/packages/vertexai/test-utils/mock-responses/unary-success-basic-reply-long.json b/packages/vertexai/test-utils/mock-responses/unary-success-basic-reply-long.json new file mode 100644 index 00000000000..46e45165d74 --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/unary-success-basic-reply-long.json @@ -0,0 +1,52 @@ +{ + "candidates": [ + { + "content": { + "parts": [ + { + "text": "1. **Use Freshly Ground Coffee**:\n - Grind your coffee beans just before brewing to preserve their flavor and aroma.\n - Use a burr grinder for a consistent grind size.\n\n\n2. **Choose the Right Water**:\n - Use filtered or spring water for the best taste.\n - Avoid using tap water, as it may contain impurities that can affect the flavor.\n\n\n3. **Measure Accurately**:\n - Use a kitchen scale to measure your coffee and water precisely.\n - A general rule of thumb is to use 1:16 ratio of coffee to water (e.g., 15 grams of coffee to 240 grams of water).\n\n\n4. **Preheat Your Equipment**:\n - Preheat your coffee maker or espresso machine before brewing to ensure a consistent temperature.\n\n\n5. **Control the Water Temperature**:\n - The ideal water temperature for brewing coffee is between 195°F (90°C) and 205°F (96°C).\n - Too hot water can extract bitter flavors, while too cold water won't extract enough flavor.\n\n\n6. **Steep the Coffee**:\n - For drip coffee, let the water slowly drip through the coffee grounds for optimal extraction.\n - For pour-over coffee, pour the water in a circular motion over the coffee grounds, allowing it to steep for 30-45 seconds before continuing.\n\n\n7. **Clean Your Equipment**:\n - Regularly clean your coffee maker or espresso machine to prevent the buildup of oils and residue that can affect the taste of your coffee.\n\n\n8. **Experiment with Different Coffee Beans**:\n - Try different coffee beans from various regions and roasts to find your preferred flavor profile.\n - Experiment with different grind sizes and brewing methods to optimize the flavor of your chosen beans.\n\n\n9. **Store Coffee Properly**:\n - Store your coffee beans in an airtight container in a cool, dark place to preserve their freshness and flavor.\n - Avoid storing coffee in the refrigerator or freezer, as this can cause condensation and affect the taste.\n\n\n10. **Enjoy Freshly Brewed Coffee**:\n - Drink your coffee as soon as possible after brewing to enjoy its peak flavor and aroma.\n - Coffee starts to lose its flavor and aroma within 30 minutes of brewing." + } + ] + }, + "index": 0, + "safetyRatings": [ + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HARASSMENT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "probability": "NEGLIGIBLE" + } + ] + } + ], + "promptFeedback": { + "safetyRatings": [ + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HARASSMENT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "probability": "NEGLIGIBLE" + } + ] + } +} diff --git a/packages/vertexai/test-utils/mock-responses/unary-success-basic-reply-short.json b/packages/vertexai/test-utils/mock-responses/unary-success-basic-reply-short.json new file mode 100644 index 00000000000..345ec582f7d --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/unary-success-basic-reply-short.json @@ -0,0 +1,52 @@ +{ + "candidates": [ + { + "content": { + "parts": [ + { + "text": "Helena" + } + ] + }, + "index": 0, + "safetyRatings": [ + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HARASSMENT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "probability": "NEGLIGIBLE" + } + ] + } + ], + "promptFeedback": { + "safetyRatings": [ + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HARASSMENT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "probability": "NEGLIGIBLE" + } + ] + } +} diff --git a/packages/vertexai/test-utils/mock-responses/unary-success-citations.json b/packages/vertexai/test-utils/mock-responses/unary-success-citations.json new file mode 100644 index 00000000000..9d1a7939ed2 --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/unary-success-citations.json @@ -0,0 +1,64 @@ +{ + "candidates": [ + { + "content": { + "parts": [ + { + "text": "1. **Definition:**\nQuantum mechanics is a fundamental theory in physics that provides the foundation for understanding the physical properties of nature at the scale of atoms and subatomic particles. It is based on the idea that energy, momentum, angular momentum, and other quantities are quantized, meaning they can only exist in discrete values. \n\n2. **Key Concepts:**\n - **Wave-particle Duality:** Particles such as electrons and photons can exhibit both wave-like and particle-like behaviors. \n - **Uncertainty Principle:** Proposed by Werner Heisenberg, it states that the more precisely the position of a particle is known, the less precisely its momentum can be known, and vice versa. \n - **Quantum Superposition:** A quantum system can exist in multiple states simultaneously until it is measured. \n - **Quantum Entanglement:** Two or more particles can become linked in such a way that the state of one affects the state of the others, regardless of the distance between them. \n\n3. **Implications and Applications:**\n - **Atomic and Molecular Structure:** Quantum mechanics explains the structure of atoms, molecules, and chemical bonds. \n - **Quantum Computing:** It enables the development of quantum computers that can solve certain computational problems much faster than classical computers. \n - **Quantum Cryptography:** Quantum principles are used to develop secure communication methods. \n - **Quantum Field Theory (QFT):** A relativistic theory that describes interactions between particles in quantum mechanics. It underpins the Standard Model of Physics. \n - **Quantum Gravity:** Attempts to reconcile quantum mechanics with general relativity to explain the behavior of matter and gravity at very small scales. \n\n4. **Learning Resources:**\n - **Books:**\n - \"Quantum Mechanics for Mathematicians\" by James Glimm and Arthur Jaffe \n - \"Principles of Quantum Mechanics\" by R. Shankar\n - \"Quantum Mechanics: Concepts and Applications\" by Nouredine Zettili \n - **Online Courses and Tutorials:**\n - [Quantum Mechanics I](https://www.example.com) on Coursera\n - [MIT OpenCourseWare](https://www.example.com) Quantum Physics I course materials \n - [Khan Academy](https://www.example.com) Quantum Physics video tutorials \n - **Videos and Documentaries:**\n - [Quantum Mechanics - Crash Course Physics](https://www.example.com)\n - [Quantum Mechanics: The Strangest Theory](https://www.example.com)\n - [BBC: The Quantum World with Jim Al-Khalili](https://www.example.com)\n - [NOVA: The Fabric of the Cosmos](https://www.example.com)" + } + ], + "role": "model" + }, + "finishReason": "STOP", + "index": 0, + "safetyRatings": [ + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HARASSMENT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "probability": "NEGLIGIBLE" + } + ], + "citationMetadata": { + "citations": [ + { + "startIndex": 574, + "endIndex": 705, + "uri": "https://www.example.com", + "license": "" + } + ] + } + } + ], + "promptFeedback": { + "safetyRatings": [ + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HARASSMENT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "probability": "NEGLIGIBLE" + } + ] + } +} diff --git a/packages/vertexai/test-utils/mock-responses/unary-unknown-enum.json b/packages/vertexai/test-utils/mock-responses/unary-unknown-enum.json new file mode 100644 index 00000000000..92ced8ce3b8 --- /dev/null +++ b/packages/vertexai/test-utils/mock-responses/unary-unknown-enum.json @@ -0,0 +1,52 @@ +{ + "candidates": [ + { + "content": { + "parts": [ + { + "text": "1. **Use Freshly Ground Coffee**:\n - Grind your coffee beans just before brewing to preserve their flavor and aroma.\n - Use a burr grinder for a consistent grind size.\n\n\n2. **Choose the Right Water**:\n - Use filtered or spring water for the best taste.\n - Avoid using tap water, as it may contain impurities that can affect the flavor.\n\n\n3. **Measure Accurately**:\n - Use a kitchen scale to measure your coffee and water precisely.\n - A general rule of thumb is to use 1:16 ratio of coffee to water (e.g., 15 grams of coffee to 240 grams of water).\n\n\n4. **Preheat Your Equipment**:\n - Preheat your coffee maker or espresso machine before brewing to ensure a consistent temperature.\n\n\n5. **Control the Water Temperature**:\n - The ideal water temperature for brewing coffee is between 195°F (90°C) and 205°F (96°C).\n - Too hot water can extract bitter flavors, while too cold water won't extract enough flavor.\n\n\n6. **Steep the Coffee**:\n - For drip coffee, let the water slowly drip through the coffee grounds for optimal extraction.\n - For pour-over coffee, pour the water in a circular motion over the coffee grounds, allowing it to steep for 30-45 seconds before continuing.\n\n\n7. **Clean Your Equipment**:\n - Regularly clean your coffee maker or espresso machine to prevent the buildup of oils and residue that can affect the taste of your coffee.\n\n\n8. **Experiment with Different Coffee Beans**:\n - Try different coffee beans from various regions and roasts to find your preferred flavor profile.\n - Experiment with different grind sizes and brewing methods to optimize the flavor of your chosen beans.\n\n\n9. **Store Coffee Properly**:\n - Store your coffee beans in an airtight container in a cool, dark place to preserve their freshness and flavor.\n - Avoid storing coffee in the refrigerator or freezer, as this can cause condensation and affect the taste.\n\n\n10. **Enjoy Freshly Brewed Coffee**:\n - Drink your coffee as soon as possible after brewing to enjoy its peak flavor and aroma.\n - Coffee starts to lose its flavor and aroma within 30 minutes of brewing." + } + ] + }, + "index": 0, + "safetyRatings": [ + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT_ENUM_NEW", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HARASSMENT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "probability": "NEGLIGIBLE" + } + ] + } + ], + "promptFeedback": { + "safetyRatings": [ + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_HARASSMENT", + "probability": "NEGLIGIBLE" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT_LIKE_A_NEW_ENUM", + "probability": "NEGLIGIBLE_NEW_ENUM" + } + ] + } +} diff --git a/packages/vertexai/tsconfig.json b/packages/vertexai/tsconfig.json new file mode 100644 index 00000000000..ca3b32571f5 --- /dev/null +++ b/packages/vertexai/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../config/tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + }, + "exclude": [ + "dist/**/*" + ] +} \ No newline at end of file diff --git a/packages/webchannel-wrapper/CHANGELOG.md b/packages/webchannel-wrapper/CHANGELOG.md index f955d35d152..07eb7707aed 100644 --- a/packages/webchannel-wrapper/CHANGELOG.md +++ b/packages/webchannel-wrapper/CHANGELOG.md @@ -1,5 +1,11 @@ # @firebase/webchannel-wrapper +## 0.10.6 + +### Patch Changes + +- [`0c5150106`](https://github.com/firebase/firebase-js-sdk/commit/0c515010607bf2223b468acb94c672b1279ed1a0) [#8079](https://github.com/firebase/firebase-js-sdk/pull/8079) - Update `repository.url` field in all `package.json` files to NPM's preferred format. + ## 0.10.5 ### Patch Changes diff --git a/packages/webchannel-wrapper/bloom-blob/package.json b/packages/webchannel-wrapper/bloom-blob/package.json new file mode 100644 index 00000000000..956333e7cf2 --- /dev/null +++ b/packages/webchannel-wrapper/bloom-blob/package.json @@ -0,0 +1,9 @@ +{ + "name": "@firebase/webchannel-wrapper/bloom-blob", + "description": "Bloom filter related code from the Closure library.", + "main": "../dist/bloom-blob/bloom_blob_es2018.js", + "browser": "../dist/bloom-blob/esm/bloom_blob_es2018.js", + "module": "../dist/bloom-blob/esm/bloom_blob_es2018.js", + "esm5": "../dist/bloom-blob/bloom_blob_es5.js", + "typings": "../dist/bloom-blob/bloom_blob_types.d.ts" +} diff --git a/packages/webchannel-wrapper/empty.js b/packages/webchannel-wrapper/empty.js new file mode 100644 index 00000000000..0a92763191f --- /dev/null +++ b/packages/webchannel-wrapper/empty.js @@ -0,0 +1,24 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * This package has no main entry point and only allows imports from its + * two subpaths. This file is provided for the top-level package.json + * "main" field to point to. + */ + +export default {}; diff --git a/packages/webchannel-wrapper/externs/overrides.js b/packages/webchannel-wrapper/externs/overrides.js deleted file mode 100644 index 8aa01e2ae5d..00000000000 --- a/packages/webchannel-wrapper/externs/overrides.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @license - * Copyright 2017 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Overrides for the goog.net.WebChannel.Options object provided - * by closure-library. This prevents the mangling of these properties - * so downstream clients can properly leverage the API - */ - -/** @record @suppress {duplicate} */ -goog.net.WebChannel.Options = {}; - -/** @type {Object|undefined} */ -goog.net.WebChannel.Options.messageHeaders; - -/** @type {Object|undefined} */ -goog.net.WebChannel.Options.initMessageHeaders; - -/** @type {string|boolean|undefined} */ -goog.net.WebChannel.Options.messageContentType; - -/** @type {Object|undefined|undefined} */ -goog.net.WebChannel.Options.messageUrlParams; - -/** @type {boolean|undefined} */ -goog.net.WebChannel.Options.clientProtocolHeaderRequired; - -/** @type {number|undefined} */ -goog.net.WebChannel.Options.concurrentRequestLimit; - -/** @type {boolean|undefined} */ -goog.net.WebChannel.Options.supportsCrossDomainXhr; - -/** @type {boolean|undefined} */ -goog.net.WebChannel.Options.sendRawJson; - -/** @type {string|undefined} */ -goog.net.WebChannel.Options.httpSessionIdParam; - -/** @type {boolean|undefined} */ -goog.net.WebChannel.Options.encodeInitMessageHeaders; - -/** @type {boolean|undefined} */ -goog.net.WebChannel.Options.fastHandshake; - -/** @type {!Object|undefined} */ -goog.net.WebChannel.Options.internalChannelParams; - -/** @type {boolean|undefined} */ -goog.net.WebChannel.Options.forceLongPolling; - -/** @type {boolean|undefined} */ -goog.net.WebChannel.Options.detectBufferingProxy; - -/** @type {boolean|undefined} */ -goog.net.WebChannel.Options.useFetchStreams; - -/** @type {unknown} */ -goog.net.WebChannel.Options.xmlHttpFactory; - -/** @type {number|undefined} */ -goog.net.WebChannel.Options.longPollingTimeout; - -goog.labs.net.webChannel.requestStats.Event = {}; -goog.labs.net.webChannel.requestStats.Event.STAT_EVENT; - -goog.labs.net.webChannel.requestStats.StatEvent = {}; -goog.labs.net.webChannel.requestStats.StatEvent.stat; - -goog.labs.net.webChannel.requestStats.Stat = {}; -goog.labs.net.webChannel.requestStats.Stat.PROXY; -goog.labs.net.webChannel.requestStats.Stat.NOPROXY; diff --git a/packages/webchannel-wrapper/gulpfile.js b/packages/webchannel-wrapper/gulpfile.js deleted file mode 100644 index 820f7ea537e..00000000000 --- a/packages/webchannel-wrapper/gulpfile.js +++ /dev/null @@ -1,218 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const gulp = require('gulp'); -const rollup = require('rollup'); -const closureCompiler = require('google-closure-compiler').gulp(); -const del = require('del'); -const path = require('path'); -const sourcemaps = require('gulp-sourcemaps'); -const { resolve } = require('path'); -const commonjs = require('@rollup/plugin-commonjs'); -const rollupSourcemaps = require('rollup-plugin-sourcemaps'); -const typescriptPlugin = require('rollup-plugin-typescript2'); -const typescript = require('typescript'); -const pkg = require('./package.json'); - -// Copied from "../../scripts/build/rollup_emit_module_package_file" which is ESM -// and would require converting this file to MJS to use -function emitModulePackageFile() { - return { - generateBundle() { - this.emitFile({ - fileName: 'package.json', - source: `{"type":"module"}`, - type: 'asset' - }); - }, - name: 'emit-module-package-file' - }; -} - -// The optimization level for the JS compiler. -// Valid levels: WHITESPACE_ONLY, SIMPLE_OPTIMIZATIONS, ADVANCED_OPTIMIZATIONS. -const OPTIMIZATION_LEVEL = 'ADVANCED_OPTIMIZATIONS'; - -// For minified builds, wrap the output so we avoid leaking global variables. -const CJS_WRAPPER_PREFIX = `(function() {`; -const CJS_WRAPPER_SUFFIX = - `}).apply(typeof global !== 'undefined' ? ` + - `global : typeof self !== 'undefined' ? ` + - `self : typeof window !== 'undefined' ? window : {});`; - -const closureLibRoot = path.dirname( - require.resolve('google-closure-library/package.json') -); - -const closureDefines = [ - // Avoid unsafe eval() calls (https://github.com/firebase/firebase-js-sdk/issues/798) - 'goog.json.USE_NATIVE_JSON=true', - // Disable debug logging (saves 8780 bytes). - 'goog.DEBUG=false', - // Disable fallbacks for running async code (saves 1472 bytes). - 'goog.ASSUME_NATIVE_PROMISE=true', - // Disables IE8-specific event fallback code (saves 523 bytes). - 'goog.events.CAPTURE_SIMULATION_MODE=0', - // Disable IE-Specific ActiveX fallback for XHRs (saves 524 bytes). - 'goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR=true', - // Disable Origin Trials code for WebChannel (saves 1786 bytes). - 'goog.net.webChannel.ALLOW_ORIGIN_TRIAL_FEATURES=false' -]; - -/** - * Generates a closure compiler build of webchannel-wrapper. - * @param {string} filename name of the generated file - * @param {string} prefix prefix to the compiled code - * @param {string} suffix suffix to the compiled code - */ -function createBuildTask(filename, prefix, suffix, languageout) { - return function closureBuild() { - return gulp - .src( - [ - `${closureLibRoot}/closure/goog/**/*.js`, - `${closureLibRoot}/third_party/closure/goog/**/*.js`, - 'src/**/*.js' - ], - { base: '.' } - ) - .pipe(sourcemaps.init()) - .pipe( - closureCompiler({ - js_output_file: filename, - output_wrapper: `${prefix}%output%${suffix}`, - entry_point: 'firebase.webchannel.wrapper', - compilation_level: OPTIMIZATION_LEVEL, - externs: [ - resolve(__dirname, './externs/overrides.js'), - resolve(__dirname, './externs/module.js') - ], - language_out: languageout, - dependency_mode: 'PRUNE', - define: closureDefines - }) - ) - .pipe(sourcemaps.write('.')) - .pipe(gulp.dest('dist')); - }; -} - -function createRollupTask({ - inputPath, - outputExtension, - compileToES5 = false, - format = 'es' -}) { - return async function rollupBuild() { - const plugins = [rollupSourcemaps(), commonjs()]; - if (compileToES5) { - plugins.push( - typescriptPlugin({ - typescript, - // Uncomment for development only. Prevents caching between builds. - // clean: true, - compilerOptions: { allowJs: true }, - include: ['dist/**/*.js'] - }) - ); - } - if (format === 'es') { - plugins.push(emitModulePackageFile()); - } - const inputOptions = { - input: inputPath, - plugins - }; - - let outputFilename; - if (format === 'es') { - if (compileToES5) { - // ESM5 - outputFilename = pkg.esm5; - } else { - // ESM2017 - outputFilename = pkg.module; - } - } else { - // CJS - outputFilename = pkg.main; - } - const outputOptions = { - file: outputFilename, - format, - sourcemap: true, - // Prevents warning when compiling CJS that there are named and default exports together. - exports: 'named' - }; - - const bundle = await rollup.rollup(inputOptions); - return bundle.write(outputOptions); - }; -} - -async function deleteIntermediateFiles() { - await del('dist/temp'); -} - -// Closure-generated ES2017 intermediate file (no wrapper text) -const intermediateEsmFile = 'temp/esm.js'; -const intermediateEsmPath = resolve(__dirname, 'dist/', intermediateEsmFile); -const esmBuild = createBuildTask( - intermediateEsmFile, - '', - '', - 'ECMASCRIPT_2017' -); - -// cjs output -// Closure-generated ES5 CJS build -const cjsBuildOutput = 'index.js'; -const cjsBuild = createBuildTask( - cjsBuildOutput, - CJS_WRAPPER_PREFIX, - CJS_WRAPPER_SUFFIX, - 'ECMASCRIPT5' -); - -gulp.task('cjs', cjsBuild); - -// esm intermediateEsmPath -const rollupEsmTask = createRollupTask({ - inputPath: intermediateEsmPath, - outputExtension: 'esm', - compileToES5: true, - format: 'es' -}); -gulp.task('esm', gulp.series(esmBuild, rollupEsmTask)); - -// esm2017 output -const rollup2017Task = createRollupTask({ - inputPath: intermediateEsmPath, - outputExtension: 'esm2017', - compileToES5: false, - format: 'es' -}); -gulp.task('esm2017', gulp.series(esmBuild, rollup2017Task)); - -gulp.task( - 'allEsm', - gulp.series(esmBuild, gulp.parallel(rollupEsmTask, rollup2017Task)) -); - -gulp.task('buildAll', gulp.parallel('cjs', 'allEsm')); - -gulp.task('default', gulp.series('buildAll', deleteIntermediateFiles)); diff --git a/packages/webchannel-wrapper/package.json b/packages/webchannel-wrapper/package.json index a009f7c94e4..ce1eced19bd 100644 --- a/packages/webchannel-wrapper/package.json +++ b/packages/webchannel-wrapper/package.json @@ -1,37 +1,41 @@ { "name": "@firebase/webchannel-wrapper", - "version": "0.10.5", + "version": "0.10.6", "description": "A wrapper of the webchannel packages from closure-library for use outside of a closure compiled application", "author": "Firebase (https://firebase.google.com/)", - "main": "dist/index.js", - "module": "dist/esm/index.esm2017.js", - "esm5": "dist/esm/index.esm.js", + "main": "empty.js", "exports": { - ".": { - "types": "./src/index.d.ts", - "require": "./dist/index.js", - "esm5": "./dist/esm/index.esm.js", - "default": "./dist/esm/index.esm2017.js" + "./webchannel-blob": { + "types": "./dist/webchannel-blob/webchannel_blob_types.d.ts", + "require": "./dist/webchannel-blob/webchannel_blob_es2018.js", + "esm5": "./dist/webchannel-blob/webchannel_blob_es5.js", + "default": "./dist/webchannel-blob/esm/webchannel_blob_es2018.js" + }, + "./bloom-blob": { + "types": "./dist/bloom-blob/bloom_blob_types.d.ts", + "require": "./dist/bloom-blob/bloom_blob_es2018.js", + "es5": "./dist/bloom-blob/bloom_blob_es5.js", + "default": "./dist/bloom-blob/esm/bloom_blob_es2018.js" }, "./package.json": "./package.json" }, "files": [ - "dist" + "dist", + "bloom-blob/package.json", + "webchannel-blob/package.json" ], "scripts": { "dev": "watch 'yarn build' src", - "build": "gulp", + "build": "rollup -c", "test": "echo 'No test suite for webchannel-wrapper'", "test:ci": "echo 'No test suite for webchannel-wrapper'" }, "license": "Apache-2.0", "devDependencies": { + "closure-net": "git+https://github.com/google/closure-net.git#0412666", "@rollup/plugin-commonjs": "21.1.0", - "google-closure-compiler": "20230228.0.0", - "google-closure-library": "git+https://github.com/google/closure-library.git#7818ff7", - "gulp": "4.0.2", - "gulp-sourcemaps": "3.0.0", "rollup": "2.79.1", + "rollup-plugin-copy": "3.5.0", "rollup-plugin-sourcemaps": "0.6.3", "rollup-plugin-typescript2": "0.31.2", "typescript": "4.7.4" @@ -39,9 +43,9 @@ "repository": { "directory": "packages/webchannel-wrapper", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, - "typings": "src/index.d.ts", + "typings": "./dist/webchannel-blob/webchannel_blob_types.d.ts", "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" } diff --git a/packages/webchannel-wrapper/rollup.config.js b/packages/webchannel-wrapper/rollup.config.js new file mode 100644 index 00000000000..77c29ecb4ac --- /dev/null +++ b/packages/webchannel-wrapper/rollup.config.js @@ -0,0 +1,73 @@ +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { join } from 'path'; +import copy from 'rollup-plugin-copy'; +import commonjs from '@rollup/plugin-commonjs'; +import typescriptPlugin from 'rollup-plugin-typescript2'; +import typescript from 'typescript'; +import { emitModulePackageFile } from '../../scripts/build/rollup_emit_module_package_file'; +import pkg from './package.json'; + +const closureBlobsDir = '../../node_modules/closure-net/firebase/'; + +const es2017BuildPlugins = [ + copy({ + targets: [ + { + src: join(closureBlobsDir, 'webchannel_blob_*.*'), + dest: 'dist/webchannel-blob' + }, + { src: join(closureBlobsDir, 'bloom_blob_*.*'), dest: 'dist/bloom-blob' } + ] + }), + typescriptPlugin({ + typescript, + tsconfigOverride: { + compilerOptions: { + target: 'es2017' + } + } + }), + commonjs() +]; + +/** + * ESM builds + */ +const esm2017Builds = [ + { + input: join(closureBlobsDir, 'webchannel_blob_es2018.js'), + output: { + file: pkg.exports['./webchannel-blob'].default, + format: 'es', + sourcemap: true + }, + plugins: [...es2017BuildPlugins, emitModulePackageFile()] + }, + { + input: join(closureBlobsDir, 'bloom_blob_es2018.js'), + output: { + file: pkg.exports['./bloom-blob'].default, + format: 'es', + sourcemap: true + }, + plugins: [...es2017BuildPlugins, emitModulePackageFile()] + } +]; + +export default esm2017Builds; diff --git a/packages/webchannel-wrapper/src/index.d.ts b/packages/webchannel-wrapper/src/index.d.ts deleted file mode 100644 index 776bb8e8634..00000000000 --- a/packages/webchannel-wrapper/src/index.d.ts +++ /dev/null @@ -1,165 +0,0 @@ -/** - * @license - * Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// WARNING: This is not a complete set of types exported by WebChannelWrapper. -// It is merely meant to support the usage patterns of the Firestore SDK. - -export var EventType: { - COMPLETE: string; -}; - -export namespace WebChannel { - export var EventType: { - OPEN: string; - CLOSE: string; - ERROR: string; - MESSAGE: string; - }; -} - -export var Event: { - STAT_EVENT: string; -}; - -export var Stat: { - PROXY: number; - NOPROXY: number; -}; - -export var ErrorCode: { - NO_ERROR: number; - HTTP_ERROR: number; - TIMEOUT: number; -}; - -export interface Headers { - [name: string]: string | number; -} - -export interface WebChannelError { - error?: { status: string; message: string }; -} - -export class XhrIo { - send( - url: string, - method?: string, - body?: string, - headers?: Headers, - timeoutInterval?: number - ): void; - - getLastErrorCode(): number; - - getLastError(): string; - - getStatus(): number; - - getResponseText(): string; - - getResponseJson(): WebChannelError | object; - - listenOnce(type: string, cb: (param: unknown) => void): void; - - setWithCredentials(withCredentials: boolean): void; -} - -export interface WebChannelOptions { - messageHeaders?: { - // To ensure compatibility with property minifcation tools, keys need to - // be listed explicity. - [k: string]: never; - }; - initMessageHeaders?: { - // To ensure compatibility with property minifcation tools, keys need to - // be listed explicity. - [k: string]: never; - }; - messageContentType?: string; - messageUrlParams?: { - database?: string; - }; - clientProtocolHeaderRequired?: boolean; - concurrentRequestLimit?: number; - supportsCrossDomainXhr?: boolean; - sendRawJson?: boolean; - httpSessionIdParam?: string; - encodeInitMessageHeaders?: boolean; - forceLongPolling?: boolean; - detectBufferingProxy?: boolean; - longPollingTimeout?: number; - fastHandshake?: boolean; - disableRedac?: boolean; - clientProfile?: string; - internalChannelParams?: { - forwardChannelRequestTimeoutMs?: number; - }; - useFetchStreams?: boolean; - xmlHttpFactory?: unknown; - requestRefreshThresholds?: { [key: string]: number }; -} - -export interface EventTarget { - listen(type: string | number, cb: (param: unknown) => void): void; -} - -export interface WebChannel extends EventTarget { - open(): void; - close(): void; - send(msg: unknown): void; -} - -export interface StatEvent { - stat: number; -} - -export interface WebChannelTransport { - createWebChannel(url: string, options: WebChannelOptions): WebChannel; -} - -export function createWebChannelTransport(): WebChannelTransport; - -export function getStatEventTarget(): EventTarget; - -export class FetchXmlHttpFactory { - constructor(options: {}); -} - -// See https://google.github.io/closure-library/api/goog.crypt.Md5.html -// Unit test are written in -// packages/firestore/test/unit/core/webchannel_wrapper.test.ts -export class Md5 { - reset(): void; - digest(): Array; - update(bytes: Array | Uint8Array | string, opt_length?: number): void; -} - -// See https://google.github.io/closure-library/api/goog.math.Integer.html -// Unit test are written in -// packages/firestore/test/unit/core/webchannel_wrapper.test.ts -export class Integer { - constructor(bits: Array, sign: number); - add(other: Integer): Integer; - multiply(other: Integer): Integer; - modulo(other: Integer): Integer; - compare(other: Integer): number; - toNumber(): number; - toString(opt_radix?: number): string; - getBits(index: number): number; - static fromNumber(value: number): Integer; - static fromString(str: string, opt_radix?: number): Integer; -} diff --git a/packages/webchannel-wrapper/src/index.js b/packages/webchannel-wrapper/src/index.js deleted file mode 100644 index 7346b0acaa4..00000000000 --- a/packages/webchannel-wrapper/src/index.js +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @license - * Copyright 2017 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Bring in closure-library dependencies - */ - -goog.provide('firebase.webchannel.wrapper'); - -// goog.net.WebChannelTransport -goog.require('goog.net.createWebChannelTransport'); -goog.require('goog.net.FetchXmlHttpFactory'); -goog.require('goog.labs.net.webChannel.requestStats'); -goog.require('goog.labs.net.webChannel.WebChannelBaseTransport'); - -/** - * NOTE: The `createWebChannel` function takes an options object as a second param - * whose properties are typically mangled. We override these in externs/overrides.js - * Without those externs, this does not function properly. - */ -goog.labs.net.webChannel.WebChannelBaseTransport.prototype['createWebChannel'] = - goog.labs.net.webChannel.WebChannelBaseTransport.prototype.createWebChannel; -goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype['send'] = - goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype.send; -goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype['open'] = - goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype.open; -goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype['close'] = - goog.labs.net.webChannel.WebChannelBaseTransport.Channel.prototype.close; - -// goog.net.ErrorCode -goog.require('goog.net.ErrorCode'); -goog.net.ErrorCode['NO_ERROR'] = goog.net.ErrorCode.NO_ERROR; -goog.net.ErrorCode['TIMEOUT'] = goog.net.ErrorCode.TIMEOUT; -goog.net.ErrorCode['HTTP_ERROR'] = goog.net.ErrorCode.HTTP_ERROR; - -// goog.net.ErrorType -goog.require('goog.net.EventType'); -goog.net.EventType['COMPLETE'] = goog.net.EventType.COMPLETE; - -// goog.net.WebChannel -goog.require('goog.net.WebChannel'); -goog.require('goog.events.EventTarget'); -goog.net.WebChannel['EventType'] = goog.net.WebChannel.EventType; -goog.net.WebChannel.EventType['OPEN'] = goog.net.WebChannel.EventType.OPEN; -goog.net.WebChannel.EventType['CLOSE'] = goog.net.WebChannel.EventType.CLOSE; -goog.net.WebChannel.EventType['ERROR'] = goog.net.WebChannel.EventType.ERROR; -goog.net.WebChannel.EventType['MESSAGE'] = - goog.net.WebChannel.EventType.MESSAGE; -goog.events.EventTarget.prototype['listen'] = - goog.events.EventTarget.prototype.listen; - -goog.require('goog.net.XhrIo'); -goog.net.XhrIo.prototype['listenOnce'] = goog.net.XhrIo.prototype.listenOnce; -goog.net.XhrIo.prototype['getLastError'] = - goog.net.XhrIo.prototype.getLastError; -goog.net.XhrIo.prototype['getLastErrorCode'] = - goog.net.XhrIo.prototype.getLastErrorCode; -goog.net.XhrIo.prototype['getStatus'] = goog.net.XhrIo.prototype.getStatus; -goog.net.XhrIo.prototype['getResponseJson'] = - goog.net.XhrIo.prototype.getResponseJson; -goog.net.XhrIo.prototype['getResponseText'] = - goog.net.XhrIo.prototype.getResponseText; -goog.net.XhrIo.prototype['send'] = goog.net.XhrIo.prototype.send; -goog.net.XhrIo.prototype['setWithCredentials'] = - goog.net.XhrIo.prototype.setWithCredentials; - -goog.require('goog.crypt.Md5'); -goog.crypt.Md5.prototype['digest'] = goog.crypt.Md5.prototype.digest; -goog.crypt.Md5.prototype['reset'] = goog.crypt.Md5.prototype.reset; -goog.crypt.Md5.prototype['update'] = goog.crypt.Md5.prototype.update; - -goog.require('goog.math.Integer'); -goog.math.Integer.prototype['add'] = goog.math.Integer.prototype.add; -goog.math.Integer.prototype['multiply'] = goog.math.Integer.prototype.multiply; -goog.math.Integer.prototype['modulo'] = goog.math.Integer.prototype.modulo; -goog.math.Integer.prototype['compare'] = goog.math.Integer.prototype.compare; -goog.math.Integer.prototype['toNumber'] = goog.math.Integer.prototype.toNumber; -goog.math.Integer.prototype['toString'] = goog.math.Integer.prototype.toString; -goog.math.Integer.prototype['getBits'] = goog.math.Integer.prototype.getBits; -goog.math.Integer['fromNumber'] = goog.math.Integer.fromNumber; -goog.math.Integer['fromString'] = goog.math.Integer.fromString; - -module['exports']['createWebChannelTransport'] = - goog.net.createWebChannelTransport; -module['exports']['getStatEventTarget'] = - goog.labs.net.webChannel.requestStats.getStatEventTarget; -module['exports']['ErrorCode'] = goog.net.ErrorCode; -module['exports']['EventType'] = goog.net.EventType; -module['exports']['Event'] = goog.labs.net.webChannel.requestStats.Event; -module['exports']['Stat'] = goog.labs.net.webChannel.requestStats.Stat; -module['exports']['FetchXmlHttpFactory'] = goog.net.FetchXmlHttpFactory; -module['exports']['WebChannel'] = goog.net.WebChannel; -module['exports']['XhrIo'] = goog.net.XhrIo; -module['exports']['Md5'] = goog.crypt.Md5; -module['exports']['Integer'] = goog.math.Integer; diff --git a/packages/webchannel-wrapper/tsconfig.json b/packages/webchannel-wrapper/tsconfig.json index a777c9d54b7..23e05a91330 100644 --- a/packages/webchannel-wrapper/tsconfig.json +++ b/packages/webchannel-wrapper/tsconfig.json @@ -4,5 +4,6 @@ "declaration": false, "outDir": "dist", "downlevelIteration": true, - } + }, + "include": ["../../node_modules/closure-net/firebase"] } diff --git a/packages/webchannel-wrapper/webchannel-blob/package.json b/packages/webchannel-wrapper/webchannel-blob/package.json new file mode 100644 index 00000000000..cb339b82557 --- /dev/null +++ b/packages/webchannel-wrapper/webchannel-blob/package.json @@ -0,0 +1,9 @@ +{ + "name": "@firebase/webchannel-wrapper/webchannel-blob", + "description": "Webchannel related code from the Closure library.", + "main": "../dist/webchannel-blob/webchannel_blob_es2018.js", + "browser": "../dist/webchannel-blob/esm/webchannel_blob_es2018.js", + "module": "../dist/webchannel-blob/esm/webchannel_blob_es2018.js", + "esm5": "../dist/webchannel-blob/webchannel_blob_es5.js", + "typings": "../dist/webchannel-blob/webchannel_blob_types.d.ts" +} diff --git a/repo-scripts/api-documenter/package.json b/repo-scripts/api-documenter/package.json index 55289c2170d..1e6b1a9ac21 100644 --- a/repo-scripts/api-documenter/package.json +++ b/repo-scripts/api-documenter/package.json @@ -5,7 +5,7 @@ "repository": { "directory": "repo-scripts/documenter", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "license": "Apache-2.0", "scripts": { @@ -13,7 +13,7 @@ "test": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' nyc --reporter lcovonly -- mocha src/**/*.test.ts --config ../../config/mocharc.node.js" }, "bin": { - "api-documenter-fire": "./dist/start.js" + "api-documenter-fire": "dist/start.js" }, "files": [ "dist" @@ -24,15 +24,15 @@ "api-extractor-model-me": "0.1.1", "@microsoft/tsdoc": "0.12.24", "@rushstack/node-core-library": "3.59.7", - "@rushstack/ts-command-line": "4.15.2", + "@rushstack/ts-command-line": "4.19.1", "colors": "~1.4.0", "resolve": "~1.22.0", "tslib": "^2.1.0", "js-yaml": "4.1.0" }, "devDependencies": { - "@types/js-yaml": "4.0.5", - "@types/resolve": "1.20.2", + "@types/js-yaml": "4.0.9", + "@types/resolve": "1.20.6", "mocha-chai-jest-snapshot": "1.1.3" } } diff --git a/repo-scripts/changelog-generator/package.json b/repo-scripts/changelog-generator/package.json index 648892ad527..e04bb6f2ecf 100644 --- a/repo-scripts/changelog-generator/package.json +++ b/repo-scripts/changelog-generator/package.json @@ -20,7 +20,7 @@ "@changesets/types": "3.3.0", "@changesets/get-github-info": "0.5.2", "@types/node": "20.8.10", - "undici": "5.26.5" + "undici": "5.28.4" }, "license": "Apache-2.0", "devDependencies": { @@ -29,7 +29,7 @@ "repository": { "directory": "repo-scripts/changelog-generator", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/repo-scripts/prune-dts/package.json b/repo-scripts/prune-dts/package.json index 27deb42e859..f48f530f38a 100644 --- a/repo-scripts/prune-dts/package.json +++ b/repo-scripts/prune-dts/package.json @@ -20,7 +20,7 @@ "repository": { "directory": "repo-scripts/prune-dts", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/repo-scripts/size-analysis/analysis-helper.ts b/repo-scripts/size-analysis/analysis-helper.ts index 11dc499aedc..9507bfe253c 100644 --- a/repo-scripts/size-analysis/analysis-helper.ts +++ b/repo-scripts/size-analysis/analysis-helper.ts @@ -498,7 +498,7 @@ export async function generateReportForModule( * * @param pkgJson package.json of the module. * - * This function implements a fallback of locating module's budle file. + * This function implements a fallback of locating module's bundle file. * It first looks at esm2017 field of package.json, then module field. Main * field at the last. * diff --git a/repo-scripts/size-analysis/package.json b/repo-scripts/size-analysis/package.json index eb33f986ec7..9fd085bfe82 100644 --- a/repo-scripts/size-analysis/package.json +++ b/repo-scripts/size-analysis/package.json @@ -27,7 +27,7 @@ "rollup-plugin-typescript2": "0.31.2", "@rollup/plugin-virtual": "2.1.0", "webpack": "5.76.0", - "@types/webpack": "5.28.0", + "@types/webpack": "5.28.5", "webpack-virtual-modules": "0.5.0", "child-process-promise": "2.2.1", "memfs": "3.5.3", @@ -35,19 +35,19 @@ "typescript": "4.7.4", "terser": "5.16.1", "yargs": "17.7.2", - "@firebase/util": "1.9.3", + "@firebase/util": "1.9.5", "gzip-size": "6.0.0", "glob": "7.2.3" }, "license": "Apache-2.0", "devDependencies": { - "@firebase/logger": "0.4.0", - "@firebase/app": "0.9.25" + "@firebase/logger": "0.4.1", + "@firebase/app": "0.10.2" }, "repository": { "directory": "repo-scripts/size-analysis", "type": "git", - "url": "https://github.com/firebase/firebase-js-sdk.git" + "url": "git+https://github.com/firebase/firebase-js-sdk.git" }, "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" diff --git a/scripts/ci/check_changeset.ts b/scripts/ci/check_changeset.ts index 0c514af0a89..234eef87cd1 100644 --- a/scripts/ci/check_changeset.ts +++ b/scripts/ci/check_changeset.ts @@ -17,6 +17,7 @@ import { resolve } from 'path'; import { existsSync } from 'fs'; +import { writeFile } from 'fs/promises'; import { exec } from 'child-process-promise'; import chalk from 'chalk'; import simpleGit from 'simple-git'; @@ -28,6 +29,14 @@ const git = simpleGit(root); const baseRef = process.env.GITHUB_PULL_REQUEST_BASE_SHA || 'master'; const headRef = process.env.GITHUB_PULL_REQUEST_HEAD_SHA || 'HEAD'; +const githubOutputFile = (function (): string { + const value = process.env.GITHUB_OUTPUT; + if (!value) { + throw new Error('GITHUB_OUTPUT environment variable must be set'); + } + return value; +})(); + // Version bump text converted to rankable numbers. const bumpRank: Record = { 'patch': 0, @@ -37,7 +46,7 @@ const bumpRank: Record = { /** * Get highest bump that isn't the main firebase package, return -// numerical rank, bump text, package name. + * numerical rank, bump text, package name. */ function getHighestBump(changesetPackages: Record) { const firebasePkgJson = require(resolve( @@ -205,10 +214,13 @@ async function main() { * step. See: * https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-output-parameter */ - if (errors.length > 0) - await exec( - `echo "CHANGESET_ERROR_MESSAGE=${errors.join('%0A')}" >> $GITHUB_OUTPUT` + if (errors.length > 0) { + await writeFile( + githubOutputFile, + `CHANGESET_ERROR_MESSAGE=${errors.join('%0A')}\n`, + { flag: 'a' } ); + } process.exit(); } diff --git a/scripts/docgen/docgen.ts b/scripts/docgen/docgen.ts index 0b38da3bd8b..3f4d10ebbd9 100644 --- a/scripts/docgen/docgen.ts +++ b/scripts/docgen/docgen.ts @@ -54,7 +54,8 @@ const PREFERRED_PARAMS = [ 'messaging', 'performance', 'remoteConfig', - 'storage' + 'storage', + 'vertexAI' ]; yargs diff --git a/scripts/emulator-testing/emulators/emulator.ts b/scripts/emulator-testing/emulators/emulator.ts index d56226842eb..1295d413e4b 100644 --- a/scripts/emulator-testing/emulators/emulator.ts +++ b/scripts/emulator-testing/emulators/emulator.ts @@ -119,8 +119,8 @@ export abstract class Emulator { if (elapsed > timeout) { reject(`Emulator not ready after ${timeout}s. Exiting ...`); } else { - console.log(`Ping emulator at [http://localhost:${this.port}] ...`); - fetch(`http://localhost:${this.port}`).then( + console.log(`Ping emulator at [http://127.0.0.1:${this.port}] ...`); + fetch(`http://127.0.0.1:${this.port}`).then( () => { // Database and Firestore emulators will return 400 and 200 respectively. // As long as we get a response back, it means the emulator is ready. diff --git a/scripts/format/license.ts b/scripts/format/license.ts index 10de501165f..e5672ef41c3 100644 --- a/scripts/format/license.ts +++ b/scripts/format/license.ts @@ -81,7 +81,14 @@ export async function doLicense(changedFiles?: string[]) { filesToChange = await new Promise(resolve => { glob( '+(packages|repo-scripts)/**/*.+(ts|js)', - { ignore: ['**/node_modules/**', './node_modules/**', '**/dist/**'] }, + { + ignore: [ + '**/node_modules/**', + './node_modules/**', + '**/dist/**', + '**/mocks-lookup.ts' + ] + }, (err, res) => resolve(res) ); }); diff --git a/scripts/release/utils/publish.ts b/scripts/release/utils/publish.ts index 55d641cc510..1ed3e6261d7 100644 --- a/scripts/release/utils/publish.ts +++ b/scripts/release/utils/publish.ts @@ -75,9 +75,14 @@ export async function publishInCI( continue; } } catch (e) { - // 404 from NPM indicates the package doesn't exist there. - console.log(`Skipping pkg: ${pkg} - it has never been published to NPM.`); - continue; + const versionParts = version.split('-'); + if (versionParts[0] !== '0.0.1') { + // 404 from NPM indicates the package doesn't exist there. + console.log( + `Skipping pkg: ${pkg} - it has never been published to NPM.` + ); + continue; + } } const tag = `${pkg}@${version}`; diff --git a/yarn.lock b/yarn.lock index e8334ee4194..f8df951e815 100644 --- a/yarn.lock +++ b/yarn.lock @@ -34,21 +34,6 @@ dependencies: "@babel/highlight" "^7.14.5" -"@babel/code-frame@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== - dependencies: - "@babel/highlight" "^7.18.6" - -"@babel/code-frame@^7.22.10": - version "7.22.13" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz" - integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== - dependencies: - "@babel/highlight" "^7.22.13" - chalk "^2.4.2" - "@babel/code-frame@^7.22.5": version "7.22.5" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz" @@ -56,6 +41,14 @@ dependencies: "@babel/highlight" "^7.22.5" +"@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2": + version "7.24.2" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" + integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== + dependencies: + "@babel/highlight" "^7.24.2" + picocolors "^1.0.0" + "@babel/compat-data@^7.15.0": version "7.15.0" resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz" @@ -66,22 +59,27 @@ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz" integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ== -"@babel/core@7.22.11": - version "7.22.11" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.22.11.tgz" - integrity sha512-lh7RJrtPdhibbxndr6/xx0w8+CVlY5FJZiaSz908Fpy+G0xkBFTvwLcKJFF4PJxVfGhVWNebikpWGnOoC71juQ== +"@babel/compat-data@^7.23.5": + version "7.24.1" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz#31c1f66435f2a9c329bb5716a6d6186c516c3742" + integrity sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA== + +"@babel/core@7.24.3": + version "7.24.3" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz#568864247ea10fbd4eff04dda1e05f9e2ea985c3" + integrity sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.22.10" - "@babel/generator" "^7.22.10" - "@babel/helper-compilation-targets" "^7.22.10" - "@babel/helper-module-transforms" "^7.22.9" - "@babel/helpers" "^7.22.11" - "@babel/parser" "^7.22.11" - "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.11" - "@babel/types" "^7.22.11" - convert-source-map "^1.7.0" + "@babel/code-frame" "^7.24.2" + "@babel/generator" "^7.24.1" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.24.1" + "@babel/parser" "^7.24.1" + "@babel/template" "^7.24.0" + "@babel/traverse" "^7.24.1" + "@babel/types" "^7.24.0" + convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" @@ -117,24 +115,14 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/generator@^7.22.10": - version "7.22.10" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz" - integrity sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A== - dependencies: - "@babel/types" "^7.22.10" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - -"@babel/generator@^7.22.7": - version "7.22.7" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz" - integrity sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ== +"@babel/generator@^7.24.1": + version "7.24.1" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz#e67e06f68568a4ebf194d1c6014235344f0476d0" + integrity sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A== dependencies: - "@babel/types" "^7.22.5" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" + "@babel/types" "^7.24.0" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" "@babel/helper-annotate-as-pure@^7.18.6": @@ -179,6 +167,17 @@ lru-cache "^5.1.1" semver "^6.3.1" +"@babel/helper-compilation-targets@^7.23.6": + version "7.23.6" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" + integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== + dependencies: + "@babel/compat-data" "^7.23.5" + "@babel/helper-validator-option" "^7.23.5" + browserslist "^4.22.2" + lru-cache "^5.1.1" + semver "^6.3.1" + "@babel/helper-create-class-features-plugin@^7.22.11": version "7.22.11" resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.11.tgz" @@ -237,20 +236,16 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + "@babel/helper-environment-visitor@^7.22.5": version "7.22.5" resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz" integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q== -"@babel/helper-function-name@^7.15.4": - version "7.15.4" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz" - integrity sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw== - dependencies: - "@babel/helper-get-function-arity" "^7.15.4" - "@babel/template" "^7.15.4" - "@babel/types" "^7.15.4" - "@babel/helper-function-name@^7.22.5": version "7.22.5" resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz" @@ -259,19 +254,13 @@ "@babel/template" "^7.22.5" "@babel/types" "^7.22.5" -"@babel/helper-get-function-arity@^7.15.4": - version "7.15.4" - resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz" - integrity sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-hoist-variables@^7.15.4": - version "7.15.4" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz" - integrity sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA== +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== dependencies: - "@babel/types" "^7.15.4" + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" @@ -301,6 +290,13 @@ dependencies: "@babel/types" "^7.15.4" +"@babel/helper-module-imports@^7.22.15": + version "7.24.3" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128" + integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg== + dependencies: + "@babel/types" "^7.24.0" + "@babel/helper-module-imports@^7.22.5": version "7.22.5" resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz" @@ -347,6 +343,17 @@ "@babel/helper-split-export-declaration" "^7.22.6" "@babel/helper-validator-identifier" "^7.22.5" +"@babel/helper-module-transforms@^7.23.3": + version "7.23.3" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" + integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== + 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" + "@babel/helper-optimise-call-expression@^7.15.4": version "7.15.4" resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz" @@ -461,7 +468,12 @@ resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== -"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.22.20", "@babel/helper-validator-identifier@^7.22.5": +"@babel/helper-string-parser@^7.23.4": + version "7.24.1" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz#f99c36d3593db9540705d0739a1f10b5e20c696e" + integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ== + +"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.22.20", "@babel/helper-validator-identifier@^7.22.5": 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== @@ -486,6 +498,11 @@ resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz" integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw== +"@babel/helper-validator-option@^7.23.5": + version "7.23.5" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" + integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== + "@babel/helper-wrap-function@^7.22.9": version "7.22.10" resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz" @@ -504,14 +521,14 @@ "@babel/traverse" "^7.15.4" "@babel/types" "^7.15.4" -"@babel/helpers@^7.22.11": - version "7.22.11" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.11.tgz" - integrity sha512-vyOXC8PBWaGc5h7GMsNx68OH33cypkEDJCHvYVVgVbbxJDROYVtexSk0gK5iCF1xNjRIN2s8ai7hwkWDq5szWg== +"@babel/helpers@^7.24.1": + version "7.24.1" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz#183e44714b9eba36c3038e442516587b1e0a1a94" + integrity sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg== dependencies: - "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.11" - "@babel/types" "^7.22.11" + "@babel/template" "^7.24.0" + "@babel/traverse" "^7.24.1" + "@babel/types" "^7.24.0" "@babel/highlight@^7.10.4", "@babel/highlight@^7.14.5": version "7.14.5" @@ -522,24 +539,6 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.22.13": - version "7.22.13" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz" - integrity sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ== - dependencies: - "@babel/helper-validator-identifier" "^7.22.5" - chalk "^2.4.2" - js-tokens "^4.0.0" - "@babel/highlight@^7.22.5": version "7.22.5" resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz" @@ -549,21 +548,31 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/highlight@^7.24.2": + version "7.24.2" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz#3f539503efc83d3c59080a10e6634306e0370d26" + integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + "@babel/parser@^7.15.4", "@babel/parser@^7.15.5", "@babel/parser@^7.7.2": version "7.15.7" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.15.7.tgz" integrity sha512-rycZXvQ+xS9QyIcJ9HXeDWf1uxqlbVFAUq0Rq0dbc50Zb/+wUe/ehyfzGfm9KZZF0kBejYgxltBXocP+gKdL2g== -"@babel/parser@^7.22.11": - version "7.22.13" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.22.13.tgz" - integrity sha512-3l6+4YOvc9wx7VlCSw4yQfcBo01ECA8TicQfbnCPuCEpRQrf+gTUyGdxNw+pyTUyywp6JRD1w0YQs9TpBXYlkw== - -"@babel/parser@^7.22.5", "@babel/parser@^7.22.7": +"@babel/parser@^7.22.5": version "7.22.7" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz" integrity sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q== +"@babel/parser@^7.24.0", "@babel/parser@^7.24.1": + version "7.24.1" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz#1e416d3627393fab1cb5b0f2f1796a100ae9133a" + integrity sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg== + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5": version "7.22.5" resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz" @@ -1253,15 +1262,15 @@ "@babel/plugin-transform-modules-commonjs" "^7.22.11" "@babel/plugin-transform-typescript" "^7.22.11" -"@babel/register@7.22.5": - version "7.22.5" - resolved "https://registry.npmjs.org/@babel/register/-/register-7.22.5.tgz" - integrity sha512-vV6pm/4CijSQ8Y47RH5SopXzursN35RQINfGJkmOlcpAtGuf94miFvIPhCKGQN7WGIcsgG1BHEX2KVdTYwTwUQ== +"@babel/register@7.23.7": + version "7.23.7" + resolved "https://registry.npmjs.org/@babel/register/-/register-7.23.7.tgz#485a5e7951939d21304cae4af1719fdb887bc038" + integrity sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ== dependencies: clone-deep "^4.0.1" find-cache-dir "^2.0.0" make-dir "^2.1.0" - pirates "^4.0.5" + pirates "^4.0.6" source-map-support "^0.5.16" "@babel/regjsgen@^0.8.0": @@ -1292,6 +1301,15 @@ "@babel/parser" "^7.15.4" "@babel/types" "^7.15.4" +"@babel/template@^7.22.15", "@babel/template@^7.24.0": + version "7.24.0" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" + integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/parser" "^7.24.0" + "@babel/types" "^7.24.0" + "@babel/template@^7.22.5": version "7.22.5" resolved "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz" @@ -1301,51 +1319,20 @@ "@babel/parser" "^7.22.5" "@babel/types" "^7.22.5" -"@babel/traverse@^7.15.4", "@babel/traverse@^7.7.2": - version "7.15.4" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz" - integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/generator" "^7.15.4" - "@babel/helper-function-name" "^7.15.4" - "@babel/helper-hoist-variables" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" - "@babel/parser" "^7.15.4" - "@babel/types" "^7.15.4" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.22.11": - version "7.22.11" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.11.tgz" - integrity sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ== - dependencies: - "@babel/code-frame" "^7.22.10" - "@babel/generator" "^7.22.10" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-function-name" "^7.22.5" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.22.11" - "@babel/types" "^7.22.11" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.22.5": - version "7.22.8" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz" - integrity sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw== +"@babel/traverse@^7.15.4", "@babel/traverse@^7.22.5", "@babel/traverse@^7.24.1", "@babel/traverse@^7.7.2": + version "7.24.1" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz#d65c36ac9dd17282175d1e4a3c49d5b7988f530c" + integrity sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ== dependencies: - "@babel/code-frame" "^7.22.5" - "@babel/generator" "^7.22.7" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-function-name" "^7.22.5" + "@babel/code-frame" "^7.24.1" + "@babel/generator" "^7.24.1" + "@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.22.7" - "@babel/types" "^7.22.5" - debug "^4.1.0" + "@babel/parser" "^7.24.1" + "@babel/types" "^7.24.0" + debug "^4.3.1" globals "^11.1.0" "@babel/types@^7.0.0": @@ -1374,7 +1361,7 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" -"@babel/types@^7.22.10", "@babel/types@^7.22.11": +"@babel/types@^7.22.10": version "7.22.11" resolved "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz" integrity sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg== @@ -1392,6 +1379,15 @@ "@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" +"@babel/types@^7.23.0", "@babel/types@^7.24.0": + version "7.24.0" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf" + integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + "@changesets/apply-release-plan@^6.1.4": version "6.1.4" resolved "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-6.1.4.tgz" @@ -1866,7 +1862,7 @@ "@types/yargs" "^16.0.0" chalk "^4.0.0" -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": +"@jridgewell/gen-mapping@^0.3.0": version "0.3.2" resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz" integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== @@ -1875,21 +1871,35 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@3.1.0": - version "3.1.0" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" "@jridgewell/resolve-uri@^3.0.3": version "3.0.5" resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz" integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + "@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + "@jridgewell/source-map@^0.3.2": version "0.3.2" resolved "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz" @@ -1898,19 +1908,14 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@1.4.14": - version "1.4.14" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.11" resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz" integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== -"@jridgewell/sourcemap-codec@^1.4.13": +"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15": version "1.4.15" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== "@jridgewell/trace-mapping@0.3.9": @@ -1921,13 +1926,13 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.17": - version "0.3.18" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz" - integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== dependencies: - "@jridgewell/resolve-uri" "3.1.0" - "@jridgewell/sourcemap-codec" "1.4.14" + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" "@jridgewell/trace-mapping@^0.3.9": version "0.3.14" @@ -2964,12 +2969,12 @@ resolved "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz" integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= -"@rollup/plugin-alias@3.1.9": - version "3.1.9" - resolved "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-3.1.9.tgz" - integrity sha512-QI5fsEvm9bDzt32k39wpOwZhVzRcL5ydcffUHMyLVaVaLeC70I8TJZ17F1z1eMoLu4E/UOcH9BWVkKpIKdrfiw== +"@rollup/plugin-alias@5.1.0": + version "5.1.0" + resolved "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-5.1.0.tgz#99a94accc4ff9a3483be5baeedd5d7da3b597e93" + integrity sha512-lpA3RZ9PdIG7qqhEfv79tBffNaoDuukFDrmhLqg9ifv99u/ehn+lOg30x2zmhf8AQqQUZaMk/B9fZraQ6/acDQ== dependencies: - slash "^3.0.0" + slash "^4.0.0" "@rollup/plugin-commonjs@21.1.0": version "21.1.0" @@ -3062,6 +3067,18 @@ semver "~7.5.4" z-schema "~5.0.2" +"@rushstack/node-core-library@4.0.2": + version "4.0.2" + resolved "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-4.0.2.tgz#e26854a3314b279d57e8abdb4acce7797d02f554" + integrity sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg== + dependencies: + fs-extra "~7.0.1" + import-lazy "~4.0.0" + jju "~1.4.0" + resolve "~1.22.1" + semver "~7.5.4" + z-schema "~5.0.2" + "@rushstack/rig-package@0.2.9": version "0.2.9" resolved "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.2.9.tgz" @@ -3071,14 +3088,22 @@ resolve "~1.17.0" strip-json-comments "~3.1.1" -"@rushstack/ts-command-line@4.15.2": - version "4.15.2" - resolved "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.15.2.tgz" - integrity sha512-5+C2uoJY8b+odcZD6coEe2XNC4ZjGB4vCMESbqW/8DHRWC/qIHfANdmN9F1wz/lAgxz72i7xRoVtPY2j7e4gpQ== +"@rushstack/terminal@0.10.0": + version "0.10.0" + resolved "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.10.0.tgz#e81909fa0e5c8016b6df4739f0f381f44358269f" + integrity sha512-UbELbXnUdc7EKwfH2sb8ChqNgapUOdqcCIdQP4NGxBpTZV2sQyeekuK3zmfQSa/MN+/7b4kBogl2wq0vpkpYGw== + dependencies: + "@rushstack/node-core-library" "4.0.2" + supports-color "~8.1.1" + +"@rushstack/ts-command-line@4.19.1": + version "4.19.1" + resolved "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.19.1.tgz#288ee54dd607e558a8be07705869c16c31b5c3ef" + integrity sha512-J7H768dgcpG60d7skZ5uSSwyCZs/S2HrWP1Ds8d1qYAyaaeJmpmmLr9BVw97RjFzmQPOYnoXcKA4GkqDCkduQg== dependencies: + "@rushstack/terminal" "0.10.0" "@types/argparse" "1.0.38" argparse "~1.0.9" - colors "~1.2.1" string-argv "~0.3.1" "@rushstack/ts-command-line@4.7.8": @@ -3150,10 +3175,10 @@ dependencies: defer-to-connect "^2.0.0" -"@testim/chrome-version@^1.1.3": - version "1.1.3" - resolved "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.3.tgz" - integrity sha512-g697J3WxV/Zytemz8aTuKjTGYtta9+02kva3C1xc7KXB8GdbfE1akGJIsZLyY/FSh2QrnE+fiB7vmWU3XNcb6A== +"@testim/chrome-version@^1.1.4": + version "1.1.4" + resolved "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz#86e04e677cd6c05fa230dd15ac223fa72d1d7090" + integrity sha512-kIhULpw9TrGYnHp/8VfdcneIcxKnLixmADtukQRtJUmsVlMg0niMkwV0xZmi8hqa57xqilIHjWFA0GKvEjVU5g== "@tootallnate/once@1": version "1.1.2" @@ -3220,10 +3245,10 @@ resolved "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz" integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w== -"@types/chai-as-promised@7.1.5": - version "7.1.5" - resolved "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz" - integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== +"@types/chai-as-promised@7.1.8": + version "7.1.8" + resolved "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz#f2b3d82d53c59626b5d6bbc087667ccb4b677fe9" + integrity sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw== dependencies: "@types/chai" "*" @@ -3232,15 +3257,15 @@ resolved "https://registry.npmjs.org/@types/chai/-/chai-4.2.22.tgz" integrity sha512-tFfcE+DSTzWAgifkjik9AySNqIyNoYwmR+uecPwwD/XRNfvOjmC/FjCxpiUGDkDVDphPfCUecSQVFw+lN3M3kQ== -"@types/chai@4.3.5": - version "4.3.5" - resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz" - integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng== +"@types/chai@4.3.14": + version "4.3.14" + resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz#ae3055ea2be43c91c9fd700a36d67820026d96e6" + integrity sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w== -"@types/child-process-promise@2.2.2": - version "2.2.2" - resolved "https://registry.npmjs.org/@types/child-process-promise/-/child-process-promise-2.2.2.tgz" - integrity sha512-4eGTIhKW0jb9DlS81Fgo/UyZ12DMhDhz3Ec8tdHW53l4ubteynNIuy7Z1HNnyHn1jTzXa/o9iX0WoAdiSoDs+Q== +"@types/child-process-promise@2.2.6": + version "2.2.6" + resolved "https://registry.npmjs.org/@types/child-process-promise/-/child-process-promise-2.2.6.tgz#3936229dd9c88d14a52cb05a061d9a67f0d0374e" + integrity sha512-g0pOHijr6Trug43D2bV0PLSIsSHa/xHEES2HeX5BAlduq1vW0nZcq27Zeud5lgmNB+kPYYVqiMap32EHGTco/w== dependencies: "@types/node" "*" @@ -3331,10 +3356,10 @@ "@types/qs" "*" "@types/range-parser" "*" -"@types/express@4.17.17": - version "4.17.17" - resolved "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz" - integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== +"@types/express@4.17.21": + version "4.17.21" + resolved "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "^4.17.33" @@ -3368,10 +3393,10 @@ resolved "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz" integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== -"@types/inquirer@8.2.6": - version "8.2.6" - resolved "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.6.tgz" - integrity sha512-3uT88kxg8lNzY8ay2ZjP44DKcRaTGztqeIvN2zHvhzIBH/uAPaL75aBtdNRKbA7xXoMbBt5kX0M00VKAnfOYlA== +"@types/inquirer@8.2.10": + version "8.2.10" + resolved "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.10.tgz#9444dce2d764c35bc5bb4d742598aaa4acb6561b" + integrity sha512-IdD5NmHyVjWM8SHWo/kPBgtzXatwPkfwzyP3fN1jF2g9BWt5WO+8hL2F4o2GKIYsU40PpqeevuUWvkS/roXJkA== dependencies: "@types/through" "*" rxjs "^7.2.0" @@ -3402,10 +3427,10 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/js-yaml@4.0.5": - version "4.0.5" - resolved "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz" - integrity sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA== +"@types/js-yaml@4.0.9": + version "4.0.9" + resolved "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz#cd82382c4f902fed9691a2ed79ec68c5898af4c2" + integrity sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg== "@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.8": version "7.0.9" @@ -3417,10 +3442,10 @@ resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== -"@types/json-stable-stringify@1.0.34": - version "1.0.34" - resolved "https://registry.npmjs.org/@types/json-stable-stringify/-/json-stable-stringify-1.0.34.tgz" - integrity sha512-s2cfwagOQAS8o06TcwKfr9Wx11dNGbH2E9vJz1cqV+a/LOyhWNLUNd6JSRYNzvB4d29UuJX2M0Dj9vE1T8fRXw== +"@types/json-stable-stringify@1.0.36": + version "1.0.36" + resolved "https://registry.npmjs.org/@types/json-stable-stringify/-/json-stable-stringify-1.0.36.tgz#fe6c6001a69ff8160a772da08779448a333c7ddd" + integrity sha512-b7bq23s4fgBB76n34m2b3RBf6M369B0Z9uRR8aHTMd8kZISRkmDEpPD8hhpYvDFzr3bJCPES96cm3Q6qRNDbQw== "@types/json5@^0.0.29": version "0.0.29" @@ -3434,10 +3459,10 @@ dependencies: "@types/node" "*" -"@types/listr@0.14.4": - version "0.14.4" - resolved "https://registry.npmjs.org/@types/listr/-/listr-0.14.4.tgz" - integrity sha512-+MWvidNujBUgJsi4yMVwEQQwaHe6oHedPSy+dwk3akGEeuIbvhWkK+TGsXSwbFup7Y0cCBb+wzzdD+yGKp7sOg== +"@types/listr@0.14.9": + version "0.14.9" + resolved "https://registry.npmjs.org/@types/listr/-/listr-0.14.9.tgz#736581cfdfcdb821bace0a3e5b05e91182e00c85" + integrity sha512-Ncsy/jtO/HZYrupLGcnp1BOswZVsNvggjIjnf2EZ1xECfU4hxcQ3FWvFEyR+/DXssz0HDm74Op/tEsyrB3eV5w== dependencies: "@types/node" "*" rxjs "^6.5.1" @@ -3472,10 +3497,10 @@ resolved "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz" integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== -"@types/mz@2.7.4": - version "2.7.4" - resolved "https://registry.npmjs.org/@types/mz/-/mz-2.7.4.tgz" - integrity sha512-Zs0imXxyWT20j3Z2NwKpr0IO2LmLactBblNyLua5Az4UHuqOQ02V3jPTgyKwDkuc33/ahw+C3O1PIZdrhFMuQA== +"@types/mz@2.7.8": + version "2.7.8" + resolved "https://registry.npmjs.org/@types/mz/-/mz-2.7.8.tgz#5ac05b34f08e6225d7ad9b05e158b03d9ca9e2d4" + integrity sha512-mGLNqqwt8yu4pDw9rEphAiyWnEdok0GzOGrwi5EiTuDFxw7H3ZaEI4ASFKq4HaZtemtjQ8MkcmtWcrU4V0WkIw== dependencies: "@types/node" "*" @@ -3556,10 +3581,10 @@ resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== -"@types/request@2.48.8": - version "2.48.8" - resolved "https://registry.npmjs.org/@types/request/-/request-2.48.8.tgz" - integrity sha512-whjk1EDJPcAR2kYHRbFl/lKeeKYTi05A15K9bnLInCVroNDCtXce57xKdI0/rQaA3K+6q0eFyUBPmqfSndUZdQ== +"@types/request@2.48.12": + version "2.48.12" + resolved "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz#0f590f615a10f87da18e9790ac94c29ec4c5ef30" + integrity sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw== dependencies: "@types/caseless" "*" "@types/node" "*" @@ -3573,10 +3598,10 @@ dependencies: "@types/node" "*" -"@types/resolve@1.20.2": - version "1.20.2" - resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz" - integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== +"@types/resolve@1.20.6": + version "1.20.6" + resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz#e6e60dad29c2c8c206c026e6dd8d6d1bdda850b8" + integrity sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ== "@types/responselike@*", "@types/responselike@^1.0.0": version "1.0.0" @@ -3608,10 +3633,10 @@ "@types/mime" "*" "@types/node" "*" -"@types/sinon-chai@3.2.9": - version "3.2.9" - resolved "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.9.tgz" - integrity sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ== +"@types/sinon-chai@3.2.12": + version "3.2.12" + resolved "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.12.tgz#c7cb06bee44a534ec84f3a5534c3a3a46fd779b6" + integrity sha512-9y0Gflk3b0+NhQZ/oxGtaAJDvRywCa5sIyaVnounqLvmf93yBF4EgIRspePtkMs3Tr844nCclYMlcCNmLCvjuQ== dependencies: "@types/chai" "*" "@types/sinon" "*" @@ -3647,20 +3672,20 @@ dependencies: "@types/node" "*" -"@types/tmp@0.2.3": - version "0.2.3" - resolved "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.3.tgz" - integrity sha512-dDZH/tXzwjutnuk4UacGgFRwV+JSLaXL1ikvidfJprkb7L9Nx1njcRHHmi3Dsvt7pgqqTEeucQuOrWHPFgzVHA== +"@types/tmp@0.2.6": + version "0.2.6" + resolved "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.6.tgz#d785ee90c52d7cc020e249c948c36f7b32d1e217" + integrity sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA== "@types/tough-cookie@*": version "4.0.1" resolved "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.1.tgz" integrity sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg== -"@types/trusted-types@2.0.3": - version "2.0.3" - resolved "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz" - integrity sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g== +"@types/trusted-types@2.0.7": + version "2.0.7" + resolved "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" + integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw== "@types/vinyl@^2.0.4": version "2.0.6" @@ -3670,10 +3695,10 @@ "@types/expect" "^1.20.4" "@types/node" "*" -"@types/webpack@5.28.0": - version "5.28.0" - resolved "https://registry.npmjs.org/@types/webpack/-/webpack-5.28.0.tgz" - integrity sha512-8cP0CzcxUiFuA9xGJkfeVpqmWTk9nx6CWwamRGCj95ph1SmlRRk9KlCZ6avhCbZd4L68LvYT6l1kpdEnQXrF8w== +"@types/webpack@5.28.5": + version "5.28.5" + resolved "https://registry.npmjs.org/@types/webpack/-/webpack-5.28.5.tgz#0e9d9a15efa09bbda2cef41356ca4ac2031ea9a2" + integrity sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw== dependencies: "@types/node" "*" tapable "^2.2.0" @@ -3684,10 +3709,10 @@ resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz" integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== -"@types/yargs@17.0.24": - version "17.0.24" - resolved "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz" - integrity sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw== +"@types/yargs@17.0.32": + version "17.0.32" + resolved "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" + integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== dependencies: "@types/yargs-parser" "*" @@ -4440,6 +4465,14 @@ arr-union@^3.1.0: resolved "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +array-buffer-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" + integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== + dependencies: + call-bind "^1.0.5" + is-array-buffer "^3.0.4" + array-differ@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz" @@ -4471,14 +4504,15 @@ array-ify@^1.0.0: integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= array-includes@^3.1.4: - version "3.1.5" - resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz" - integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - get-intrinsic "^1.1.1" + version "3.1.8" + resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" + integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" is-string "^1.0.7" array-initial@^1.0.0: @@ -4532,7 +4566,7 @@ array-unique@^0.3.2: resolved "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -array.prototype.flat@^1.2.3, array.prototype.flat@^1.2.5: +array.prototype.flat@^1.2.3: version "1.3.0" resolved "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz" integrity sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw== @@ -4542,6 +4576,30 @@ array.prototype.flat@^1.2.3, array.prototype.flat@^1.2.5: es-abstract "^1.19.2" es-shim-unscopables "^1.0.0" +array.prototype.flat@^1.2.5: + version "1.3.2" + resolved "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +arraybuffer.prototype.slice@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" + integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== + dependencies: + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.2.1" + get-intrinsic "^1.2.3" + is-array-buffer "^3.0.4" + is-shared-array-buffer "^1.0.2" + arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz" @@ -4562,6 +4620,15 @@ asap@^2.0.0: resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= +asn1.js@^4.10.1: + version "4.10.1" + resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + asn1.js@^5.2.0: version "5.4.1" resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz" @@ -4682,6 +4749,13 @@ available-typed-arrays@^1.0.5: resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz" @@ -4692,12 +4766,12 @@ aws4@^1.8.0: resolved "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -axios@^1.4.0: - version "1.5.0" - resolved "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz" - integrity sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ== +axios@^1.6.0: + version "1.6.8" + resolved "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66" + integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ== dependencies: - follow-redirects "^1.15.0" + follow-redirects "^1.15.6" form-data "^4.0.0" proxy-from-env "^1.1.0" @@ -4987,11 +5061,16 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.1.1: +bn.js@^5.0.0: version "5.2.0" resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz" integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + body-parser@1.19.0, body-parser@^1.18.3, body-parser@^1.19.0: version "1.19.0" resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz" @@ -5008,13 +5087,13 @@ body-parser@1.19.0, body-parser@^1.18.3, body-parser@^1.19.0: raw-body "2.4.0" type-is "~1.6.17" -body-parser@1.20.1: - version "1.20.1" - resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz" - integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== +body-parser@1.20.2: + version "1.20.2" + resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" + integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== dependencies: bytes "3.1.2" - content-type "~1.0.4" + content-type "~1.0.5" debug "2.6.9" depd "2.0.0" destroy "1.2.0" @@ -5022,7 +5101,7 @@ body-parser@1.20.1: iconv-lite "0.4.24" on-finished "2.4.1" qs "6.11.0" - raw-body "2.5.1" + raw-body "2.5.2" type-is "~1.6.18" unpipe "1.0.0" @@ -5102,7 +5181,7 @@ browser-stdout@1.3.1: resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -browserify-aes@^1.0.0, browserify-aes@^1.0.4: +browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== @@ -5133,7 +5212,7 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: +browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz" integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== @@ -5142,19 +5221,20 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: randombytes "^2.0.1" browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + version "4.2.3" + resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz#7afe4c01ec7ee59a89a558a4b75bd85ae62d4208" + integrity sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw== dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" + bn.js "^5.2.1" + browserify-rsa "^4.1.0" create-hash "^1.2.0" create-hmac "^1.1.7" - elliptic "^6.5.3" + elliptic "^6.5.5" + hash-base "~3.0" inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" + parse-asn1 "^5.1.7" + readable-stream "^2.3.8" + safe-buffer "^5.2.1" browserify-zlib@^0.2.0: version "0.2.0" @@ -5184,6 +5264,16 @@ browserslist@^4.21.10, browserslist@^4.21.9: node-releases "^2.0.13" update-browserslist-db "^1.0.11" +browserslist@^4.22.2: + version "4.23.0" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" + integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== + dependencies: + caniuse-lite "^1.0.30001587" + electron-to-chromium "^1.4.668" + node-releases "^2.0.14" + update-browserslist-db "^1.0.13" + browserstack@^1.5.1: version "1.6.1" resolved "https://registry.npmjs.org/browserstack/-/browserstack-1.6.1.tgz" @@ -5383,6 +5473,17 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" +call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz" @@ -5417,15 +5518,10 @@ camelcase@^6.0.0, camelcase@^6.2.0: resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz" integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== -caniuse-lite@^1.0.30001259: - version "1.0.30001429" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001429.tgz" - integrity sha512-511ThLu1hF+5RRRt0zYCf2U2yRr9GPF6m5y90SBCWsvSoYoW7yAGlv/elyPaNfvGCkp6kj/KFZWU0BMA69Prsg== - -caniuse-lite@^1.0.30001517: - version "1.0.30001524" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001524.tgz" - integrity sha512-Jj917pJtYg9HSJBF95HVX3Cdr89JUyLT4IZ8SvM5aDRni95swKgYi3TgYLH5hnGfPE/U1dg6IfZ50UsIlLkwSA== +caniuse-lite@^1.0.30001259, caniuse-lite@^1.0.30001517, caniuse-lite@^1.0.30001587: + version "1.0.30001611" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001611.tgz" + integrity sha512-19NuN1/3PjA3QI8Eki55N8my4LzfkMCRLgCVfrl/slbSAchQfV0+GwjPrK3rq37As4UCLlM/DHajbKkAqbv92Q== cardinal@^2.1.1: version "2.1.1" @@ -5454,20 +5550,20 @@ chai-exclude@2.1.0: dependencies: fclone "^1.0.11" -chai@4.3.7: - version "4.3.7" - resolved "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz" - integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== +chai@4.4.1: + version "4.4.1" + resolved "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz#3603fa6eba35425b0f2ac91a009fe924106e50d1" + integrity sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g== dependencies: assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^4.1.2" - get-func-name "^2.0.0" - loupe "^2.3.1" + check-error "^1.0.3" + deep-eql "^4.1.3" + get-func-name "^2.0.2" + loupe "^2.3.6" pathval "^1.1.1" - type-detect "^4.0.5" + type-detect "^4.0.8" -chalk@4.1.2, chalk@4.x, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: +chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: version "4.1.2" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -5510,6 +5606,13 @@ check-error@^1.0.2: resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= +check-error@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" + integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== + dependencies: + get-func-name "^2.0.2" + child-process-promise@2.2.1: version "2.2.1" resolved "https://registry.npmjs.org/child-process-promise/-/child-process-promise-2.2.1.tgz" @@ -5583,18 +5686,18 @@ chrome-trace-event@^1.0.2: resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz" integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== -chromedriver@114.0.2: - version "114.0.2" - resolved "https://registry.npmjs.org/chromedriver/-/chromedriver-114.0.2.tgz" - integrity sha512-v0qrXRBknbxqmtklG7RWOe3TJ/dLaHhtB0jVxE7BAdYERxUjEaNRyqBwoGgVfQDibHCB0swzvzsj158nnfPgZw== +chromedriver@119.0.1: + version "119.0.1" + resolved "https://registry.npmjs.org/chromedriver/-/chromedriver-119.0.1.tgz#064f3650790ccea055e9bfd95c600f5ea60295e9" + integrity sha512-lpCFFLaXPpvElTaUOWKdP74pFb/sJhWtWqMjn7Ju1YriWn8dT5JBk84BGXMPvZQs70WfCYWecxdMmwfIu1Mupg== dependencies: - "@testim/chrome-version" "^1.1.3" - axios "^1.4.0" - compare-versions "^5.0.3" + "@testim/chrome-version" "^1.1.4" + axios "^1.6.0" + compare-versions "^6.1.0" extract-zip "^2.0.1" https-proxy-agent "^5.0.1" proxy-from-env "^1.1.0" - tcp-port-used "^1.0.1" + tcp-port-used "^1.0.2" ci-info@^2.0.0: version "2.0.0" @@ -5780,6 +5883,10 @@ cloneable-readable@^1.0.0: process-nextick-args "^2.0.0" readable-stream "^2.3.5" +"closure-net@git+https://github.com/google/closure-net.git#0412666": + version "0.0.0" + resolved "git+https://github.com/google/closure-net.git#0412666e8f29b8ae69decb1fdc7ead635a5cf43e" + cmd-shim@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/cmd-shim/-/cmd-shim-4.1.0.tgz" @@ -5955,10 +6062,10 @@ compare-func@^2.0.0: array-ify "^1.0.0" dot-prop "^5.1.0" -compare-versions@^5.0.3: - version "5.0.3" - resolved "https://registry.npmjs.org/compare-versions/-/compare-versions-5.0.3.tgz" - integrity sha512-4UZlZP8Z99MGEY+Ovg/uJxJuvoXuN4M6B3hKaiackiHrgzQFEe3diJi1mf1PNHbFujM7FvLrK2bpgIaImbtZ1A== +compare-versions@^6.1.0: + version "6.1.0" + resolved "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz#3f2131e3ae93577df111dba133e6db876ffe127a" + integrity sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg== component-emitter@^1.2.1, component-emitter@~1.3.0: version "1.3.0" @@ -6084,6 +6191,11 @@ content-type@^1.0.4, content-type@~1.0.4: resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== +content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + conventional-changelog-angular@^5.0.12: version "5.0.13" resolved "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz" @@ -6173,6 +6285,11 @@ convert-source-map@^1.0.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, dependencies: safe-buffer "~5.1.1" +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + convert-source-map@~1.1.0: version "1.1.3" resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz" @@ -6188,10 +6305,10 @@ cookie@0.4.0: resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz" integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== -cookie@0.5.0: - version "0.5.0" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== +cookie@0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== cookie@~0.4.1: version "0.4.1" @@ -6438,6 +6555,14 @@ d@1, d@^1.0.1: es5-ext "^0.10.50" type "^1.0.1" +d@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/d/-/d-1.0.2.tgz#2aefd554b81981e7dccf72d6842ae725cb17e5de" + integrity sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw== + dependencies: + es5-ext "^0.10.64" + type "^2.7.2" + dargs@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz" @@ -6455,6 +6580,33 @@ data-uri-to-buffer@3: resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz" integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og== +data-view-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" + integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" + integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" + integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + dataloader@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz" @@ -6491,7 +6643,7 @@ debug-fabulous@^1.0.0: debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" - resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" @@ -6564,9 +6716,9 @@ dedent@^0.7.0: resolved "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= -deep-eql@^4.1.2: +deep-eql@^4.1.3: version "4.1.3" - resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz" + resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== dependencies: type-detect "^4.0.0" @@ -6622,6 +6774,15 @@ defer-to-connect@^2.0.0: resolved "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + define-properties@^1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" @@ -6637,6 +6798,15 @@ define-properties@^1.1.4: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +define-properties@^1.2.0, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + define-property@^0.2.5: version "0.2.5" resolved "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz" @@ -6936,6 +7106,11 @@ electron-to-chromium@^1.4.477: resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.505.tgz" integrity sha512-0A50eL5BCCKdxig2SsCXhpuztnB9PfUgRMojj5tMvt8O54lbwz3t6wNgnpiTRosw5QjlJB7ixhVyeg8daLQwSQ== +electron-to-chromium@^1.4.668: + version "1.4.722" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.722.tgz#99ae3484c5fc0f387d39ad98d77e1f259b9f4074" + integrity sha512-5nLE0TWFFpZ80Crhtp4pIp8LXCztjYX41yUcV6b+bKR2PqzjskTMOOlBi1VjBHlvHwS+4gar7kNKOrsbsewEZQ== + elegant-spinner@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz" @@ -6954,6 +7129,19 @@ elliptic@^6.5.3: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +elliptic@^6.5.5: + version "6.5.5" + resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.5.tgz#c715e09f78b6923977610d4c2346d6ce22e6dded" + integrity sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz" @@ -7016,14 +7204,13 @@ engine.io@~6.2.0: engine.io-parser "~5.0.3" ws "~8.2.3" -enhanced-resolve@^4.0.0: - version "4.5.0" - resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz" - integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== +enhanced-resolve@^5.0.0: + version "5.16.0" + resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz#65ec88778083056cb32487faa9aef82ed0864787" + integrity sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA== dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.5.0" - tapable "^1.0.0" + graceful-fs "^4.2.4" + tapable "^2.2.0" enhanced-resolve@^5.10.0: version "5.15.0" @@ -7106,7 +7293,7 @@ es-abstract@^1.18.0-next.2, es-abstract@^1.18.5: string.prototype.trimstart "^1.0.4" unbox-primitive "^1.0.1" -es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5: +es-abstract@^1.19.0, es-abstract@^1.19.2, es-abstract@^1.19.5: version "1.20.0" resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.0.tgz" integrity sha512-URbD8tgRthKD3YcC39vbvSDrX23upXnPcnGAjQfgxXF5ID75YcENawc9ZX/9iTP9ptUyfCLIxTTuMYoRfiOVKA== @@ -7135,6 +7322,70 @@ es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19 string.prototype.trimstart "^1.0.5" unbox-primitive "^1.0.2" +es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2: + version "1.23.3" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" + integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== + dependencies: + array-buffer-byte-length "^1.0.1" + arraybuffer.prototype.slice "^1.0.3" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + data-view-buffer "^1.0.1" + data-view-byte-length "^1.0.1" + data-view-byte-offset "^1.0.0" + es-define-property "^1.0.0" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-set-tostringtag "^2.0.3" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.4" + get-symbol-description "^1.0.2" + globalthis "^1.0.3" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" + has-symbols "^1.0.3" + hasown "^2.0.2" + internal-slot "^1.0.7" + is-array-buffer "^3.0.4" + is-callable "^1.2.7" + is-data-view "^1.0.1" + is-negative-zero "^2.0.3" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.3" + is-string "^1.0.7" + is-typed-array "^1.1.13" + is-weakref "^1.0.2" + object-inspect "^1.13.1" + object-keys "^1.1.1" + object.assign "^4.1.5" + regexp.prototype.flags "^1.5.2" + safe-array-concat "^1.1.2" + safe-regex-test "^1.0.3" + string.prototype.trim "^1.2.9" + string.prototype.trimend "^1.0.8" + string.prototype.trimstart "^1.0.8" + typed-array-buffer "^1.0.2" + typed-array-byte-length "^1.0.1" + typed-array-byte-offset "^1.0.2" + typed-array-length "^1.0.6" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.15" + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.2.1, es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + es-module-lexer@^0.7.1: version "0.7.1" resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.7.1.tgz" @@ -7145,6 +7396,22 @@ es-module-lexer@^0.9.0: resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz" integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es-object-atoms@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" + integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" + integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== + dependencies: + get-intrinsic "^1.2.4" + has-tostringtag "^1.0.2" + hasown "^2.0.1" + es-shim-unscopables@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz" @@ -7161,21 +7428,22 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: - version "0.10.53" - resolved "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz" - integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@^0.10.62, es5-ext@^0.10.64, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: + version "0.10.64" + resolved "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz#12e4ffb48f1ba2ea777f1fcdd1918ef73ea21714" + integrity sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg== dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.3" - next-tick "~1.0.0" + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + esniff "^2.0.1" + next-tick "^1.1.0" es6-error@^4.0.1: version "4.1.1" resolved "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== -es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.3: +es6-iterator@^2.0.1, es6-iterator@^2.0.3: version "2.0.3" resolved "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz" integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= @@ -7201,7 +7469,7 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" -es6-symbol@^3.1.1, es6-symbol@~3.1.3: +es6-symbol@^3.1.1: version "3.1.3" resolved "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz" integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== @@ -7209,6 +7477,14 @@ es6-symbol@^3.1.1, es6-symbol@~3.1.3: d "^1.0.1" ext "^1.1.2" +es6-symbol@^3.1.3: + version "3.1.4" + resolved "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz#f4e7d28013770b4208ecbf3e0bf14d3bcb557b8c" + integrity sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg== + dependencies: + d "^1.0.2" + ext "^1.7.0" + es6-weak-map@^2.0.1, es6-weak-map@^2.0.3: version "2.0.3" resolved "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz" @@ -7262,24 +7538,24 @@ escodegen@^1.8.1: source-map "~0.6.1" eslint-import-resolver-node@^0.3.6: - version "0.3.6" - resolved "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz" - integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== + version "0.3.9" + resolved "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== dependencies: debug "^3.2.7" - resolve "^1.20.0" + is-core-module "^2.13.0" + resolve "^1.22.4" eslint-module-utils@^2.7.3: - version "2.7.3" - resolved "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz" - integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ== + version "2.8.1" + resolved "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz#52f2404300c3bd33deece9d7372fb337cc1d7c34" + integrity sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q== dependencies: debug "^3.2.7" - find-up "^2.1.0" eslint-plugin-import@2.26.0: version "2.26.0" - resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz" + resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b" integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA== dependencies: array-includes "^3.1.4" @@ -7384,6 +7660,16 @@ eslint@7.32.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" +esniff@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308" + integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg== + dependencies: + d "^1.0.1" + es5-ext "^0.10.62" + event-emitter "^0.3.5" + type "^2.7.2" + espree@^7.3.0, espree@^7.3.1: version "7.3.1" resolved "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz" @@ -7582,17 +7868,17 @@ expect@^27.2.1: jest-message-util "^27.2.0" jest-regex-util "^27.0.6" -express@4.18.2: - version "4.18.2" - resolved "https://registry.npmjs.org/express/-/express-4.18.2.tgz" - integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== +express@4.19.2: + version "4.19.2" + resolved "https://registry.npmjs.org/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" + integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.1" + body-parser "1.20.2" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.5.0" + cookie "0.6.0" cookie-signature "1.0.6" debug "2.6.9" depd "2.0.0" @@ -7662,6 +7948,13 @@ ext@^1.1.2: dependencies: type "^2.5.0" +ext@^1.7.0: + version "1.7.0" + resolved "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" @@ -7979,7 +8272,7 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -find-up@^2.0.0, find-up@^2.1.0: +find-up@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= @@ -8154,15 +8447,17 @@ fn.name@1.x.x: resolved "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.0.0: - version "1.14.4" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz" - integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g== +follow-redirects@^1.0.0, follow-redirects@^1.15.6: + version "1.15.6" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== -follow-redirects@^1.15.0: - version "1.15.2" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" @@ -8370,6 +8665,11 @@ function-bind@^1.1.1: resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + function.prototype.name@^1.1.5: version "1.1.5" resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz" @@ -8380,12 +8680,22 @@ function.prototype.name@^1.1.5: es-abstract "^1.19.0" functions-have-names "^1.2.2" +function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -functions-have-names@^1.2.2: +functions-have-names@^1.2.2, functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== @@ -8496,10 +8806,10 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= +get-func-name@^2.0.1, get-func-name@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1" @@ -8510,6 +8820,17 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" +get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" @@ -8550,6 +8871,15 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" +get-symbol-description@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" + integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== + dependencies: + call-bind "^1.0.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + get-uri@3: version "3.0.2" resolved "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz" @@ -8765,6 +9095,13 @@ globals@^9.18.0: resolved "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + globby@10.0.1: version "10.0.1" resolved "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz" @@ -8852,45 +9189,6 @@ google-auth-library@^8.0.2: jws "^4.0.0" lru-cache "^6.0.0" -google-closure-compiler-java@^20230228.0.0: - version "20230228.0.0" - resolved "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20230228.0.0.tgz" - integrity sha512-t0sXYJbhfkuNTF6zniwrTv4gLap620D32v6GwBJQzlYUg0lb7yQHN9KswwqBsuuO917cPNwW4okI0O40G7GrMQ== - -google-closure-compiler-linux@^20230228.0.0: - version "20230228.0.0" - resolved "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20230228.0.0.tgz#17cb6187015e0e2ae8c2dd5b560228fdf5625818" - integrity sha512-5YLxfWS8lvHkD/a0+pitTuDV1X9QPBToGQ5mnLFg7HcbBR1w6I5ZKHjl7FAsAOHEXYwIrStwwaLzrNzbolrZLg== - -google-closure-compiler-osx@^20230228.0.0: - version "20230228.0.0" - resolved "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20230228.0.0.tgz" - integrity sha512-ORveHpHuNhJEJIGir35+xP4UuBOldSO8XeOwJV5yunUhZAPzR4aixdTdtm6i0GsqW4/Eu2cjcHrkIR3eFCcwSg== - -google-closure-compiler-windows@^20230228.0.0: - version "20230228.0.0" - resolved "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20230228.0.0.tgz#dff4afcd6d21a831b38a9bdb873eed0daca79807" - integrity sha512-xKMjUq6JwEOFqS97S86TWkn+BMiDHjP85mMgAmR8vRmKxgfHIyxMcr+RlMz0msgY9jedgj119KXyOe32lIQTjA== - -google-closure-compiler@20230228.0.0: - version "20230228.0.0" - resolved "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20230228.0.0.tgz" - integrity sha512-jFI4QNZgM4WhNIoaRNwA5kHq6n6NKSWZj3N9HgRsJE9bN4LUrkIURI+svChbEp/WmGh3Bt3o3/5kUlOOWyCo3Q== - dependencies: - chalk "4.x" - google-closure-compiler-java "^20230228.0.0" - minimist "1.x" - vinyl "2.x" - vinyl-sourcemaps-apply "^0.2.0" - optionalDependencies: - google-closure-compiler-linux "^20230228.0.0" - google-closure-compiler-osx "^20230228.0.0" - google-closure-compiler-windows "^20230228.0.0" - -"google-closure-library@git+https://github.com/google/closure-library.git#7818ff7": - version "20230802.0.0" - resolved "git+https://git@github.com/google/closure-library.git#7818ff7dc0b53555a7fb3c3427e6761e88bde3a2" - google-gax@^3.0.1: version "3.1.3" resolved "https://registry.npmjs.org/google-gax/-/google-gax-3.1.3.tgz" @@ -8924,6 +9222,13 @@ google-p12-pem@^4.0.0: dependencies: node-forge "^1.3.1" +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + got@11.8.2: version "11.8.2" resolved "https://registry.npmjs.org/got/-/got-11.8.2.tgz" @@ -9144,6 +9449,18 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1, has-proto@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + has-symbols@^1.0.1, has-symbols@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz" @@ -9161,6 +9478,13 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + has-unicode@^2.0.0, has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" @@ -9218,6 +9542,14 @@ hash-base@^3.0.0: readable-stream "^3.6.0" safe-buffer "^5.2.0" +hash-base@~3.0: + version "3.0.4" + resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" @@ -9234,6 +9566,13 @@ hasha@^5.0.0: is-stream "^2.0.0" type-fest "^0.8.0" +hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + he@1.2.0, he@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" @@ -9285,9 +9624,9 @@ html-escaper@^2.0.0: integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + version "4.1.1" + resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== http-errors@1.7.2: version "1.7.2" @@ -9672,6 +10011,15 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" +internal-slot@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" + integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== + dependencies: + es-errors "^1.3.0" + hasown "^2.0.0" + side-channel "^1.0.4" + interpret@^1.0.0, interpret@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" @@ -9695,14 +10043,14 @@ ip-regex@^4.1.0: integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== ip@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= + version "1.1.9" + resolved "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz#8dfbcc99a754d07f425310b86a99546b1151e396" + integrity sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ== ip@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz" - integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== + version "2.0.1" + resolved "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105" + integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ== ipaddr.js@1.9.1: version "1.9.1" @@ -9739,6 +10087,14 @@ is-arguments@^1.0.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-array-buffer@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" + integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" @@ -9790,6 +10146,11 @@ is-builtin-module@^3.1.0: dependencies: builtin-modules "^3.0.0" +is-callable@^1.1.3, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + is-callable@^1.1.4, is-callable@^1.2.4: version "1.2.4" resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz" @@ -9851,6 +10212,13 @@ is-data-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-data-view@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" + integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== + dependencies: + is-typed-array "^1.1.13" + is-date-object@^1.0.1: version "1.0.5" resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" @@ -9994,6 +10362,11 @@ is-negative-zero@^2.0.2: resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== +is-negative-zero@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" + integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== + is-npm@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz" @@ -10125,6 +10498,13 @@ is-shared-array-buffer@^1.0.2: dependencies: call-bind "^1.0.2" +is-shared-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" + integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== + dependencies: + call-bind "^1.0.7" + is-ssh@^1.3.0: version "1.3.3" resolved "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.3.tgz" @@ -10175,6 +10555,13 @@ is-text-path@^1.0.1: dependencies: text-extensions "^1.0.0" +is-typed-array@^1.1.13: + version "1.1.13" + resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" + integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== + dependencies: + which-typed-array "^1.1.14" + is-typed-array@^1.1.3, is-typed-array@^1.1.7: version "1.1.8" resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz" @@ -10266,6 +10653,11 @@ isarray@1.0.0, isarray@~1.0.0: resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + isbinaryfile@^4.0.8: version "4.0.8" resolved "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz" @@ -10738,33 +11130,29 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -json-stable-stringify@1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz" - integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== +json-stable-stringify@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz#52d4361b47d49168bcc4e564189a42e5a7439454" + integrity sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg== dependencies: + call-bind "^1.0.5" + isarray "^2.0.5" jsonify "^0.0.1" + object-keys "^1.1.1" json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== +json5@^1.0.1, json5@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" - -json5@^2.2.3: +json5@^2.1.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -10820,19 +11208,9 @@ jssha@^3.1.2: resolved "https://registry.npmjs.org/jssha/-/jssha-3.3.0.tgz" integrity sha512-w9OtT4ALL+fbbwG3gw7erAO0jvS5nfvrukGPMWIAoea359B26ALXGpzy4YJSp9yGnpUvuvOw1nSjSoHDfWSr1w== -jszip@^3.1.3, jszip@^3.6.0: - version "3.7.1" - resolved "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz" - integrity sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg== - dependencies: - lie "~3.3.0" - pako "~1.0.2" - readable-stream "~2.3.6" - set-immediate-shim "~1.0.1" - -jszip@^3.10.0: +jszip@^3.1.3, jszip@^3.10.0, jszip@^3.6.0: version "3.10.1" - resolved "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz" + resolved "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== dependencies: lie "~3.3.0" @@ -10914,13 +11292,13 @@ karma-coverage-istanbul-reporter@3.0.3: istanbul-reports "^3.0.2" minimatch "^3.0.4" -karma-firefox-launcher@2.1.2: - version "2.1.2" - resolved "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-2.1.2.tgz" - integrity sha512-VV9xDQU1QIboTrjtGVD4NCfzIH7n01ZXqy/qpBhnOeGVOkG5JYPEm8kuSd7psHE6WouZaQ9Ool92g8LFweSNMA== +karma-firefox-launcher@2.1.3: + version "2.1.3" + resolved "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-2.1.3.tgz#b278a4cbffa92ab81394b1a398813847b0624a85" + integrity sha512-LMM2bseebLbYjODBOVt7TCPP9OI2vZIXCavIXhkO9m+10Uj5l7u/SKoeRmYx8FYHTVGZSpk6peX+3BMHC1WwNw== dependencies: is-wsl "^2.2.0" - which "^2.0.1" + which "^3.0.0" karma-mocha-reporter@2.2.5: version "2.2.5" @@ -10950,13 +11328,6 @@ karma-sourcemap-loader@0.4.0: dependencies: graceful-fs "^4.2.10" -karma-spec-reporter@0.0.34: - version "0.0.34" - resolved "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.34.tgz" - integrity sha512-l5H/Nh9q4g2Ysx2CDU2m+NIPyLQpCVbk9c4V02BTZHw3NM6RO1dq3eRpKXCSSdPt4RGfhHk8jDt3XYkGp+5PWg== - dependencies: - colors "1.4.0" - karma-spec-reporter@0.0.36: version "0.0.36" resolved "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.36.tgz" @@ -11616,12 +11987,12 @@ loose-envify@^1.0.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -loupe@^2.3.1: - version "2.3.4" - resolved "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz" - integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== +loupe@^2.3.6: + version "2.3.7" + resolved "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" + integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== dependencies: - get-func-name "^2.0.0" + get-func-name "^2.0.1" lowercase-keys@^2.0.0: version "2.0.0" @@ -11674,12 +12045,12 @@ magic-string@^0.25.2, magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.4" -magic-string@^0.30.0: - version "0.30.0" - resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz" - integrity sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ== +magic-string@^0.30.2: + version "0.30.8" + resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz#14e8624246d2bedba70d5462aa99ac9681844613" + integrity sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ== dependencies: - "@jridgewell/sourcemap-codec" "^1.4.13" + "@jridgewell/sourcemap-codec" "^1.4.15" magic-string@~0.26.2: version "0.26.7" @@ -12101,7 +12472,7 @@ minimist-options@4.1.0, minimist-options@^4.0.2: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@1.x, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: +minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: version "1.2.5" resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -12438,11 +12809,6 @@ next-tick@1, next-tick@^1.1.0: resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz" integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== -next-tick@~1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= - nice-try@^1.0.4: version "1.0.5" resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz" @@ -12625,6 +12991,11 @@ node-releases@^2.0.13: resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz" integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== +node-releases@^2.0.14: + version "2.0.14" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== + node-version@^1.0.0: version "1.2.0" resolved "https://registry.npmjs.org/node-version/-/node-version-1.2.0.tgz" @@ -12913,6 +13284,11 @@ object-inspect@^1.12.0: resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz" integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== +object-inspect@^1.13.1: + version "1.13.1" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + object-is@^1.0.1: version "1.1.5" resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz" @@ -12943,6 +13319,16 @@ object.assign@^4.0.4, object.assign@^4.1.0, object.assign@^4.1.2: has-symbols "^1.0.1" object-keys "^1.1.1" +object.assign@^4.1.5: + version "4.1.5" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" + integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== + dependencies: + call-bind "^1.0.5" + define-properties "^1.2.1" + has-symbols "^1.0.3" + object-keys "^1.1.1" + object.defaults@^1.0.0, object.defaults@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz" @@ -12986,13 +13372,13 @@ object.reduce@^1.0.0: make-iterator "^1.0.0" object.values@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz" - integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== + version "1.2.0" + resolved "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" + integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" on-finished@2.4.1: version "2.4.1" @@ -13377,7 +13763,7 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-asn1@^5.0.0, parse-asn1@^5.1.5: +parse-asn1@^5.0.0: version "5.1.6" resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz" integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== @@ -13388,6 +13774,18 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" +parse-asn1@^5.1.7: + version "5.1.7" + resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz#73cdaaa822125f9647165625eb45f8a051d2df06" + integrity sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg== + dependencies: + asn1.js "^4.10.1" + browserify-aes "^1.2.0" + evp_bytestokey "^1.0.3" + hash-base "~3.0" + pbkdf2 "^3.1.2" + safe-buffer "^5.2.1" + parse-filepath@^1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz" @@ -13462,10 +13860,10 @@ pascalcase@^0.1.1: resolved "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -patch-package@7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/patch-package/-/patch-package-7.0.0.tgz" - integrity sha512-eYunHbnnB2ghjTNc5iL1Uo7TsGMuXk0vibX3RFcE/CdVdXzmdbMsG/4K4IgoSuIkLTI5oHrMQk4+NkFqSed0BQ== +patch-package@7.0.2: + version "7.0.2" + resolved "https://registry.npmjs.org/patch-package/-/patch-package-7.0.2.tgz#c01589bb6964854b5210506a5845d47900641f5a" + integrity sha512-PMYfL8LXxGIRmxXLqlEaBxzKPu7/SdP13ld6GSfAUJUZRmBDPp8chZs0dpzaAFn9TSPnFiMwkC6PJt6pBiAl8Q== dependencies: "@yarnpkg/lockfile" "^1.1.0" chalk "^4.1.2" @@ -13477,7 +13875,7 @@ patch-package@7.0.0: minimist "^1.2.6" open "^7.4.2" rimraf "^2.6.3" - semver "^5.6.0" + semver "^7.5.3" slash "^2.0.0" tmp "^0.0.33" yaml "^2.2.2" @@ -13598,7 +13996,7 @@ pathval@^1.1.1: resolved "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -pbkdf2@^3.0.3: +pbkdf2@^3.0.3, pbkdf2@^3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== @@ -13673,10 +14071,10 @@ pirates@^4.0.1: dependencies: node-modules-regexp "^1.0.0" -pirates@^4.0.5: - version "4.0.5" - resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz" - integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== +pirates@^4.0.6: + version "4.0.6" + resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== "pkg-dir@< 6 >= 5": version "5.0.0" @@ -13732,6 +14130,11 @@ posix-character-classes@^0.1.0: resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= +possible-typed-array-names@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" + integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== + postcss@^7.0.16: version "7.0.36" resolved "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz" @@ -13860,9 +14263,9 @@ proto3-json-serializer@^1.0.0: dependencies: protobufjs "^6.11.3" -protobufjs@6.11.3, protobufjs@^6.11.3: +protobufjs@6.11.3: version "6.11.3" - resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz#637a527205a35caa4f3e2a9a4a13ddffe0e7af74" integrity sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg== dependencies: "@protobufjs/aspromise" "^1.1.2" @@ -13879,10 +14282,10 @@ protobufjs@6.11.3, protobufjs@^6.11.3: "@types/node" ">=13.7.0" long "^4.0.0" -protobufjs@7.2.4, protobufjs@^7.2.4: - version "7.2.4" - resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz" - integrity sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ== +protobufjs@7.2.6, protobufjs@^7.2.4: + version "7.2.6" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz#4a0ccd79eb292717aacf07530a07e0ed20278215" + integrity sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -13897,6 +14300,25 @@ protobufjs@7.2.4, protobufjs@^7.2.4: "@types/node" ">=13.7.0" long "^5.0.0" +protobufjs@^6.11.3: + version "6.11.4" + resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz#29a412c38bf70d89e537b6d02d904a6f448173aa" + integrity sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw== + 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" + protocols@^1.1.0, protocols@^1.4.0: version "1.4.8" resolved "https://registry.npmjs.org/protocols/-/protocols-1.4.8.tgz" @@ -14128,10 +14550,10 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" -raw-body@2.5.1: - version "2.5.1" - resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: bytes "3.1.2" http-errors "2.0.0" @@ -14326,6 +14748,19 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^2.3.8: + version "2.3.8" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + 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" + readable-stream@^4.0.0: version "4.4.0" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.0.tgz" @@ -14442,6 +14877,16 @@ regexp.prototype.flags@^1.4.1: define-properties "^1.1.3" functions-have-names "^1.2.2" +regexp.prototype.flags@^1.5.2: + version "1.5.2" + resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" + integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== + dependencies: + call-bind "^1.0.6" + define-properties "^1.2.1" + es-errors "^1.3.0" + set-function-name "^2.0.1" + regexpp@^3.1.0: version "3.2.0" resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" @@ -14667,12 +15112,12 @@ resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.17. is-core-module "^2.2.0" path-parse "^1.0.6" -resolve@^1.22.0, resolve@~1.22.0: - version "1.22.0" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== +resolve@^1.22.0, resolve@^1.22.4: + version "1.22.8" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== dependencies: - is-core-module "^2.8.1" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -14683,6 +15128,15 @@ resolve@~1.17.0: dependencies: path-parse "^1.0.6" +resolve@~1.22.0: + version "1.22.0" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@~1.22.1: version "1.22.4" resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz" @@ -14777,10 +15231,10 @@ rollup-plugin-copy-assets@2.0.3: dependencies: fs-extra "^7.0.1" -rollup-plugin-copy@3.4.0: - version "3.4.0" - resolved "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz" - integrity sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ== +rollup-plugin-copy@3.5.0: + version "3.5.0" + resolved "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.5.0.tgz#7ffa2a7a8303e143876fa64fb5eed9022d304eeb" + integrity sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA== dependencies: "@types/fs-extra" "^8.0.1" colorette "^1.1.0" @@ -14788,14 +15242,14 @@ rollup-plugin-copy@3.4.0: globby "10.0.1" is-plain-object "^3.0.0" -rollup-plugin-dts@5.3.0: - version "5.3.0" - resolved "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-5.3.0.tgz" - integrity sha512-8FXp0ZkyZj1iU5klkIJYLjIq/YZSwBoERu33QBDxm/1yw5UU4txrEtcmMkrq+ZiKu3Q4qvPCNqc3ovX6rjqzbQ== +rollup-plugin-dts@5.3.1: + version "5.3.1" + resolved "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-5.3.1.tgz#c2841269a3a5cb986b7791b0328e6a178eba108f" + integrity sha512-gusMi+Z4gY/JaEQeXnB0RUdU82h1kF0WYzCWgVmV4p3hWXqelaKuCvcJawfeg+EKn2T1Ie+YWF2OiN1/L8bTVg== dependencies: - magic-string "^0.30.0" + magic-string "^0.30.2" optionalDependencies: - "@babel/code-frame" "^7.18.6" + "@babel/code-frame" "^7.22.5" rollup-plugin-license@3.0.1: version "3.0.1" @@ -14920,6 +15374,16 @@ rxjs@^7.5.5: dependencies: tslib "^2.1.0" +safe-array-concat@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" + integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== + dependencies: + call-bind "^1.0.7" + get-intrinsic "^1.2.4" + has-symbols "^1.0.3" + isarray "^2.0.5" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" @@ -14930,6 +15394,15 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-regex-test@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" + integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-regex "^1.1.4" + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz" @@ -15065,51 +15538,32 @@ semver-greatest-satisfied-range@^1.1.0: resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@7.3.8: - version "7.3.8" - resolved "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== +semver@7.5.3: + version "7.5.3" + resolved "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" + integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^6.3.1: +semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@~7.3.0: - version "7.3.5" - resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== +semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@~7.5.4: + version "7.5.4" + resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" -semver@^7.3.7: +semver@~7.3.0: version "7.3.7" resolved "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz" integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== dependencies: lru-cache "^6.0.0" -semver@^7.3.8: - version "7.5.0" - resolved "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz" - integrity sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA== - dependencies: - lru-cache "^6.0.0" - -semver@^7.5.3, semver@~7.5.4: - version "7.5.4" - resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" - send@0.17.1: version "0.17.1" resolved "https://registry.npmjs.org/send/-/send-0.17.1.tgz" @@ -15192,10 +15646,27 @@ set-blocking@^2.0.0, set-blocking@~2.0.0: resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -set-immediate-shim@~1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz" - integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +set-function-name@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.2" set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" @@ -15262,9 +15733,9 @@ shebang-regex@^3.0.0: integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shell-quote@^1.6.1: - version "1.7.2" - resolved "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz" - integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== + version "1.8.1" + resolved "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== shelljs@^0.8.3: version "0.8.4" @@ -15294,10 +15765,10 @@ signal-exit@^3.0.7: resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -simple-git@3.19.1: - version "3.19.1" - resolved "https://registry.npmjs.org/simple-git/-/simple-git-3.19.1.tgz" - integrity sha512-Ck+rcjVaE1HotraRAS8u/+xgTvToTuoMkT9/l9lvuP5jftwnYUp6DwuJzsKErHgfyRk8IB8pqGHWEbM3tLgV1w== +simple-git@3.24.0: + version "3.24.0" + resolved "https://registry.npmjs.org/simple-git/-/simple-git-3.24.0.tgz#33a8c88dc6fa74e53eaf3d6bfc27d0182a49ec00" + integrity sha512-QqAKee9Twv+3k8IFOFfPB2hnk6as6Y6ACUpwCtQvRYBAes23Wv3SZlHVobAzqcE8gfsisCvPw3HGW3HYM+VYYw== dependencies: "@kwsites/file-exists" "^1.1.1" "@kwsites/promise-deferred" "^1.1.1" @@ -15337,6 +15808,11 @@ slash@^3.0.0: resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + slice-ansi@0.0.4: version "0.0.4" resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz" @@ -15537,7 +16013,7 @@ source-map-url@^0.4.0: resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz" integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== -source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3: +source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3: version "0.5.7" resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -15552,6 +16028,11 @@ source-map@^0.7.3, source-map@~0.7.2: resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== +source-map@^0.7.4: + version "0.7.4" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + sourcemap-codec@^1.4.4, sourcemap-codec@^1.4.8: version "1.4.8" resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" @@ -15865,6 +16346,16 @@ string.prototype.padend@^3.0.0: define-properties "^1.1.3" es-abstract "^1.18.0-next.2" +string.prototype.trim@^1.2.9: + version "1.2.9" + resolved "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" + integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.0" + es-object-atoms "^1.0.0" + string.prototype.trimend@^1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz" @@ -15882,6 +16373,15 @@ string.prototype.trimend@^1.0.5: define-properties "^1.1.4" es-abstract "^1.19.5" +string.prototype.trimend@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" + integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + string.prototype.trimstart@^1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz" @@ -15899,6 +16399,15 @@ string.prototype.trimstart@^1.0.5: define-properties "^1.1.4" es-abstract "^1.19.5" +string.prototype.trimstart@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" + integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" @@ -16025,7 +16534,7 @@ superstatic@^9.0.3: optionalDependencies: re2 "^1.17.7" -supports-color@8.1.1, supports-color@^8.0.0, supports-color@^8.1.1: +supports-color@8.1.1, supports-color@^8.0.0, supports-color@^8.1.1, supports-color@~8.1.1: version "8.1.1" resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -16100,11 +16609,6 @@ table@^6.0.9: string-width "^4.2.0" strip-ansi "^6.0.0" -tapable@^1.0.0: - version "1.1.3" - resolved "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz" - integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== - tapable@^2.1.1, tapable@^2.2.0: version "2.2.1" resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" @@ -16158,7 +16662,7 @@ tar@^6.0.2, tar@^6.1.0, tar@^6.1.11, tar@^6.1.2: mkdirp "^1.0.3" yallist "^4.0.0" -tcp-port-used@^1.0.1, tcp-port-used@^1.0.2: +tcp-port-used@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz" integrity sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA== @@ -16481,16 +16985,16 @@ ts-essentials@9.3.0: resolved "https://registry.npmjs.org/ts-essentials/-/ts-essentials-9.3.0.tgz" integrity sha512-XeiCboEyBG8UqXZtXl59bWEi4ZgOqRsogFDI6WDGIF1LmzbYiAkIwjkXN6zZWWl4re/lsOqMlYfe8KA0XiiEPw== -ts-loader@8.4.0: - version "8.4.0" - resolved "https://registry.npmjs.org/ts-loader/-/ts-loader-8.4.0.tgz" - integrity sha512-6nFY3IZ2//mrPc+ImY3hNWx1vCHyEhl6V+wLmL4CZcm6g1CqX7UKrkc6y0i4FwcfOhxyMPCfaEvh20f4r9GNpw== +ts-loader@9.5.1: + version "9.5.1" + resolved "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz#63d5912a86312f1fbe32cef0859fb8b2193d9b89" + integrity sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg== dependencies: chalk "^4.1.0" - enhanced-resolve "^4.0.0" - loader-utils "^2.0.0" + enhanced-resolve "^5.0.0" micromatch "^4.0.0" semver "^7.3.4" + source-map "^0.7.4" ts-node@10.9.1: version "10.9.1" @@ -16512,12 +17016,12 @@ ts-node@10.9.1: yn "3.1.1" tsconfig-paths@^3.14.1: - version "3.14.1" - resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz" - integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== + version "3.15.0" + resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== dependencies: "@types/json5" "^0.0.29" - json5 "^1.0.1" + json5 "^1.0.2" minimist "^1.2.6" strip-bom "^3.0.0" @@ -16618,7 +17122,7 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5, type-detect@^4.0.8: +type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.8: 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== @@ -16686,6 +17190,55 @@ type@^2.5.0: resolved "https://registry.npmjs.org/type/-/type-2.5.0.tgz" integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== +type@^2.7.2: + version "2.7.2" + resolved "https://registry.npmjs.org/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== + +typed-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" + integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + is-typed-array "^1.1.13" + +typed-array-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" + integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + +typed-array-byte-offset@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" + integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + +typed-array-length@^1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" + integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" @@ -16760,9 +17313,9 @@ typeson@7.0.2, typeson@^7.0.1: integrity sha512-Rc/BXqUq+pgAc9D3Na+A2iiTlenfzZW9VA2H9DzpYWKOqUMwUaLyu6OQWXCIEiFs1AQ6Fssbed1/subMY/cEag== ua-parser-js@^0.7.30: - version "0.7.31" - resolved "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz" - integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ== + version "0.7.37" + resolved "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.37.tgz#e464e66dac2d33a7a1251d7d7a99d6157ec27832" + integrity sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA== uglify-js@^3.1.4, uglify-js@^3.4.9: version "3.14.2" @@ -16835,10 +17388,10 @@ undici-types@~5.26.4: resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== -undici@5.26.5: - version "5.26.5" - resolved "https://registry.npmjs.org/undici/-/undici-5.26.5.tgz#f6dc8c565e3cad8c4475b187f51a13e505092838" - integrity sha512-cSb4bPFd5qgR7qr2jYAi0hlX9n5YKK2ONKkLFkxl+v/9BvC0sOpZjBHDBSXc5lWAf5ty9oZdRXytBIHzgUcerw== +undici@5.28.4: + version "5.28.4" + resolved "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068" + integrity sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g== dependencies: "@fastify/busboy" "^2.0.0" @@ -16994,6 +17547,14 @@ update-browserslist-db@^1.0.11: escalade "^3.1.1" picocolors "^1.0.0" +update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + update-notifier-cjs@^5.1.6: version "5.1.6" resolved "https://registry.npmjs.org/update-notifier-cjs/-/update-notifier-cjs-5.1.6.tgz" @@ -17203,14 +17764,7 @@ vinyl-sourcemap@^1.1.0: remove-bom-buffer "^3.0.0" vinyl "^2.0.0" -vinyl-sourcemaps-apply@^0.2.0: - version "0.2.1" - resolved "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz" - integrity sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU= - dependencies: - source-map "^0.5.1" - -vinyl@2.x, vinyl@^2.0.0, vinyl@^2.1.0, vinyl@^2.2.1: +vinyl@^2.0.0, vinyl@^2.1.0, vinyl@^2.2.1: version "2.2.1" resolved "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz" integrity sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw== @@ -17510,6 +18064,17 @@ which-pm@2.0.0: load-yaml-file "^0.2.0" path-exists "^4.0.0" +which-typed-array@^1.1.14, which-typed-array@^1.1.15: + version "1.1.15" + resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" + integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.2" + which-typed-array@^1.1.2: version "1.1.7" resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz" @@ -17536,6 +18101,13 @@ which@^1.2.1, which@^1.2.14, which@^1.2.9, which@^1.3.1: dependencies: isexe "^2.0.0" +which@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/which/-/which-3.0.1.tgz#89f1cd0c23f629a8105ffe69b8172791c87b4be1" + integrity sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg== + dependencies: + isexe "^2.0.0" + wide-align@^1.1.0: version "1.1.3" resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz"