diff --git a/.github/resources/integ-service-account.json.gpg b/.github/resources/integ-service-account.json.gpg
index 7740dccd8b..5a52805c9a 100644
Binary files a/.github/resources/integ-service-account.json.gpg and b/.github/resources/integ-service-account.json.gpg differ
diff --git a/.github/scripts/publish_preflight_check.sh b/.github/scripts/publish_preflight_check.sh
index d52b49a531..3aabd70b58 100755
--- a/.github/scripts/publish_preflight_check.sh
+++ b/.github/scripts/publish_preflight_check.sh
@@ -146,8 +146,8 @@ echo_info "Generating changelog"
echo_info "--------------------------------------------"
echo_info ""
-echo_info "---< git fetch origin master --prune --unshallow >---"
-git fetch origin master --prune --unshallow
+echo_info "---< git fetch origin main --prune --unshallow >---"
+git fetch origin main --prune --unshallow
echo ""
echo_info "Generating changelog from history..."
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ba8a5896b2..36bf48432f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,9 +12,9 @@ jobs:
node-version: [18.x, 20.x, 22.x, 24.x]
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Set up Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v4
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ matrix.node-version }}
- name: Install and build
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index 277f1449e4..8f4e36bbfb 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -29,12 +29,12 @@ jobs:
steps:
- name: Checkout source for staging
- uses: actions/checkout@v4
+ uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
ref: ${{ github.event.client_payload.ref || github.ref }}
- name: Set up Node.js
- uses: actions/setup-node@v4
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 18.x
@@ -72,7 +72,7 @@ jobs:
# Attach the packaged artifacts to the workflow output. These can be manually
# downloaded for later inspection if necessary.
- name: Archive artifacts
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: dist
path: dist
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0589a5f669..88bf8a28ba 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -15,10 +15,18 @@
name: Release Candidate
on:
- # Only run the workflow when a PR is updated or when a developer explicitly requests
- # a build by sending a 'firebase_build' event.
+ # Run the workflow when:
+ # 1. A PR is created or updated (staging checks).
+ # 2. A commit is pushed to main (release publication).
+ # 3. A developer explicitly requests a build via 'firebase_build' event.
pull_request:
- types: [opened, synchronize, closed]
+ types: [opened, synchronize]
+
+ push:
+ branches:
+ - main
+ paths:
+ - 'package.json'
repository_dispatch:
types:
@@ -26,26 +34,22 @@ on:
jobs:
stage_release:
- # To publish a release, merge the release PR with the label 'release:publish'.
+ # To publish a release, merge a PR with the title prefix '[chore] Release ' to main
+ # and ensure the squashed commit message also has the prefix.
# To stage a release without publishing it, send a 'firebase_build' event or apply
# the 'release:stage' label to a PR.
if: github.event.action == 'firebase_build' ||
contains(github.event.pull_request.labels.*.name, 'release:stage') ||
- (github.event.pull_request.merged &&
- contains(github.event.pull_request.labels.*.name, 'release:publish'))
+ (github.event_name == 'push' && startsWith(github.event.head_commit.message, '[chore] Release '))
runs-on: ubuntu-latest
- # When manually triggering the build, the requester can specify a target branch or a tag
- # via the 'ref' client parameter.
steps:
- name: Checkout source for staging
- uses: actions/checkout@v4
- with:
- ref: ${{ github.event.client_payload.ref || github.ref }}
+ uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Set up Node.js
- uses: actions/setup-node@v4
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 18.x
@@ -77,7 +81,7 @@ jobs:
# Attach the packaged artifacts to the workflow output. These can be manually
# downloaded for later inspection if necessary.
- name: Archive artifacts
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: dist
path: dist
@@ -90,34 +94,33 @@ jobs:
publish_release:
needs: stage_release
- # Check whether the release should be published. We publish only when the trigger PR is
- # 1. merged
- # 2. to the master branch
- # 3. with the label 'release:publish', and
- # 4. the title prefix '[chore] Release '.
- if: github.event.pull_request.merged &&
- github.ref == 'refs/heads/master' &&
- contains(github.event.pull_request.labels.*.name, 'release:publish') &&
- startsWith(github.event.pull_request.title, '[chore] Release ')
+ # Check whether the release should be published. We publish only when the trigger is
+ # 1. a push (merge)
+ # 2. to the main branch
+ # 3. and the commit message has the title prefix '[chore] Release '.
+ if: github.event_name == 'push' &&
+ github.ref == 'refs/heads/main' &&
+ startsWith(github.event.head_commit.message, '[chore] Release ')
runs-on: ubuntu-latest
+ environment: Release
permissions:
contents: write
steps:
- name: Checkout source for publish
- uses: actions/checkout@v4
+ uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
# Download the artifacts created by the stage_release job.
- name: Download release candidates
- uses: actions/download-artifact@v4.1.7
+ uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: dist
path: dist
# Node.js and NPM are needed to complete the publish.
- name: Set up Node.js
- uses: actions/setup-node@v4
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 18.x
@@ -129,27 +132,15 @@ jobs:
- name: Create release tag
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: gh release create ${{ steps.preflight.outputs.version }}
- --title "Firebase Admin Node.js SDK ${{ steps.preflight.outputs.version }}"
- --notes '${{ steps.preflight.outputs.changelog }}'
+ RELEASE_VER: ${{ steps.preflight.outputs.version }}
+ RELEASE_BODY: ${{ steps.preflight.outputs.changelog }}
+ run: |
+ gh release create "$RELEASE_VER" \
+ --title "Firebase Admin Node.js SDK $RELEASE_VER" \
+ --notes "$RELEASE_BODY"
- name: Publish to NPM
run: ./.github/scripts/publish_package.sh
env:
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
VERSION: ${{ steps.preflight.outputs.version }}
-
- # Post to Twitter if explicitly opted-in by adding the label 'release:tweet'.
- - name: Post to Twitter
- if: success() &&
- contains(github.event.pull_request.labels.*.name, 'release:tweet')
- uses: ./.github/actions/send-tweet
- with:
- status: >
- ${{ steps.preflight.outputs.version }} of @Firebase Admin Node.js SDK is available.
- https://github.com/firebase/firebase-admin-node/releases/tag/${{ steps.preflight.outputs.version }}
- consumer-key: ${{ secrets.TWITTER_CONSUMER_KEY }}
- consumer-secret: ${{ secrets.TWITTER_CONSUMER_SECRET }}
- access-token: ${{ secrets.TWITTER_ACCESS_TOKEN }}
- access-token-secret: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }}
- continue-on-error: true
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4a7df3f715..8f9d80ec69 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -47,7 +47,7 @@ Great, we love hearing how we can improve our products! Share you idea through o
## Want to submit a pull request?
Sweet, we'd love to accept your contribution!
-[Open a new pull request](https://github.com/firebase/firebase-admin-node/pull/new/master) and fill
+[Open a new pull request](https://github.com/firebase/firebase-admin-node/pull/new/main) and fill
out the provided template.
**If you want to implement a new feature, please open an issue with a proposal first so that we can
diff --git a/package-lock.json b/package-lock.json
index 3826e45eb1..b7b1f0ff1a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "firebase-admin",
- "version": "13.5.0",
+ "version": "13.6.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "firebase-admin",
- "version": "13.5.0",
+ "version": "13.6.1",
"license": "Apache-2.0",
"dependencies": {
"@fastify/busboy": "^3.0.0",
@@ -27,7 +27,7 @@
"@firebase/auth-compat": "^0.6.0",
"@firebase/auth-types": "^0.13.0",
"@microsoft/api-extractor": "^7.11.2",
- "@types/bcrypt": "^5.0.0",
+ "@types/bcrypt": "^6.0.0",
"@types/chai": "^4.0.0",
"@types/chai-as-promised": "^7.1.0",
"@types/firebase-token-generator": "^2.0.28",
@@ -43,7 +43,7 @@
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^7.16.1",
"@typescript-eslint/parser": "^7.16.1",
- "bcrypt": "^5.0.0",
+ "bcrypt": "^6.0.0",
"chai": "^4.2.0",
"chai-as-promised": "^7.0.0",
"chai-exclude": "^2.1.0",
@@ -1280,27 +1280,6 @@
"url": "https://opencollective.com/js-sdsl"
}
},
- "node_modules/@mapbox/node-pre-gyp": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
- "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "detect-libc": "^2.0.0",
- "https-proxy-agent": "^5.0.0",
- "make-dir": "^3.1.0",
- "node-fetch": "^2.6.7",
- "nopt": "^5.0.0",
- "npmlog": "^5.0.1",
- "rimraf": "^3.0.2",
- "semver": "^7.3.5",
- "tar": "^6.1.11"
- },
- "bin": {
- "node-pre-gyp": "bin/node-pre-gyp"
- }
- },
"node_modules/@microsoft/api-extractor": {
"version": "7.52.10",
"resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.52.10.tgz",
@@ -2026,9 +2005,9 @@
"license": "MIT"
},
"node_modules/@types/bcrypt": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz",
- "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-6.0.0.tgz",
+ "integrity": "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2529,13 +2508,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/abbrev": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
- "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@@ -2589,8 +2561,8 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
- "devOptional": true,
"license": "MIT",
+ "optional": true,
"dependencies": {
"debug": "4"
},
@@ -2925,13 +2897,6 @@
"node": ">=8"
}
},
- "node_modules/aproba": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
- "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/archy": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
@@ -2939,21 +2904,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/are-we-there-yet": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
- "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
- "deprecated": "This package is no longer supported.",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "delegates": "^1.0.0",
- "readable-stream": "^3.6.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
@@ -3282,18 +3232,18 @@
"license": "MIT"
},
"node_modules/bcrypt": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz",
- "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz",
+ "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
- "@mapbox/node-pre-gyp": "^1.0.11",
- "node-addon-api": "^5.0.0"
+ "node-addon-api": "^8.3.0",
+ "node-gyp-build": "^4.8.4"
},
"engines": {
- "node": ">= 10.0.0"
+ "node": ">= 18"
}
},
"node_modules/bcrypt-pbkdf": {
@@ -3727,16 +3677,6 @@
"node": ">= 6"
}
},
- "node_modules/chownr": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
- "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/clean-stack": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@@ -3971,13 +3911,6 @@
"source-map": "^0.6.1"
}
},
- "node_modules/console-control-strings": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
- "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/convert-source-map": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
@@ -4223,13 +4156,6 @@
"node": ">=0.4.0"
}
},
- "node_modules/delegates": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
- "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/detect-file": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
@@ -4240,16 +4166,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/detect-libc": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
- "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/diff": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
@@ -5331,39 +5247,6 @@
"node": ">=6 <7 || >=8"
}
},
- "node_modules/fs-minipass": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
- "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/fs-minipass/node_modules/minipass": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
- "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/fs-minipass/node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/fs-mkdirp-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz",
@@ -5446,28 +5329,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/gauge": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
- "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
- "deprecated": "This package is no longer supported.",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "aproba": "^1.0.3 || ^2.0.0",
- "color-support": "^1.1.2",
- "console-control-strings": "^1.0.0",
- "has-unicode": "^2.0.1",
- "object-assign": "^4.1.1",
- "signal-exit": "^3.0.0",
- "string-width": "^4.2.3",
- "strip-ansi": "^6.0.1",
- "wide-align": "^1.1.2"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/gaxios": {
"version": "6.7.1",
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz",
@@ -5650,10 +5511,11 @@
}
},
"node_modules/glob": {
- "version": "10.4.5",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
- "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
@@ -6546,13 +6408,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/has-unicode": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
- "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/hasha": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
@@ -6708,8 +6563,8 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
- "devOptional": true,
"license": "MIT",
+ "optional": true,
"dependencies": {
"agent-base": "6",
"debug": "4"
@@ -7734,23 +7589,23 @@
}
},
"node_modules/jsonwebtoken/node_modules/jwa": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
- "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz",
+ "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==",
"license": "MIT",
"dependencies": {
- "buffer-equal-constant-time": "1.0.1",
+ "buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jsonwebtoken/node_modules/jws": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
- "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz",
+ "integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==",
"license": "MIT",
"dependencies": {
- "jwa": "^1.4.1",
+ "jwa": "^1.4.2",
"safe-buffer": "^5.0.1"
}
},
@@ -7778,12 +7633,12 @@
"license": "MIT"
},
"node_modules/jwa": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
- "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
+ "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
"license": "MIT",
"dependencies": {
- "buffer-equal-constant-time": "1.0.1",
+ "buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
@@ -7815,12 +7670,12 @@
}
},
"node_modules/jws": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
- "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
+ "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
"license": "MIT",
"dependencies": {
- "jwa": "^2.0.0",
+ "jwa": "^2.0.1",
"safe-buffer": "^5.0.1"
}
},
@@ -7991,9 +7846,9 @@
}
},
"node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "version": "4.17.23",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
+ "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
"dev": true,
"license": "MIT"
},
@@ -8343,58 +8198,12 @@
"node": ">=8"
}
},
- "node_modules/minizlib": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
- "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "minipass": "^3.0.0",
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/minizlib/node_modules/minipass": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
- "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/minizlib/node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "mkdirp": "bin/cmd.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/mocha": {
- "version": "11.7.1",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.1.tgz",
- "integrity": "sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A==",
+ "version": "11.7.5",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz",
+ "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"browser-stdout": "^1.3.1",
"chokidar": "^4.0.1",
@@ -8404,6 +8213,7 @@
"find-up": "^5.0.0",
"glob": "^10.4.5",
"he": "^1.2.0",
+ "is-path-inside": "^3.0.3",
"js-yaml": "^4.1.0",
"log-symbols": "^4.1.0",
"minimatch": "^9.0.5",
@@ -8596,11 +8406,14 @@
}
},
"node_modules/node-addon-api": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz",
- "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==",
+ "version": "8.5.0",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz",
+ "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": "^18 || ^20 || >= 21"
+ }
},
"node_modules/node-fetch": {
"version": "2.7.0",
@@ -8623,14 +8436,26 @@
}
},
"node_modules/node-forge": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
- "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz",
+ "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==",
"license": "(BSD-3-Clause OR GPL-2.0)",
"engines": {
"node": ">= 6.13.0"
}
},
+ "node_modules/node-gyp-build": {
+ "version": "4.8.4",
+ "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
+ "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "node-gyp-build": "bin.js",
+ "node-gyp-build-optional": "optional.js",
+ "node-gyp-build-test": "build-test.js"
+ }
+ },
"node_modules/node-preload": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
@@ -8661,22 +8486,6 @@
"node": ">=6.0.0"
}
},
- "node_modules/nopt": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
- "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "abbrev": "1"
- },
- "bin": {
- "nopt": "bin/nopt.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/normalize-package-data": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
@@ -8887,20 +8696,6 @@
"node": ">=4"
}
},
- "node_modules/npmlog": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
- "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
- "deprecated": "This package is no longer supported.",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "are-we-there-yet": "^2.0.0",
- "console-control-strings": "^1.1.0",
- "gauge": "^3.0.0",
- "set-blocking": "^2.0.0"
- }
- },
"node_modules/nyc": {
"version": "17.1.0",
"resolved": "https://registry.npmjs.org/nyc/-/nyc-17.1.0.tgz",
@@ -11335,31 +11130,6 @@
"semver": "bin/semver.js"
}
},
- "node_modules/tar": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
- "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "chownr": "^2.0.0",
- "fs-minipass": "^2.0.0",
- "minipass": "^5.0.0",
- "minizlib": "^2.1.1",
- "mkdirp": "^1.0.3",
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/tar/node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/teeny-request": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz",
@@ -12329,16 +12099,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/wide-align": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
- "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "string-width": "^1.0.2 || 2 || 3 || 4"
- }
- },
"node_modules/word-wrap": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
diff --git a/package.json b/package.json
index 721ff00c9f..cef227703a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "firebase-admin",
- "version": "13.6.0",
+ "version": "13.6.1",
"description": "Firebase admin SDK for Node.js",
"author": "Firebase (https://firebase.google.com/)",
"license": "Apache-2.0",
@@ -228,7 +228,7 @@
"@firebase/auth-compat": "^0.6.0",
"@firebase/auth-types": "^0.13.0",
"@microsoft/api-extractor": "^7.11.2",
- "@types/bcrypt": "^5.0.0",
+ "@types/bcrypt": "^6.0.0",
"@types/chai": "^4.0.0",
"@types/chai-as-promised": "^7.1.0",
"@types/firebase-token-generator": "^2.0.28",
@@ -244,7 +244,7 @@
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^7.16.1",
"@typescript-eslint/parser": "^7.16.1",
- "bcrypt": "^5.0.0",
+ "bcrypt": "^6.0.0",
"chai": "^4.2.0",
"chai-as-promised": "^7.0.0",
"chai-exclude": "^2.1.0",
diff --git a/src/data-connect/data-connect-api-client-internal.ts b/src/data-connect/data-connect-api-client-internal.ts
index 28284db6a4..6292d023aa 100644
--- a/src/data-connect/data-connect-api-client-internal.ts
+++ b/src/data-connect/data-connect-api-client-internal.ts
@@ -413,10 +413,7 @@ export class DataConnectApiClient {
*/
private objectToString(data: unknown): string {
if (typeof data === 'string') {
- const escapedString = data
- .replace(/\\/g, '\\\\') // Replace \ with \\
- .replace(/"/g, '\\"'); // Replace " with \"
- return `"${escapedString}"`;
+ return JSON.stringify(data);
}
if (typeof data === 'number' || typeof data === 'boolean' || data === null) {
return String(data);
diff --git a/src/utils/validator.ts b/src/utils/validator.ts
index fb738904e1..15b2f53e68 100644
--- a/src/utils/validator.ts
+++ b/src/utils/validator.ts
@@ -15,8 +15,6 @@
* limitations under the License.
*/
-import url = require('url');
-
/**
* Validates that a value is a byte buffer.
*
@@ -234,33 +232,38 @@ export function isURL(urlStr: any): boolean {
return false;
}
try {
- const uri = url.parse(urlStr);
+ const uri = new URL(urlStr);
const scheme = uri.protocol;
- const slashes = uri.slashes;
- const hostname = uri.hostname;
- const pathname = uri.pathname;
- if ((scheme !== 'http:' && scheme !== 'https:') || !slashes) {
+ if (scheme !== 'http:' && scheme !== 'https:') {
return false;
}
- // Validate hostname: Can contain letters, numbers, underscore and dashes separated by a dot.
- // Each zone must not start with a hyphen or underscore.
- if (!hostname || !/^[a-zA-Z0-9]+[\w-]*([.]?[a-zA-Z0-9]+[\w-]*)*$/.test(hostname)) {
- return false;
+ const hostname = uri.hostname;
+ // Validate hostname strictly to match previous behavior and prevent weak/invalid domains.
+ // Must be alphanumeric with optional dashes/underscores, separated by dots.
+ // Cannot start/end with dot or dash (mostly).
+ // This regex is safe (no nested quantifiers with overlap).
+ if (!/^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*$/.test(hostname)) {
+ // Check for IPv6 literals which are valid but behave differently.
+ // Node 'new URL' keeps brackets for IPv6: [::1] -> [::1]
+ // Check for IPv6 address (simple check for brackets)
+ if (!/^\[[a-fA-F0-9:.]+\]$/.test(hostname)) {
+ return false;
+ }
}
- // Allow for pathnames: (/chars+)*/?
+ // Restore strict pathname validation: (/chars+)*/?
// Where chars can be a combination of: a-z A-Z 0-9 - _ . ~ ! $ & ' ( ) * + , ; = : @ %
const pathnameRe = /^(\/[\w\-.~!$'()*+,;=:@%]+)*\/?$/;
// Validate pathname.
+ const pathname = uri.pathname;
if (pathname &&
- pathname !== '/' &&
- !pathnameRe.test(pathname)) {
+ pathname !== '/' &&
+ !pathnameRe.test(pathname)) {
return false;
}
- // Allow any query string and hash as long as no invalid character is used.
+ return true;
} catch (e) {
return false;
}
- return true;
}
diff --git a/test/unit/data-connect/data-connect-api-client-internal.spec.ts b/test/unit/data-connect/data-connect-api-client-internal.spec.ts
index 628608a9e9..7dc20080b1 100644
--- a/test/unit/data-connect/data-connect-api-client-internal.spec.ts
+++ b/test/unit/data-connect/data-connect-api-client-internal.spec.ts
@@ -928,4 +928,61 @@ describe('DataConnectApiClient CRUD helpers', () => {
.to.be.rejectedWith(FirebaseDataConnectError, `${serverErrorString}. ${additionalErrorMessageForBulkImport}`);
});
});
+
+ describe('String serialization', () => {
+ it('should correctly escape special characters in strings during insert', async () => {
+ const data = {
+ content: 'Line 1\nLine 2',
+ };
+
+ await apiClient.insert(tableName, data);
+ const callArgs = executeGraphqlStub.firstCall.args[0];
+
+ expect(callArgs).to.include(String.raw`content: "Line 1\nLine 2"`);
+ });
+
+ it('should correctly escape backslash', async () => {
+ const data = {
+ content: 'Backslash \\',
+ };
+
+ await apiClient.insert(tableName, data);
+ const callArgs = executeGraphqlStub.firstCall.args[0];
+
+ expect(callArgs).to.include(String.raw`content: "Backslash \\"`);
+ });
+
+ it('should correctly escape double quotes', async () => {
+ const data = {
+ content: 'Quote "test"',
+ };
+
+ await apiClient.insert(tableName, data);
+ const callArgs = executeGraphqlStub.firstCall.args[0];
+
+ expect(callArgs).to.include(String.raw`content: "Quote \"test\""`);
+ });
+
+ it('should correctly escape tab character', async () => {
+ const data = {
+ content: 'Tab\tCharacter',
+ };
+
+ await apiClient.insert(tableName, data);
+ const callArgs = executeGraphqlStub.firstCall.args[0];
+
+ expect(callArgs).to.include(String.raw`content: "Tab\tCharacter"`);
+ });
+
+ it('should correctly handle emojis', async () => {
+ const data = {
+ content: 'Emoji 😊',
+ };
+
+ await apiClient.insert(tableName, data);
+ const callArgs = executeGraphqlStub.firstCall.args[0];
+
+ expect(callArgs).to.include('content: "Emoji 😊"');
+ });
+ });
});
diff --git a/test/unit/data-connect/validate-admin-args.spec.ts b/test/unit/data-connect/validate-admin-args.spec.ts
index 0d940d5144..7c60718838 100644
--- a/test/unit/data-connect/validate-admin-args.spec.ts
+++ b/test/unit/data-connect/validate-admin-args.spec.ts
@@ -179,25 +179,33 @@ describe('validateAdminArgs()', () => {
describe('and validateVars = true', () => {
describe('should succeed if vars WERE provided', () => {
it('and the first argument is a DataConnect instance', () => {
+ let dcInstance, inputVars, inputOpts;
expect(() => {
- const { dc: dcInstance, vars: inputVars, options: inputOpts } = validateAdminArgs(
+ const parsedArgs = validateAdminArgs(
connectorConfig, providedDcInstance, variables, undefined, true, true
);
- expect(dcInstance).to.deep.equal(providedDcInstance);
- expect(inputVars).to.deep.equal(variables);
- expect(inputOpts).to.be.undefined;
- }).to.not.throw(invalidVariablesError);
+ dcInstance = parsedArgs.dc;
+ inputVars = parsedArgs.vars;
+ inputOpts = parsedArgs.options;
+ }).to.not.throw(invalidVariablesError);
+ expect(dcInstance).to.deep.equal(providedDcInstance);
+ expect(inputVars).to.deep.equal(variables);
+ expect(inputOpts).to.be.undefined;
});
it('and the first argument is variables instance', () => {
+ let dcInstance, inputVars, inputOpts;
expect(() => {
- const { dc: dcInstance, vars: inputVars, options: inputOpts } = validateAdminArgs(
+ const parsedArgs = validateAdminArgs(
connectorConfig, variables, undefined, undefined, true, true
);
- expect(dcInstance).to.deep.equal(stubDcInstance);
- expect(inputVars).to.deep.equal(variables);
- expect(inputOpts).to.be.undefined;
+ dcInstance = parsedArgs.dc;
+ inputVars = parsedArgs.vars;
+ inputOpts = parsedArgs.options;
}).to.not.throw(invalidVariablesError);
+ expect(dcInstance).to.deep.equal(stubDcInstance);
+ expect(inputVars).to.deep.equal(variables);
+ expect(inputOpts).to.be.undefined;
});
});
@@ -219,14 +227,18 @@ describe('validateAdminArgs()', () => {
describe('and validateVars = false', () => {
describe('should succeed if vars WERE provided', () => {
it('and the first argument is a DataConnect instance', () => {
+ let dcInstance, inputVars, inputOpts;
expect(() => {
- const { dc: dcInstance, vars: inputVars, options: inputOpts } = validateAdminArgs(
+ const parsedArgs = validateAdminArgs(
connectorConfig, providedDcInstance, variables, undefined, true, false
);
- expect(dcInstance).to.deep.equal(providedDcInstance);
- expect(inputVars).to.be.undefined;
- expect(inputOpts).to.be.undefined;
+ dcInstance = parsedArgs.dc;
+ inputVars = parsedArgs.vars;
+ inputOpts = parsedArgs.options;
}).to.not.throw(invalidVariablesError);
+ expect(dcInstance).to.deep.equal(providedDcInstance);
+ expect(inputVars).to.deep.equal(variables);
+ expect(inputOpts).to.be.undefined;
});
it('and the first argument is variables instance', () => {
@@ -245,25 +257,33 @@ describe('validateAdminArgs()', () => {
describe('should succeed if vars were NOT provided', () => {
it('and the first argument is a DataConnect instance', () => {
+ let dcInstance, inputVars, inputOpts;
expect(() => {
- const { dc: dcInstance, vars: inputVars, options: inputOpts } = validateAdminArgs(
+ const parsedArgs = validateAdminArgs(
connectorConfig, providedDcInstance, undefined, undefined, true, false
);
- expect(dcInstance).to.deep.equal(providedDcInstance);
- expect(inputVars).to.deep.equal(variables);
- expect(inputOpts).to.be.undefined;
+ dcInstance = parsedArgs.dc;
+ inputVars = parsedArgs.vars;
+ inputOpts = parsedArgs.options;
}).to.not.throw(invalidVariablesError);
+ expect(dcInstance).to.deep.equal(providedDcInstance);
+ expect(inputVars).to.be.undefined;
+ expect(inputOpts).to.be.undefined;
});
it('and the first argument is undefined variables', () => {
+ let dcInstance, inputVars, inputOpts;
expect(() => {
- const { dc: dcInstance, vars: inputVars, options: inputOpts } = validateAdminArgs(
+ const parsedArgs = validateAdminArgs(
connectorConfig, undefined, undefined, undefined, true, false
);
- expect(dcInstance).to.deep.equal(stubDcInstance);
- expect(inputVars).to.be.undefined;
- expect(inputOpts).to.be.undefined;
+ dcInstance = parsedArgs.dc;
+ inputVars = parsedArgs.vars;
+ inputOpts = parsedArgs.options;
}).to.not.throw(invalidVariablesError);
+ expect(dcInstance).to.deep.equal(stubDcInstance);
+ expect(inputVars).to.be.undefined;
+ expect(inputOpts).to.be.undefined;
});
});
});